Re: [PATCH] bio: return EINTR if copying to user space got interrupted

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2016-02-12 at 09:39 +0100, Hannes Reinecke wrote:
> Commit 35dc248383bbab0a7203fca4d722875bc81ef091 introduced a check for
> current->mm to see if we have a user space context and only copies data
> if we do. Now if an IO gets interrupted by a signal data isn't copied
> into user space any more (as we don't have a user space context) but
> user space isn't notified about it.
> 
> This patch modifies the behaviour to return -EINTR from bio_uncopy_user()
> to notify userland that a signal has interrupted the syscall, otherwise
> it could lead to a situation where the caller may get a buffer with
> no data returned.
> 
> This can be reproduced by issuing SG_IO ioctl()s in one thread while
> constantly sending signals to it.

Well, this is definitely an improvement, since it now indicates to
the user that there was a problem instead of silently returning with
no data and no error, but it doesn't completely fix the issue.

For one thing, if the SG_IO is performed to a sequential media device,
the I/O is actually performed, and the position changes, it is just the
data that is not copied back.  So e.g. a user program making calls to
read from a tape device that gets signals and retrying on -EINTR will
skip blocks.  There is a similar problem already with SG_IO and
-ERESTARTSYS.  I believe that that only way around this is to mask the
signals.  (This is also problem with non-idempotent commands, such as
COMPARE AND WRITE.)

I should mention that the patch "sg: Fix user memory corruption when
SG_IO is interrupted by a signal" broke a 3rd-party kernel module that
happened to use SG_IO to pass *kernel* addresses for I/O.  Which worked
for them until the current->mm test was added.  (I don't know why they
didn't just put I/O on the request queue like everyone else, though.)

This patch should go in, though.

Reviewed-by: Ewan D. Milne <emilne@xxxxxxxxxx>

> 
> Fixes: 35dc248 [SCSI] sg: Fix user memory corruption when SG_IO is interrupted by a signal
> Signed-off-by: Johannes Thumshirn <jthumshirn@xxxxxxx>
> Signed-off-by: Hannes Reinecke <hare@xxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx # v.3.11+
> ---
>  block/bio.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/block/bio.c b/block/bio.c
> index dbabd48..24e5b69 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -1090,9 +1090,12 @@ int bio_uncopy_user(struct bio *bio)
>  	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.
> +		 * don't copy into a random user address space, just free
> +		 * and return -EINTR so user space doesn't expect any data.
>  		 */
> -		if (current->mm && bio_data_dir(bio) == READ)
> +		if (!current->mm)
> +			ret = -EINTR;
> +		else if (bio_data_dir(bio) == READ)
>  			ret = bio_copy_to_iter(bio, bmd->iter);
>  		if (bmd->is_our_pages)
>  			bio_free_pages(bio);


--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]