Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

compat_ioctl: scsi: handle HDIO commands from drivers

The ata_sas_scsi_ioctl() function implements a number of HDIO_* commands
for SCSI devices, it is used by all libata drivers as well as a few
drivers that support SAS attached SATA drives.

The only command that is not safe for compat ioctls here is
HDIO_GET_32BIT. Change the implementation to check for in_compat_syscall()
in order to do both cases correctly, and change all callers to use it
as both native and compat callback pointers, including the indirect
callers through sas_ioctl and ata_scsi_ioctl.

Reviewed-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+39
+9
drivers/ata/libata-scsi.c
··· 17 17 * - http://www.t13.org/ 18 18 */ 19 19 20 + #include <linux/compat.h> 20 21 #include <linux/slab.h> 21 22 #include <linux/kernel.h> 22 23 #include <linux/blkdev.h> ··· 762 761 return 0; 763 762 } 764 763 764 + /* 765 + * This handles both native and compat commands, so anything added 766 + * here must have a compatible argument, or check in_compat_syscall() 767 + */ 765 768 int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, 766 769 unsigned int cmd, void __user *arg) 767 770 { ··· 778 773 spin_lock_irqsave(ap->lock, flags); 779 774 val = ata_ioc32(ap); 780 775 spin_unlock_irqrestore(ap->lock, flags); 776 + #ifdef CONFIG_COMPAT 777 + if (in_compat_syscall()) 778 + return put_user(val, (compat_ulong_t __user *)arg); 779 + #endif 781 780 return put_user(val, (unsigned long __user *)arg); 782 781 783 782 case HDIO_SET_32BIT:
+3
drivers/scsi/aic94xx/aic94xx_init.c
··· 54 54 .eh_target_reset_handler = sas_eh_target_reset_handler, 55 55 .target_destroy = sas_target_destroy, 56 56 .ioctl = sas_ioctl, 57 + #ifdef CONFIG_COMPAT 58 + .compat_ioctl = sas_ioctl, 59 + #endif 57 60 .track_queue_depth = 1, 58 61 }; 59 62
+3
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
··· 1772 1772 .eh_target_reset_handler = sas_eh_target_reset_handler, 1773 1773 .target_destroy = sas_target_destroy, 1774 1774 .ioctl = sas_ioctl, 1775 + #ifdef CONFIG_COMPAT 1776 + .compat_ioctl = sas_ioctl, 1777 + #endif 1775 1778 .shost_attrs = host_attrs_v1_hw, 1776 1779 .host_reset = hisi_sas_host_reset, 1777 1780 };
+3
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
··· 3551 3551 .eh_target_reset_handler = sas_eh_target_reset_handler, 3552 3552 .target_destroy = sas_target_destroy, 3553 3553 .ioctl = sas_ioctl, 3554 + #ifdef CONFIG_COMPAT 3555 + .compat_ioctl = sas_ioctl, 3556 + #endif 3554 3557 .shost_attrs = host_attrs_v2_hw, 3555 3558 .host_reset = hisi_sas_host_reset, 3556 3559 };
+3
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
··· 3075 3075 .eh_target_reset_handler = sas_eh_target_reset_handler, 3076 3076 .target_destroy = sas_target_destroy, 3077 3077 .ioctl = sas_ioctl, 3078 + #ifdef CONFIG_COMPAT 3079 + .compat_ioctl = sas_ioctl, 3080 + #endif 3078 3081 .shost_attrs = host_attrs_v3_hw, 3079 3082 .tag_alloc_policy = BLK_TAG_ALLOC_RR, 3080 3083 .host_reset = hisi_sas_host_reset,
+3
drivers/scsi/ipr.c
··· 6727 6727 .name = "IPR", 6728 6728 .info = ipr_ioa_info, 6729 6729 .ioctl = ipr_ioctl, 6730 + #ifdef CONFIG_COMPAT 6731 + .compat_ioctl = ipr_ioctl, 6732 + #endif 6730 6733 .queuecommand = ipr_queuecommand, 6731 6734 .eh_abort_handler = ipr_eh_abort, 6732 6735 .eh_device_reset_handler = ipr_eh_dev_reset,
+3
drivers/scsi/isci/init.c
··· 168 168 .eh_target_reset_handler = sas_eh_target_reset_handler, 169 169 .target_destroy = sas_target_destroy, 170 170 .ioctl = sas_ioctl, 171 + #ifdef CONFIG_COMPAT 172 + .compat_ioctl = sas_ioctl, 173 + #endif 171 174 .shost_attrs = isci_host_attrs, 172 175 .track_queue_depth = 1, 173 176 };
+3
drivers/scsi/mvsas/mv_init.c
··· 47 47 .eh_target_reset_handler = sas_eh_target_reset_handler, 48 48 .target_destroy = sas_target_destroy, 49 49 .ioctl = sas_ioctl, 50 + #ifdef CONFIG_COMPAT 51 + .compat_ioctl = sas_ioctl, 52 + #endif 50 53 .shost_attrs = mvst_host_attrs, 51 54 .track_queue_depth = 1, 52 55 };
+3
drivers/scsi/pm8001/pm8001_init.c
··· 101 101 .eh_target_reset_handler = sas_eh_target_reset_handler, 102 102 .target_destroy = sas_target_destroy, 103 103 .ioctl = sas_ioctl, 104 + #ifdef CONFIG_COMPAT 105 + .compat_ioctl = sas_ioctl, 106 + #endif 104 107 .shost_attrs = pm8001_host_attrs, 105 108 .track_queue_depth = 1, 106 109 };
+6
include/linux/libata.h
··· 1109 1109 extern int ata_scsi_detect(struct scsi_host_template *sht); 1110 1110 extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd, 1111 1111 void __user *arg); 1112 + #ifdef CONFIG_COMPAT 1113 + #define ATA_SCSI_COMPAT_IOCTL .compat_ioctl = ata_scsi_ioctl, 1114 + #else 1115 + #define ATA_SCSI_COMPAT_IOCTL /* empty */ 1116 + #endif 1112 1117 extern int ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd); 1113 1118 extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev, 1114 1119 unsigned int cmd, void __user *arg); ··· 1346 1341 .module = THIS_MODULE, \ 1347 1342 .name = drv_name, \ 1348 1343 .ioctl = ata_scsi_ioctl, \ 1344 + ATA_SCSI_COMPAT_IOCTL \ 1349 1345 .queuecommand = ata_scsi_queuecmd, \ 1350 1346 .can_queue = ATA_DEF_QUEUE, \ 1351 1347 .tag_alloc_policy = BLK_TAG_ALLOC_RR, \