From: Greg Kroah-Hartman Date: Thu, 5 Sep 2013 18:20:26 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.0.95~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4cbd62cff974cdc0edfa8637ed0d31929b6e8d79;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: scsi-sg-fix-user-memory-corruption-when-sg_io-is-interrupted-by-a-signal.patch target-fix-trailing-ascii-space-usage-in-inquiry-vendor-model.patch --- diff --git a/queue-3.4/scsi-sg-fix-user-memory-corruption-when-sg_io-is-interrupted-by-a-signal.patch b/queue-3.4/scsi-sg-fix-user-memory-corruption-when-sg_io-is-interrupted-by-a-signal.patch new file mode 100644 index 00000000000..6c858e16a82 --- /dev/null +++ b/queue-3.4/scsi-sg-fix-user-memory-corruption-when-sg_io-is-interrupted-by-a-signal.patch @@ -0,0 +1,132 @@ +From 35dc248383bbab0a7203fca4d722875bc81ef091 Mon Sep 17 00:00:00 2001 +From: Roland Dreier +Date: Mon, 5 Aug 2013 17:55:01 -0700 +Subject: SCSI: sg: Fix user memory corruption when SG_IO is interrupted by a signal + +From: Roland Dreier + +commit 35dc248383bbab0a7203fca4d722875bc81ef091 upstream. + +There is a nasty bug in the SCSI SG_IO ioctl that in some circumstances +leads to one process writing data into the address space of some other +random unrelated process if the ioctl is interrupted by a signal. +What happens is the following: + + - A process issues an SG_IO ioctl with direction DXFER_FROM_DEV (ie the + underlying SCSI command will transfer data from the SCSI device to + the buffer provided in the ioctl) + + - Before the command finishes, a signal is sent to the process waiting + in the ioctl. This will end up waking up the sg_ioctl() code: + + result = wait_event_interruptible(sfp->read_wait, + (srp_done(sfp, srp) || sdp->detached)); + + but neither srp_done() nor sdp->detached is true, so we end up just + setting srp->orphan and returning to userspace: + + srp->orphan = 1; + write_unlock_irq(&sfp->rq_list_lock); + return result; /* -ERESTARTSYS because signal hit process */ + + At this point the original process is done with the ioctl and + blithely goes ahead handling the signal, reissuing the ioctl, etc. + + - Eventually, the SCSI command issued by the first ioctl finishes and + ends up in sg_rq_end_io(). At the end of that function, we run through: + + write_lock_irqsave(&sfp->rq_list_lock, iflags); + if (unlikely(srp->orphan)) { + if (sfp->keep_orphan) + srp->sg_io_owned = 0; + else + done = 0; + } + srp->done = done; + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + + if (likely(done)) { + /* Now wake up any sg_read() that is waiting for this + * packet. + */ + wake_up_interruptible(&sfp->read_wait); + kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); + kref_put(&sfp->f_ref, sg_remove_sfp); + } else { + INIT_WORK(&srp->ew.work, sg_rq_end_io_usercontext); + schedule_work(&srp->ew.work); + } + + Since srp->orphan *is* set, we set done to 0 (assuming the + userspace app has not set keep_orphan via an SG_SET_KEEP_ORPHAN + ioctl), and therefore we end up scheduling sg_rq_end_io_usercontext() + to run in a workqueue. + + - In workqueue context we go through sg_rq_end_io_usercontext() -> + sg_finish_rem_req() -> blk_rq_unmap_user() -> ... -> + bio_uncopy_user() -> __bio_copy_iov() -> copy_to_user(). + + The key point here is that we are doing copy_to_user() on a + workqueue -- that is, we're on a kernel thread with current->mm + equal to whatever random previous user process was scheduled before + this kernel thread. So we end up copying whatever data the SCSI + command returned to the virtual address of the buffer passed into + the original ioctl, but it's quite likely we do this copying into a + different address space! + +As suggested by James Bottomley , +add a check for current->mm (which is NULL if we're on a kernel thread +without a real userspace address space) in bio_uncopy_user(), and skip +the copy if we're on a kernel thread. + +There's no reason that I can think of for any caller of bio_uncopy_user() +to want to do copying on a kernel thread with a random active userspace +address space. + +Huge thanks to Costa Sapuntzakis for the +original pointer to this bug in the sg code. + +Signed-off-by: Roland Dreier +Tested-by: David Milburn +Cc: Jens Axboe +Signed-off-by: James Bottomley +[lizf: backported to 3.4: + - Use __bio_for_each_segment() instead of bio_for_each_segment_all()] +Signed-off-by: Li Zefan +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/bio.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/fs/bio.c ++++ b/fs/bio.c +@@ -787,12 +787,22 @@ static int __bio_copy_iov(struct bio *bi + int bio_uncopy_user(struct bio *bio) + { + struct bio_map_data *bmd = bio->bi_private; +- int ret = 0; ++ struct bio_vec *bvec; ++ int ret = 0, i; + +- if (!bio_flagged(bio, BIO_NULL_MAPPED)) +- ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, +- bmd->nr_sgvecs, bio_data_dir(bio) == READ, +- 0, bmd->is_our_pages); ++ if (!bio_flagged(bio, BIO_NULL_MAPPED)) { ++ /* ++ * if we're in a workqueue, the request is orphaned, so ++ * don't copy into a random user address space, just free. ++ */ ++ if (current->mm) ++ ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, ++ bmd->nr_sgvecs, bio_data_dir(bio) == READ, ++ 0, bmd->is_our_pages); ++ else if (bmd->is_our_pages) ++ __bio_for_each_segment(bvec, bio, i, 0) ++ __free_page(bvec->bv_page); ++ } + bio_free_map_data(bmd); + bio_put(bio); + return ret; diff --git a/queue-3.4/series b/queue-3.4/series index 9a1143081ad..0e135d6101c 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -10,3 +10,5 @@ sunrpc-fix-memory-corruption-issue-on-32-bit-highmem-systems.patch ath9k_htc-restore-skb-headroom-when-returning-skb-to-mac80211.patch iwl4965-fix-rfkill-set-state-regression.patch acpi-ec-add-asustek-l4r-to-quirk-list-in-order-to-validate-ecdt.patch +target-fix-trailing-ascii-space-usage-in-inquiry-vendor-model.patch +scsi-sg-fix-user-memory-corruption-when-sg_io-is-interrupted-by-a-signal.patch diff --git a/queue-3.4/target-fix-trailing-ascii-space-usage-in-inquiry-vendor-model.patch b/queue-3.4/target-fix-trailing-ascii-space-usage-in-inquiry-vendor-model.patch new file mode 100644 index 00000000000..6e68d39b2d5 --- /dev/null +++ b/queue-3.4/target-fix-trailing-ascii-space-usage-in-inquiry-vendor-model.patch @@ -0,0 +1,44 @@ +From ee60bddba5a5f23e39598195d944aa0eb2d455e5 Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger +Date: Wed, 24 Jul 2013 16:15:08 -0700 +Subject: target: Fix trailing ASCII space usage in INQUIRY vendor+model + +From: Nicholas Bellinger + +commit ee60bddba5a5f23e39598195d944aa0eb2d455e5 upstream. + +This patch fixes spc_emulate_inquiry_std() to add trailing ASCII +spaces for INQUIRY vendor + model fields following SPC-4 text: + + "ASCII data fields described as being left-aligned shall have any + unused bytes at the end of the field (i.e., highest offset) and + the unused bytes shall be filled with ASCII space characters (20h)." + +This addresses a problem with Falconstor NSS multipathing. + +Reported-by: Tomas Molota +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_cdb.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/target/target_core_cdb.c ++++ b/drivers/target/target_core_cdb.c +@@ -97,9 +97,12 @@ target_emulate_inquiry_std(struct se_cmd + + buf[7] = 0x2; /* CmdQue=1 */ + +- snprintf(&buf[8], 8, "LIO-ORG"); +- snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model); +- snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision); ++ memcpy(&buf[8], "LIO-ORG ", 8); ++ memset(&buf[16], 0x20, 16); ++ memcpy(&buf[16], dev->se_sub_dev->t10_wwn.model, ++ min_t(size_t, strlen(dev->se_sub_dev->t10_wwn.model), 16)); ++ memcpy(&buf[32], dev->se_sub_dev->t10_wwn.revision, ++ min_t(size_t, strlen(dev->se_sub_dev->t10_wwn.revision), 4)); + buf[4] = 31; /* Set additional length to 31 */ + + return 0;