]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sg: fix dxferp in from_to case
authorDouglas Gilbert <dgilbert@interlog.com>
Thu, 3 Mar 2016 05:31:29 +0000 (00:31 -0500)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 26 May 2016 22:46:23 +0000 (15:46 -0700)
Orabug: 23331104

[ Upstream commit 5ecee0a3ee8d74b6950cb41e8989b0c2174568d4 ]

One of the strange things that the original sg driver did was let the
user provide both a data-out buffer (it followed the sg_header+cdb)
_and_ specify a reply length greater than zero. What happened was that
the user data-out buffer was copied into some kernel buffers and then
the mid level was told a read type operation would take place with the
data from the device overwriting the same kernel buffers. The user would
then read those kernel buffers back into the user space.

From what I can tell, the above action was broken by commit fad7f01e61bf
("sg: set dxferp to NULL for READ with the older SG interface") in 2008
and syzkaller found that out recently.

Make sure that a user space pointer is passed through when data follows
the sg_header structure and command.  Fix the abnormal case when a
non-zero reply_len is also given.

Fixes: fad7f01e61bf737fe8a3740d803f000db57ecac6
Cc: <stable@vger.kernel.org> #v2.6.28+
Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Ewan Milne <emilne@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
(cherry picked from commit 685a50b681ddd07ff2b7714797b5793adcc691e7)

Signed-off-by: Dan Duval <dan.duval@oracle.com>
drivers/scsi/sg.c

index 3bbf4853733cd53defe053f2c47cd6ab2a7ad7e9..ec192939750e048c524dca362bf8910993f77f35 100644 (file)
@@ -652,7 +652,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
        else
                hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE;
        hp->dxfer_len = mxsize;
-       if (hp->dxfer_direction == SG_DXFER_TO_DEV)
+       if ((hp->dxfer_direction == SG_DXFER_TO_DEV) ||
+           (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV))
                hp->dxferp = (char __user *)buf + cmd_size;
        else
                hp->dxferp = NULL;