]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi sg: remove incorrect scsi command checking logic
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Jul 2018 00:02:17 +0000 (17:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 11 Jul 2018 00:02:17 +0000 (17:02 -0700)
The SCSI_IOCTL_SEND_COMMAND ioctl has interesting scsi command
"security" checking.

If the file was opened read-only (but only in that case), it will
fetch the first byte of the command from user space, and do
"sg_allow_access()" on it.  That, in turn, will check that
"blk_verify_command()" is ok with that command byte.

If that passes, it will then do call "sg_scsi_ioctl()" to execute
the command.

This is entirely nonsensical for several reasons.

It's nonsensical simply because it's racy: after it copies the command
byte from user mode to check it, user mode could just change the byte
before it is actually submitted later by "sg_scsi_ioctl()".

But it is nonsensical also because "sg_scsi_ioctl()" itself already does
blk_verify_command() on the command properly after it has been copied
from user space.

So it is an incorrect implementation of a pointless check. Remove it.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/scsi/sg.c

index cd2fdac000c9e23fbf1df8cca453f30379b22d66..4f3450793273a0f8eb789331c970a96efaf57bb1 100644 (file)
@@ -1103,15 +1103,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
        case SCSI_IOCTL_SEND_COMMAND:
                if (atomic_read(&sdp->detaching))
                        return -ENODEV;
-               if (read_only) {
-                       unsigned char opcode = WRITE_6;
-                       Scsi_Ioctl_Command __user *siocp = p;
-
-                       if (copy_from_user(&opcode, siocp->data, 1))
-                               return -EFAULT;
-                       if (sg_allow_access(filp, &opcode))
-                               return -EPERM;
-               }
                return sg_scsi_ioctl(sdp->device->request_queue, NULL, filp->f_mode, p);
        case SG_SET_DEBUG:
                result = get_user(val, ip);