This is the minimal fix for stable, I'll send cleanups later. Commit 854a6ed56839 ("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?
Showing the changes to include/linux (1 of 6 files). Show all
Unified · Split
| @@ -276,7 +276,7 @@ extern int sigprocmask(int, sigset_t *, sigset_t *); · 275 unmodified lines | ||
| 276 | 276 | extern int set_user_sigmask(const sigset_t __user *usigmask, sigset_t *set, |
| 277 | 277 | sigset_t *oldset, size_t sigsetsize); |
| 278 | 278 | extern void restore_user_sigmask(const void __user *usigmask, |
| 279 | − sigset_t *sigsaved); | |
| 279 | + sigset_t *sigsaved, bool interrupted); | |
| 280 | 280 | extern void set_current_blocked(sigset_t *); |
| 281 | 281 | extern void __set_current_blocked(const sigset_t *); |
| 282 | 282 | extern int show_unhandled_signals; |