1. 01 9月, 2013 28 次提交
  2. 25 8月, 2013 5 次提交
  3. 24 8月, 2013 2 次提交
  4. 22 8月, 2013 1 次提交
    • R
      [SCSI] sg: Fix user memory corruption when SG_IO is interrupted by a signal · 35dc2483
      Roland Dreier 提交于
      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: NRoland Dreier <roland@purestorage.com>
      Tested-by: NDavid Milburn <dmilburn@redhat.com>
      Cc: Jens Axboe <axboe@kernel.dk>
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
      35dc2483
  5. 20 8月, 2013 2 次提交
    • L
      proc: more readdir conversion bug-fixes · fd3930f7
      Linus Torvalds 提交于
      In the previous commit, Richard Genoud fixed proc_root_readdir(), which
      had lost the check for whether all of the non-process /proc entries had
      been returned or not.
      
      But that in turn exposed _another_ bug, namely that the original readdir
      conversion patch had yet another problem: it had lost the return value
      of proc_readdir_de(), so now checking whether it had completed
      successfully or not didn't actually work right anyway.
      
      This reinstates the non-zero return for the "end of base entries" that
      had also gotten lost in commit f0c3b509 ("[readdir] convert
      procfs").  So now you get all the base entries *and* you get all the
      process entries, regardless of getdents buffer size.
      
      (Side note: the Linux "getdents" manual page actually has a nice example
      application for testing getdents, which can be easily modified to use
      different buffers.  Who knew? Man-pages can be useful)
      Reported-by: NEmmanuel Benisty <benisty.e@gmail.com>
      Reported-by: NMarc Dionne <marc.c.dionne@gmail.com>
      Cc: Richard Genoud <richard.genoud@gmail.com>
      Cc: Al Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      fd3930f7
    • R
      proc: return on proc_readdir error · 94fc5d9d
      Richard Genoud 提交于
      Commit f0c3b509 ("[readdir] convert procfs") introduced a bug on the
      listing of the proc file-system.  The return value of proc_readdir()
      isn't tested anymore in the proc_root_readdir function.
      
      This lead to an "interesting" behaviour when we are using the getdents()
      system call with a buffer too small: instead of failing, it returns the
      first entries of /proc (enough to fill the given buffer), plus the PID
      directories.
      
      This is not triggered on glibc (as getdents is called with a 32KB
      buffer), but on uclibc, the buffer size is only 1KB, thus some proc
      entries are missing.
      
      See https://lkml.org/lkml/2013/8/12/288 for more background.
      Signed-off-by: NRichard Genoud <richard.genoud@gmail.com>
      Cc: Al Viro <viro@zeniv.linux.org.uk>
      Cc: Andrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      94fc5d9d
  6. 19 8月, 2013 2 次提交
新手
引导
客服 返回
顶部