]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Sep 2013 18:20:26 +0000 (11:20 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Sep 2013 18:20:26 +0000 (11:20 -0700)
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

queue-3.4/scsi-sg-fix-user-memory-corruption-when-sg_io-is-interrupted-by-a-signal.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/target-fix-trailing-ascii-space-usage-in-inquiry-vendor-model.patch [new file with mode: 0644]

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 (file)
index 0000000..6c858e1
--- /dev/null
@@ -0,0 +1,132 @@
+From 35dc248383bbab0a7203fca4d722875bc81ef091 Mon Sep 17 00:00:00 2001
+From: Roland Dreier <roland@purestorage.com>
+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 <roland@purestorage.com>
+
+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 <James.Bottomley@hansenpartnership.com>,
+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 <costa@purestorage.com> for the
+original pointer to this bug in the sg code.
+
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Tested-by: David Milburn <dmilburn@redhat.com>
+Cc: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+[lizf: backported to 3.4:
+ - Use __bio_for_each_segment() instead of bio_for_each_segment_all()]
+Signed-off-by: Li Zefan <lizefan@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ 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;
index 9a1143081ada37a7334b7617f2c352ec3ed605f7..0e135d6101c6fbb36f96d144714c9fb7c3e3ecd4 100644 (file)
@@ -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 (file)
index 0000000..6e68d39
--- /dev/null
@@ -0,0 +1,44 @@
+From ee60bddba5a5f23e39598195d944aa0eb2d455e5 Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Wed, 24 Jul 2013 16:15:08 -0700
+Subject: target: Fix trailing ASCII space usage in INQUIRY vendor+model
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+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 <tomas.molota@lightstorm.sk>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;