From: Greg Kroah-Hartman Date: Fri, 22 Sep 2017 11:18:17 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v3.18.72~15 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=116e97ee6b2d3fe79aa66c441ca8633db6f59cfe;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: scsi-qla2xxx-fix-an-integer-overflow-in-sysfs-code.patch scsi-sg-factor-out-sg_fill_request_table.patch scsi-sg-fixup-infoleak-when-using-sg_get_request_table.patch scsi-sg-off-by-one-in-sg_ioctl.patch scsi-sg-remove-save_scat_len.patch scsi-sg-use-standard-lists-for-sg_requests.patch --- diff --git a/queue-3.18/scsi-qla2xxx-fix-an-integer-overflow-in-sysfs-code.patch b/queue-3.18/scsi-qla2xxx-fix-an-integer-overflow-in-sysfs-code.patch new file mode 100644 index 00000000000..d896f21b781 --- /dev/null +++ b/queue-3.18/scsi-qla2xxx-fix-an-integer-overflow-in-sysfs-code.patch @@ -0,0 +1,62 @@ +From e6f77540c067b48dee10f1e33678415bfcc89017 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 30 Aug 2017 16:30:35 +0300 +Subject: scsi: qla2xxx: Fix an integer overflow in sysfs code + +From: Dan Carpenter + +commit e6f77540c067b48dee10f1e33678415bfcc89017 upstream. + +The value of "size" comes from the user. When we add "start + size" it +could lead to an integer overflow bug. + +It means we vmalloc() a lot more memory than we had intended. I believe +that on 64 bit systems vmalloc() can succeed even if we ask it to +allocate huge 4GB buffers. So we would get memory corruption and likely +a crash when we call ha->isp_ops->write_optrom() and ->read_optrom(). + +Only root can trigger this bug. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=194061 + +Fixes: b7cc176c9eb3 ("[SCSI] qla2xxx: Allow region-based flash-part accesses.") +Reported-by: shqking +Signed-off-by: Dan Carpenter +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_attr.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -404,6 +404,8 @@ qla2x00_sysfs_write_optrom_ctl(struct fi + return -EINVAL; + if (start > ha->optrom_size) + return -EINVAL; ++ if (size > ha->optrom_size - start) ++ size = ha->optrom_size - start; + + mutex_lock(&ha->optrom_mutex); + switch (val) { +@@ -429,8 +431,7 @@ qla2x00_sysfs_write_optrom_ctl(struct fi + } + + ha->optrom_region_start = start; +- ha->optrom_region_size = start + size > ha->optrom_size ? +- ha->optrom_size - start : size; ++ ha->optrom_region_size = start + size; + + ha->optrom_state = QLA_SREADING; + ha->optrom_buffer = vmalloc(ha->optrom_region_size); +@@ -503,8 +504,7 @@ qla2x00_sysfs_write_optrom_ctl(struct fi + } + + ha->optrom_region_start = start; +- ha->optrom_region_size = start + size > ha->optrom_size ? +- ha->optrom_size - start : size; ++ ha->optrom_region_size = start + size; + + ha->optrom_state = QLA_SWRITING; + ha->optrom_buffer = vmalloc(ha->optrom_region_size); diff --git a/queue-3.18/scsi-sg-factor-out-sg_fill_request_table.patch b/queue-3.18/scsi-sg-factor-out-sg_fill_request_table.patch new file mode 100644 index 00000000000..b4475fb7ca9 --- /dev/null +++ b/queue-3.18/scsi-sg-factor-out-sg_fill_request_table.patch @@ -0,0 +1,106 @@ +From 4759df905a474d245752c9dc94288e779b8734dd Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 15 Sep 2017 14:05:15 +0200 +Subject: scsi: sg: factor out sg_fill_request_table() + +From: Hannes Reinecke + +commit 4759df905a474d245752c9dc94288e779b8734dd upstream. + +Factor out sg_fill_request_table() for better readability. + +[mkp: typos, applied by hand] + +Signed-off-by: Hannes Reinecke +Reviewed-by: Bart Van Assche +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 61 ++++++++++++++++++++++++++++++------------------------ + 1 file changed, 35 insertions(+), 26 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -854,6 +854,40 @@ static int max_sectors_bytes(struct requ + return max_sectors << 9; + } + ++static void ++sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo) ++{ ++ Sg_request *srp; ++ int val; ++ unsigned int ms; ++ ++ val = 0; ++ list_for_each_entry(srp, &sfp->rq_list, entry) { ++ if (val > SG_MAX_QUEUE) ++ break; ++ memset(&rinfo[val], 0, SZ_SG_REQ_INFO); ++ rinfo[val].req_state = srp->done + 1; ++ rinfo[val].problem = ++ srp->header.masked_status & ++ srp->header.host_status & ++ srp->header.driver_status; ++ if (srp->done) ++ rinfo[val].duration = ++ srp->header.duration; ++ else { ++ ms = jiffies_to_msecs(jiffies); ++ rinfo[val].duration = ++ (ms > srp->header.duration) ? ++ (ms - srp->header.duration) : 0; ++ } ++ rinfo[val].orphan = srp->orphan; ++ rinfo[val].sg_io_owned = srp->sg_io_owned; ++ rinfo[val].pack_id = srp->header.pack_id; ++ rinfo[val].usr_ptr = srp->header.usr_ptr; ++ val++; ++ } ++} ++ + static long + sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + { +@@ -1047,38 +1081,13 @@ sg_ioctl(struct file *filp, unsigned int + return -EFAULT; + else { + sg_req_info_t *rinfo; +- unsigned int ms; + + rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE, + GFP_KERNEL); + if (!rinfo) + return -ENOMEM; + read_lock_irqsave(&sfp->rq_list_lock, iflags); +- val = 0; +- list_for_each_entry(srp, &sfp->rq_list, entry) { +- if (val >= SG_MAX_QUEUE) +- break; +- memset(&rinfo[val], 0, SZ_SG_REQ_INFO); +- rinfo[val].req_state = srp->done + 1; +- rinfo[val].problem = +- srp->header.masked_status & +- srp->header.host_status & +- srp->header.driver_status; +- if (srp->done) +- rinfo[val].duration = +- srp->header.duration; +- else { +- ms = jiffies_to_msecs(jiffies); +- rinfo[val].duration = +- (ms > srp->header.duration) ? +- (ms - srp->header.duration) : 0; +- } +- rinfo[val].orphan = srp->orphan; +- rinfo[val].sg_io_owned = srp->sg_io_owned; +- rinfo[val].pack_id = srp->header.pack_id; +- rinfo[val].usr_ptr = srp->header.usr_ptr; +- val++; +- } ++ sg_fill_request_table(sfp, rinfo); + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); + result = __copy_to_user(p, rinfo, + SZ_SG_REQ_INFO * SG_MAX_QUEUE); diff --git a/queue-3.18/scsi-sg-fixup-infoleak-when-using-sg_get_request_table.patch b/queue-3.18/scsi-sg-fixup-infoleak-when-using-sg_get_request_table.patch new file mode 100644 index 00000000000..bf3ff6ff998 --- /dev/null +++ b/queue-3.18/scsi-sg-fixup-infoleak-when-using-sg_get_request_table.patch @@ -0,0 +1,46 @@ +From 3e0097499839e0fe3af380410eababe5a47c4cf9 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 15 Sep 2017 14:05:16 +0200 +Subject: scsi: sg: fixup infoleak when using SG_GET_REQUEST_TABLE + +From: Hannes Reinecke + +commit 3e0097499839e0fe3af380410eababe5a47c4cf9 upstream. + +When calling SG_GET_REQUEST_TABLE ioctl only a half-filled table is +returned; the remaining part will then contain stale kernel memory +information. This patch zeroes out the entire table to avoid this +issue. + +Signed-off-by: Hannes Reinecke +Reviewed-by: Bart Van Assche +Reviewed-by: Christoph Hellwig +Reviewed-by: Eric Dumazet +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -865,7 +865,6 @@ sg_fill_request_table(Sg_fd *sfp, sg_req + list_for_each_entry(srp, &sfp->rq_list, entry) { + if (val > SG_MAX_QUEUE) + break; +- memset(&rinfo[val], 0, SZ_SG_REQ_INFO); + rinfo[val].req_state = srp->done + 1; + rinfo[val].problem = + srp->header.masked_status & +@@ -1082,8 +1081,8 @@ sg_ioctl(struct file *filp, unsigned int + else { + sg_req_info_t *rinfo; + +- rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE, +- GFP_KERNEL); ++ rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE, ++ GFP_KERNEL); + if (!rinfo) + return -ENOMEM; + read_lock_irqsave(&sfp->rq_list_lock, iflags); diff --git a/queue-3.18/scsi-sg-off-by-one-in-sg_ioctl.patch b/queue-3.18/scsi-sg-off-by-one-in-sg_ioctl.patch new file mode 100644 index 00000000000..5642c64ae24 --- /dev/null +++ b/queue-3.18/scsi-sg-off-by-one-in-sg_ioctl.patch @@ -0,0 +1,33 @@ +From bd46fc406b30d1db1aff8dabaff8d18bb423fdcf Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Thu, 17 Aug 2017 10:09:54 +0300 +Subject: scsi: sg: off by one in sg_ioctl() + +From: Dan Carpenter + +commit bd46fc406b30d1db1aff8dabaff8d18bb423fdcf upstream. + +If "val" is SG_MAX_QUEUE then we are one element beyond the end of the +"rinfo" array so the > should be >=. + +Fixes: 109bade9c625 ("scsi: sg: use standard lists for sg_requests") +Signed-off-by: Dan Carpenter +Acked-by: Douglas Gilbert +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1056,7 +1056,7 @@ sg_ioctl(struct file *filp, unsigned int + read_lock_irqsave(&sfp->rq_list_lock, iflags); + val = 0; + list_for_each_entry(srp, &sfp->rq_list, entry) { +- if (val > SG_MAX_QUEUE) ++ if (val >= SG_MAX_QUEUE) + break; + memset(&rinfo[val], 0, SZ_SG_REQ_INFO); + rinfo[val].req_state = srp->done + 1; diff --git a/queue-3.18/scsi-sg-remove-save_scat_len.patch b/queue-3.18/scsi-sg-remove-save_scat_len.patch new file mode 100644 index 00000000000..e6b6376f5ec --- /dev/null +++ b/queue-3.18/scsi-sg-remove-save_scat_len.patch @@ -0,0 +1,40 @@ +From 136e57bf43dc4babbfb8783abbf707d483cacbe3 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 7 Apr 2017 09:34:13 +0200 +Subject: scsi: sg: remove 'save_scat_len' + +From: Hannes Reinecke + +commit 136e57bf43dc4babbfb8783abbf707d483cacbe3 upstream. + +Unused. + +Signed-off-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Tested-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -157,7 +157,6 @@ typedef struct sg_fd { /* holds the sta + int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ + int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */ + Sg_scatter_hold reserve; /* buffer held for this file descriptor */ +- unsigned save_scat_len; /* original length of trunc. scat. element */ + Sg_request *headrp; /* head of request slist, NULL->empty */ + struct fasync_struct *async_qp; /* used by asynchronous notification */ + Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */ +@@ -2105,7 +2104,6 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_reques + req_schp->pages = NULL; + req_schp->page_order = 0; + req_schp->sglist_len = 0; +- sfp->save_scat_len = 0; + srp->res_used = 0; + /* Called without mutex lock to avoid deadlock */ + sfp->res_in_use = 0; diff --git a/queue-3.18/scsi-sg-use-standard-lists-for-sg_requests.patch b/queue-3.18/scsi-sg-use-standard-lists-for-sg_requests.patch new file mode 100644 index 00000000000..fe1b41858cc --- /dev/null +++ b/queue-3.18/scsi-sg-use-standard-lists-for-sg_requests.patch @@ -0,0 +1,290 @@ +From 109bade9c625c89bb5ea753aaa1a0a97e6fbb548 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 7 Apr 2017 09:34:16 +0200 +Subject: scsi: sg: use standard lists for sg_requests + +From: Hannes Reinecke + +commit 109bade9c625c89bb5ea753aaa1a0a97e6fbb548 upstream. + +'Sg_request' is using a private list implementation; convert it to +standard lists. + +Signed-off-by: Hannes Reinecke +Reviewed-by: Johannes Thumshirn +Tested-by: Johannes Thumshirn +Reviewed-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sg.c | 147 ++++++++++++++++++++++-------------------------------- + 1 file changed, 61 insertions(+), 86 deletions(-) + +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -133,7 +133,7 @@ struct sg_device; /* forward declaratio + struct sg_fd; + + typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ +- struct sg_request *nextrp; /* NULL -> tail request (slist) */ ++ struct list_head entry; /* list entry */ + struct sg_fd *parentfp; /* NULL -> not in use */ + Sg_scatter_hold data; /* hold buffer, perhaps scatter list */ + sg_io_hdr_t header; /* scsi command+info, see */ +@@ -157,7 +157,7 @@ typedef struct sg_fd { /* holds the sta + int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ + int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */ + Sg_scatter_hold reserve; /* buffer held for this file descriptor */ +- Sg_request *headrp; /* head of request slist, NULL->empty */ ++ struct list_head rq_list; /* head of request list */ + struct fasync_struct *async_qp; /* used by asynchronous notification */ + Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */ + char low_dma; /* as in parent but possibly overridden to 1 */ +@@ -965,7 +965,7 @@ sg_ioctl(struct file *filp, unsigned int + if (!access_ok(VERIFY_WRITE, ip, sizeof (int))) + return -EFAULT; + read_lock_irqsave(&sfp->rq_list_lock, iflags); +- for (srp = sfp->headrp; srp; srp = srp->nextrp) { ++ list_for_each_entry(srp, &sfp->rq_list, entry) { + if ((1 == srp->done) && (!srp->sg_io_owned)) { + read_unlock_irqrestore(&sfp->rq_list_lock, + iflags); +@@ -978,7 +978,8 @@ sg_ioctl(struct file *filp, unsigned int + return 0; + case SG_GET_NUM_WAITING: + read_lock_irqsave(&sfp->rq_list_lock, iflags); +- for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) { ++ val = 0; ++ list_for_each_entry(srp, &sfp->rq_list, entry) { + if ((1 == srp->done) && (!srp->sg_io_owned)) + ++val; + } +@@ -1053,35 +1054,33 @@ sg_ioctl(struct file *filp, unsigned int + if (!rinfo) + return -ENOMEM; + read_lock_irqsave(&sfp->rq_list_lock, iflags); +- for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE; +- ++val, srp = srp ? srp->nextrp : srp) { ++ val = 0; ++ list_for_each_entry(srp, &sfp->rq_list, entry) { ++ if (val > SG_MAX_QUEUE) ++ break; + memset(&rinfo[val], 0, SZ_SG_REQ_INFO); +- if (srp) { +- rinfo[val].req_state = srp->done + 1; +- rinfo[val].problem = +- srp->header.masked_status & +- srp->header.host_status & +- srp->header.driver_status; +- if (srp->done) +- rinfo[val].duration = +- srp->header.duration; +- else { +- ms = jiffies_to_msecs(jiffies); +- rinfo[val].duration = +- (ms > srp->header.duration) ? +- (ms - srp->header.duration) : 0; +- } +- rinfo[val].orphan = srp->orphan; +- rinfo[val].sg_io_owned = +- srp->sg_io_owned; +- rinfo[val].pack_id = +- srp->header.pack_id; +- rinfo[val].usr_ptr = +- srp->header.usr_ptr; ++ rinfo[val].req_state = srp->done + 1; ++ rinfo[val].problem = ++ srp->header.masked_status & ++ srp->header.host_status & ++ srp->header.driver_status; ++ if (srp->done) ++ rinfo[val].duration = ++ srp->header.duration; ++ else { ++ ms = jiffies_to_msecs(jiffies); ++ rinfo[val].duration = ++ (ms > srp->header.duration) ? ++ (ms - srp->header.duration) : 0; + } ++ rinfo[val].orphan = srp->orphan; ++ rinfo[val].sg_io_owned = srp->sg_io_owned; ++ rinfo[val].pack_id = srp->header.pack_id; ++ rinfo[val].usr_ptr = srp->header.usr_ptr; ++ val++; + } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); +- result = __copy_to_user(p, rinfo, ++ result = __copy_to_user(p, rinfo, + SZ_SG_REQ_INFO * SG_MAX_QUEUE); + result = result ? -EFAULT : 0; + kfree(rinfo); +@@ -1213,7 +1212,7 @@ sg_poll(struct file *filp, poll_table * + return POLLERR; + poll_wait(filp, &sfp->read_wait, wait); + read_lock_irqsave(&sfp->rq_list_lock, iflags); +- for (srp = sfp->headrp; srp; srp = srp->nextrp) { ++ list_for_each_entry(srp, &sfp->rq_list, entry) { + /* if any read waiting, flag it */ + if ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned)) + res = POLLIN | POLLRDNORM; +@@ -2116,7 +2115,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id) + unsigned long iflags; + + write_lock_irqsave(&sfp->rq_list_lock, iflags); +- for (resp = sfp->headrp; resp; resp = resp->nextrp) { ++ list_for_each_entry(resp, &sfp->rq_list, entry) { + /* look for requests that are ready + not SG_IO owned */ + if ((1 == resp->done) && (!resp->sg_io_owned) && + ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { +@@ -2134,70 +2133,45 @@ sg_add_request(Sg_fd * sfp) + { + int k; + unsigned long iflags; +- Sg_request *resp; + Sg_request *rp = sfp->req_arr; + + write_lock_irqsave(&sfp->rq_list_lock, iflags); +- resp = sfp->headrp; +- if (!resp) { +- memset(rp, 0, sizeof (Sg_request)); +- rp->parentfp = sfp; +- resp = rp; +- sfp->headrp = resp; +- } else { +- if (0 == sfp->cmd_q) +- resp = NULL; /* command queuing disallowed */ +- else { +- for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { +- if (!rp->parentfp) +- break; +- } +- if (k < SG_MAX_QUEUE) { +- memset(rp, 0, sizeof (Sg_request)); +- rp->parentfp = sfp; +- while (resp->nextrp) +- resp = resp->nextrp; +- resp->nextrp = rp; +- resp = rp; +- } else +- resp = NULL; ++ if (!list_empty(&sfp->rq_list)) { ++ if (!sfp->cmd_q) ++ goto out_unlock; ++ ++ for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { ++ if (!rp->parentfp) ++ break; + } ++ if (k >= SG_MAX_QUEUE) ++ goto out_unlock; + } +- if (resp) { +- resp->nextrp = NULL; +- resp->header.duration = jiffies_to_msecs(jiffies); +- } ++ memset(rp, 0, sizeof (Sg_request)); ++ rp->parentfp = sfp; ++ rp->header.duration = jiffies_to_msecs(jiffies); ++ list_add_tail(&rp->entry, &sfp->rq_list); + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); +- return resp; ++ return rp; ++out_unlock: ++ write_unlock_irqrestore(&sfp->rq_list_lock, iflags); ++ return NULL; + } + + /* Return of 1 for found; 0 for not found */ + static int + sg_remove_request(Sg_fd * sfp, Sg_request * srp) + { +- Sg_request *prev_rp; +- Sg_request *rp; + unsigned long iflags; + int res = 0; + +- if ((!sfp) || (!srp) || (!sfp->headrp)) ++ if (!sfp || !srp || list_empty(&sfp->rq_list)) + return res; + write_lock_irqsave(&sfp->rq_list_lock, iflags); +- prev_rp = sfp->headrp; +- if (srp == prev_rp) { +- sfp->headrp = prev_rp->nextrp; +- prev_rp->parentfp = NULL; ++ if (!list_empty(&srp->entry)) { ++ list_del(&srp->entry); ++ srp->parentfp = NULL; + res = 1; +- } else { +- while ((rp = prev_rp->nextrp)) { +- if (srp == rp) { +- prev_rp->nextrp = rp->nextrp; +- rp->parentfp = NULL; +- res = 1; +- break; +- } +- prev_rp = rp; +- } + } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return res; +@@ -2216,7 +2190,7 @@ sg_add_sfp(Sg_device * sdp) + + init_waitqueue_head(&sfp->read_wait); + rwlock_init(&sfp->rq_list_lock); +- ++ INIT_LIST_HEAD(&sfp->rq_list); + kref_init(&sfp->f_ref); + mutex_init(&sfp->f_mutex); + sfp->timeout = SG_DEFAULT_TIMEOUT; +@@ -2257,10 +2231,13 @@ sg_remove_sfp_usercontext(struct work_st + { + struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work); + struct sg_device *sdp = sfp->parentdp; ++ Sg_request *srp; + + /* Cleanup any responses which were never read(). */ +- while (sfp->headrp) +- sg_finish_rem_req(sfp->headrp); ++ while (!list_empty(&sfp->rq_list)) { ++ srp = list_first_entry(&sfp->rq_list, Sg_request, entry); ++ sg_finish_rem_req(srp); ++ } + + if (sfp->reserve.bufflen > 0) { + SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, +@@ -2663,7 +2640,7 @@ static int sg_proc_seq_show_devstrs(stru + /* must be called while holding sg_index_lock */ + static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) + { +- int k, m, new_interface, blen, usg; ++ int k, new_interface, blen, usg; + Sg_request *srp; + Sg_fd *fp; + const sg_io_hdr_t *hp; +@@ -2683,13 +2660,11 @@ static void sg_proc_debug_helper(struct + seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n", + (int) fp->cmd_q, (int) fp->force_packid, + (int) fp->keep_orphan); +- for (m = 0, srp = fp->headrp; +- srp != NULL; +- ++m, srp = srp->nextrp) { ++ list_for_each_entry(srp, &fp->rq_list, entry) { + hp = &srp->header; + new_interface = (hp->interface_id == '\0') ? 0 : 1; + if (srp->res_used) { +- if (new_interface && ++ if (new_interface && + (SG_FLAG_MMAP_IO & hp->flags)) + cp = " mmap>> "; + else +@@ -2720,7 +2695,7 @@ static void sg_proc_debug_helper(struct + seq_printf(s, "ms sgat=%d op=0x%02x\n", usg, + (int) srp->data.cmd_opcode); + } +- if (0 == m) ++ if (list_empty(&fp->rq_list)) + seq_puts(s, " No requests active\n"); + read_unlock(&fp->rq_list_lock); + } diff --git a/queue-3.18/series b/queue-3.18/series index a981176b34e..0e9ac4d0cd1 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -21,3 +21,9 @@ scsi-zfcp-fix-missing-trace-records-for-early-returns-in-tmf-eh-handlers.patch scsi-zfcp-fix-payload-with-full-fcp_rsp-iu-in-scsi-trace-records.patch scsi-zfcp-trace-hba-fsf-response-by-default-on-dismiss-or-timedout-late-response.patch scsi-zfcp-trace-high-part-of-new-64-bit-scsi-lun.patch +scsi-sg-remove-save_scat_len.patch +scsi-sg-use-standard-lists-for-sg_requests.patch +scsi-sg-off-by-one-in-sg_ioctl.patch +scsi-sg-factor-out-sg_fill_request_table.patch +scsi-sg-fixup-infoleak-when-using-sg_get_request_table.patch +scsi-qla2xxx-fix-an-integer-overflow-in-sysfs-code.patch