git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
sg: Fix double-free when drives detach during SG_IO
[pandora-kernel.git]
/
drivers
/
scsi
/
sg.c
diff --git
a/drivers/scsi/sg.c
b/drivers/scsi/sg.c
index
441a1c5
..
94b71b4
100644
(file)
--- a/
drivers/scsi/sg.c
+++ b/
drivers/scsi/sg.c
@@
-498,7
+498,7
@@
static ssize_t
sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
{
sg_io_hdr_t *hp = &srp->header;
sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
{
sg_io_hdr_t *hp = &srp->header;
- int err = 0;
+ int err = 0
, err2
;
int len;
if (count < SZ_SG_IO_HDR) {
int len;
if (count < SZ_SG_IO_HDR) {
@@
-527,8
+527,8
@@
sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
goto err_out;
}
err_out:
goto err_out;
}
err_out:
- err = sg_finish_rem_req(srp);
- return
(0 == err) ? count : err
;
+ err
2
= sg_finish_rem_req(srp);
+ return
err ? : err2 ? : count
;
}
static ssize_t
}
static ssize_t
@@
-609,7
+609,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;
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;
hp->dxferp = (char __user *)buf + cmd_size;
else
hp->dxferp = NULL;
@@
-741,8
+742,11
@@
sg_common_write(Sg_fd * sfp, Sg_request * srp,
return k; /* probably out of space --> ENOMEM */
}
if (sdp->detached) {
return k; /* probably out of space --> ENOMEM */
}
if (sdp->detached) {
- if (srp->bio)
+ if (srp->bio)
{
blk_end_request_all(srp->rq, -EIO);
blk_end_request_all(srp->rq, -EIO);
+ srp->rq = NULL;
+ }
+
sg_finish_rem_req(srp);
return -ENODEV;
}
sg_finish_rem_req(srp);
return -ENODEV;
}
@@
-1687,6
+1691,9
@@
static int sg_start_req(Sg_request *srp, unsigned char *cmd)
md->from_user = 0;
}
md->from_user = 0;
}
+ if (unlikely(iov_count > UIO_MAXIOV))
+ return -EINVAL;
+
if (iov_count) {
int len, size = sizeof(struct sg_iovec) * iov_count;
struct iovec *iov;
if (iov_count) {
int len, size = sizeof(struct sg_iovec) * iov_count;
struct iovec *iov;