History

compat_ioctl: reimplement SG_IO handling

There are two code locations that implement the SG_IO ioctl: the old sg.c driver, and the generic scsi_ioctl helper that is in turn used by multiple drivers. To eradicate the old compat_ioctl conversion handler for the SG_IO command, I implement a readable pair of put_sg_io_hdr() /get_sg_io_hdr() helper functions that can be used for both compat and native mode, and then I call this from both drivers. For the iovec handling, there is already a compat_import_iovec() function that can simply be called in place of import_iovec(). To avoid having to pass the compat/native state through multiple indirections, I mark the SG_IO command itself as compatible in fs/compat_ioctl.c and use in_compat_syscall() to figure out where we are called from. As a side-effect of this, the sg.c driver now also accepts the 32-bit sg_io_hdr format in compat mode using the read/write interface, not just ioctl. This should improve compatiblity with old 32-bit binaries, but it would break if any application intentionally passes the 64-bit data structure in compat mode here. Steffen Maier helped debug an issue in an earlier version of this patch.

Arnd Bergmann committed 7 years ago

Commit 98aaaec1 parent b6dfb245 files · +143 −159Browse files

Showing the changes to include/linux/blkdev.h (1 of 5 files). Show all

Unified · Split

include/linux/blkdev.h+2−0
@@ -870,6 +870,8 @@ extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, · 869 unmodified lines
870 unsigned int, void __user *);870 unsigned int, void __user *);
871extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,871extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
872 struct scsi_ioctl_command __user *);872 struct scsi_ioctl_command __user *);
873extern int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp);
874extern int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp);
873 875
874extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags);876extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags);
875extern void blk_queue_exit(struct request_queue *q);877extern void blk_queue_exit(struct request_queue *q);