signal: remove the wrong signal_pending() check in restore_user_sigmask()
This is the minimal fix for stable, I'll send cleanups later. Commit854a6ed568
("signal: Add restore_user_sigmask()") introduced the visible change which breaks user-space: a signal temporary unblocked by set_user_sigmask() can be delivered even if the caller returns success or timeout. Change restore_user_sigmask() to accept the additional "interrupted" argument which should be used instead of signal_pending() check, and update the callers. Eric said: : For clarity. I don't think this is required by posix, or fundamentally to : remove the races in select. It is what linux has always done and we have : applications who care so I agree this fix is needed. : : Further in any case where the semantic change that this patch rolls back : (aka where allowing a signal to be delivered and the select like call to : complete) would be advantage we can do as well if not better by using : signalfd. : : Michael is there any chance we can get this guarantee of the linux : implementation of pselect and friends clearly documented. The guarantee : that if the system call completes successfully we are guaranteed that no : signal that is unblocked by using sigmask will be delivered? Link: http://lkml.kernel.org/r/20190604134117.GA29963@redhat.com Fixes:854a6ed568
("signal: Add restore_user_sigmask()") Signed-off-by: Oleg Nesterov <oleg@redhat.com> Reported-by: Eric Wong <e@80x24.org> Tested-by: Eric Wong <e@80x24.org> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Deepa Dinamani <deepa.kernel@gmail.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Jason Baron <jbaron@akamai.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: David Laight <David.Laight@ACULAB.COM> Cc: <stable@vger.kernel.org> [5.0+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
867bfa4a5f
commit
97abc889ee
18
fs/select.c
18
fs/select.c
@@ -758,10 +758,9 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
|
||||
return ret;
|
||||
|
||||
ret = core_sys_select(n, inp, outp, exp, to);
|
||||
restore_user_sigmask(sigmask, &sigsaved, ret == -ERESTARTNOHAND);
|
||||
ret = poll_select_copy_remaining(&end_time, tsp, type, ret);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1106,8 +1105,7 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
|
||||
|
||||
ret = do_sys_poll(ufds, nfds, to);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved, ret == -EINTR);
|
||||
/* We can restart this syscall, usually */
|
||||
if (ret == -EINTR)
|
||||
ret = -ERESTARTNOHAND;
|
||||
@@ -1142,8 +1140,7 @@ SYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds, unsigned int, nfds,
|
||||
|
||||
ret = do_sys_poll(ufds, nfds, to);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved, ret == -EINTR);
|
||||
/* We can restart this syscall, usually */
|
||||
if (ret == -EINTR)
|
||||
ret = -ERESTARTNOHAND;
|
||||
@@ -1350,10 +1347,9 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
|
||||
return ret;
|
||||
|
||||
ret = compat_core_sys_select(n, inp, outp, exp, to);
|
||||
restore_user_sigmask(sigmask, &sigsaved, ret == -ERESTARTNOHAND);
|
||||
ret = poll_select_copy_remaining(&end_time, tsp, type, ret);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1425,8 +1421,7 @@ COMPAT_SYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds,
|
||||
|
||||
ret = do_sys_poll(ufds, nfds, to);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved, ret == -EINTR);
|
||||
/* We can restart this syscall, usually */
|
||||
if (ret == -EINTR)
|
||||
ret = -ERESTARTNOHAND;
|
||||
@@ -1461,8 +1456,7 @@ COMPAT_SYSCALL_DEFINE5(ppoll_time64, struct pollfd __user *, ufds,
|
||||
|
||||
ret = do_sys_poll(ufds, nfds, to);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved);
|
||||
|
||||
restore_user_sigmask(sigmask, &sigsaved, ret == -EINTR);
|
||||
/* We can restart this syscall, usually */
|
||||
if (ret == -EINTR)
|
||||
ret = -ERESTARTNOHAND;
|
||||
|
Reference in New Issue
Block a user