]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/block-take-care-not-to-overflow-when-calculating-total-iov-length.patch
fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / block-take-care-not-to-overflow-when-calculating-total-iov-length.patch
CommitLineData
d476d390
GKH
1From 9f864c80913467312c7b8690e41fb5ebd1b50e92 Mon Sep 17 00:00:00 2001
2From: Jens Axboe <jaxboe@fusionio.com>
3Date: Fri, 29 Oct 2010 11:31:42 -0600
4Subject: block: take care not to overflow when calculating total iov length
5
6From: Jens Axboe <jaxboe@fusionio.com>
7
8commit 9f864c80913467312c7b8690e41fb5ebd1b50e92 upstream.
9
10Reported-by: Dan Rosenberg <drosenberg@vsecurity.com>
11Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
12Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
13
14---
15 block/scsi_ioctl.c | 34 ++++++++++++++++++++++++----------
16 1 file changed, 24 insertions(+), 10 deletions(-)
17
18--- a/block/scsi_ioctl.c
19+++ b/block/scsi_ioctl.c
20@@ -321,33 +321,47 @@ static int sg_io(struct request_queue *q
21 if (hdr->iovec_count) {
22 const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
23 size_t iov_data_len;
24- struct sg_iovec *iov;
25+ struct sg_iovec *sg_iov;
26+ struct iovec *iov;
27+ int i;
28
29- iov = kmalloc(size, GFP_KERNEL);
30- if (!iov) {
31+ sg_iov = kmalloc(size, GFP_KERNEL);
32+ if (!sg_iov) {
33 ret = -ENOMEM;
34 goto out;
35 }
36
37- if (copy_from_user(iov, hdr->dxferp, size)) {
38- kfree(iov);
39+ if (copy_from_user(sg_iov, hdr->dxferp, size)) {
40+ kfree(sg_iov);
41 ret = -EFAULT;
42 goto out;
43 }
44
45+ /*
46+ * Sum up the vecs, making sure they don't overflow
47+ */
48+ iov = (struct iovec *) sg_iov;
49+ iov_data_len = 0;
50+ for (i = 0; i < hdr->iovec_count; i++) {
51+ if (iov_data_len + iov[i].iov_len < iov_data_len) {
52+ kfree(sg_iov);
53+ ret = -EINVAL;
54+ goto out;
55+ }
56+ iov_data_len += iov[i].iov_len;
57+ }
58+
59 /* SG_IO howto says that the shorter of the two wins */
60- iov_data_len = iov_length((struct iovec *)iov,
61- hdr->iovec_count);
62 if (hdr->dxfer_len < iov_data_len) {
63- hdr->iovec_count = iov_shorten((struct iovec *)iov,
64+ hdr->iovec_count = iov_shorten(iov,
65 hdr->iovec_count,
66 hdr->dxfer_len);
67 iov_data_len = hdr->dxfer_len;
68 }
69
70- ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count,
71+ ret = blk_rq_map_user_iov(q, rq, NULL, sg_iov, hdr->iovec_count,
72 iov_data_len, GFP_KERNEL);
73- kfree(iov);
74+ kfree(sg_iov);
75 } else if (hdr->dxfer_len)
76 ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
77 GFP_KERNEL);