]> git.ipfire.org Git - people/ms/linux.git/blobdiff - block/scsi_ioctl.c
Importing "grsecurity-3.1-3.19.2-201503201903.patch"
[people/ms/linux.git] / block / scsi_ioctl.c
index 28163fad3c5d8800661e2b2c8868300a99e162c2..07190a06c7816415b3821e35c34a677a25833124 100644 (file)
@@ -67,7 +67,7 @@ static int scsi_get_bus(struct request_queue *q, int __user *p)
        return put_user(0, p);
 }
 
-static int sg_get_timeout(struct request_queue *q)
+static int __intentional_overflow(-1) sg_get_timeout(struct request_queue *q)
 {
        return jiffies_to_clock_t(q->sg_timeout);
 }
@@ -227,8 +227,20 @@ EXPORT_SYMBOL(blk_verify_command);
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
                             struct sg_io_hdr *hdr, fmode_t mode)
 {
-       if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
+       unsigned char tmpcmd[sizeof(rq->__cmd)];
+       unsigned char *cmdptr;
+
+       if (rq->cmd != rq->__cmd)
+               cmdptr = rq->cmd;
+       else
+               cmdptr = tmpcmd;
+
+       if (copy_from_user(cmdptr, hdr->cmdp, hdr->cmd_len))
                return -EFAULT;
+
+       if (cmdptr != rq->cmd)
+               memcpy(rq->cmd, cmdptr, hdr->cmd_len);
+
        if (blk_verify_command(rq->cmd, mode & FMODE_WRITE))
                return -EPERM;
 
@@ -431,6 +443,8 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
        int err;
        unsigned int in_len, out_len, bytes, opcode, cmdlen;
        char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
+       unsigned char tmpcmd[sizeof(rq->__cmd)];
+       unsigned char *cmdptr;
 
        if (!sic)
                return -EINVAL;
@@ -469,9 +483,18 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
         */
        err = -EFAULT;
        rq->cmd_len = cmdlen;
-       if (copy_from_user(rq->cmd, sic->data, cmdlen))
+
+       if (rq->cmd != rq->__cmd)
+               cmdptr = rq->cmd;
+       else
+               cmdptr = tmpcmd;
+
+       if (copy_from_user(cmdptr, sic->data, cmdlen))
                goto error;
 
+       if (rq->cmd != cmdptr)
+               memcpy(rq->cmd, cmdptr, cmdlen);
+
        if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
                goto error;