Skip to content

Commit f936991

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull first series of signal handling cleanups from Al Viro: "This is just the first part of the queue (about a half of it); assorted fixes all over the place in signal handling. This one ends with all sigsuspend() implementations switched to generic one (->saved_sigmask-based). With this, a bunch of assorted old buglets are fixed and most of the missing bits of NOTIFY_RESUME hookup are in place. Two more fixes sit in arm and um trees respectively, and there's a couple of broken ones that need obvious fixes - parisc and avr32 check TIF_NOTIFY_RESUME only on one of two codepaths; fixes for that will happen in the next series" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (55 commits) unicore32: if there's no handler we need to restore sigmask, syscall or no syscall xtensa: add handling of TIF_NOTIFY_RESUME microblaze: drop 'oldset' argument of do_notify_resume() microblaze: handle TIF_NOTIFY_RESUME score: add handling of NOTIFY_RESUME to do_notify_resume() m68k: add TIF_NOTIFY_RESUME and handle it. sparc: kill ancient comment in sparc_sigaction() h8300: missing checks of __get_user()/__put_user() return values frv: missing checks of __get_user()/__put_user() return values cris: missing checks of __get_user()/__put_user() return values powerpc: missing checks of __get_user()/__put_user() return values sh: missing checks of __get_user()/__put_user() return values sparc: missing checks of __get_user()/__put_user() return values avr32: struct old_sigaction is never used m32r: struct old_sigaction is never used xtensa: xtensa_sigaction doesn't exist alpha: tidy signal delivery up score: don't open-code force_sigsegv() cris: don't open-code force_sigsegv() blackfin: don't open-code force_sigsegv() ...
2 parents 05f144a + 415d04d commit f936991

File tree

54 files changed

+386
-817
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+386
-817
lines changed

arch/alpha/kernel/signal.c

Lines changed: 27 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
3535

3636
asmlinkage void ret_from_sys_call(void);
37-
static void do_signal(struct pt_regs *, struct switch_stack *,
38-
unsigned long, unsigned long);
39-
4037

4138
/*
4239
* The OSF/1 sigprocmask calling sequence is different from the
@@ -121,17 +118,8 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
121118
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
122119
{
123120
sigset_t blocked;
124-
125-
current->saved_sigmask = current->blocked;
126-
127-
mask &= _BLOCKABLE;
128121
siginitset(&blocked, mask);
129-
set_current_blocked(&blocked);
130-
131-
current->state = TASK_INTERRUPTIBLE;
132-
schedule();
133-
set_thread_flag(TIF_RESTORE_SIGMASK);
134-
return -ERESTARTNOHAND;
122+
return sigsuspend(&blocked);
135123
}
136124

137125
asmlinkage int
@@ -376,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
376364
oldsp = rdusp();
377365
frame = get_sigframe(ka, oldsp, sizeof(*frame));
378366
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
379-
goto give_sigsegv;
367+
return -EFAULT;
380368

381369
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
382370
if (err)
383-
goto give_sigsegv;
371+
return -EFAULT;
384372

385373
/* Set up to return from userspace. If provided, use a stub
386374
already in userspace. */
@@ -396,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
396384

397385
/* Check that everything was written properly. */
398386
if (err)
399-
goto give_sigsegv;
387+
return err;
400388

401389
/* "Return" to the handler */
402390
regs->r26 = r26;
@@ -410,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
410398
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
411399
current->comm, current->pid, frame, regs->pc, regs->r26);
412400
#endif
413-
414401
return 0;
415-
416-
give_sigsegv:
417-
force_sigsegv(sig, current);
418-
return -EFAULT;
419402
}
420403

421404
static int
@@ -428,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
428411
oldsp = rdusp();
429412
frame = get_sigframe(ka, oldsp, sizeof(*frame));
430413
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
431-
goto give_sigsegv;
414+
return -EFAULT;
432415

433416
err |= copy_siginfo_to_user(&frame->info, info);
434417

@@ -443,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
443426
set->sig[0], oldsp);
444427
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
445428
if (err)
446-
goto give_sigsegv;
429+
return -EFAULT;
447430

448431
/* Set up to return from userspace. If provided, use a stub
449432
already in userspace. */
@@ -459,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
459442
}
460443

461444
if (err)
462-
goto give_sigsegv;
445+
return -EFAULT;
463446

464447
/* "Return" to the handler */
465448
regs->r26 = r26;
@@ -475,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
475458
#endif
476459

477460
return 0;
478-
479-
give_sigsegv:
480-
force_sigsegv(sig, current);
481-
return -EFAULT;
482461
}
483462

484463

485464
/*
486465
* OK, we're invoking a handler.
487466
*/
488-
static inline int
467+
static inline void
489468
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
490-
sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
469+
struct pt_regs * regs, struct switch_stack *sw)
491470
{
471+
sigset_t *oldset = &current->blocked;
492472
int ret;
493473

474+
if (test_thread_flag(TIF_RESTORE_SIGMASK))
475+
oldset = &current->saved_sigmask;
476+
494477
if (ka->sa.sa_flags & SA_SIGINFO)
495478
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
496479
else
497480
ret = setup_frame(sig, ka, oldset, regs, sw);
498481

499-
if (ret == 0)
500-
block_sigmask(ka, sig);
501-
502-
return ret;
482+
if (ret) {
483+
force_sigsegv(sig, current);
484+
return;
485+
}
486+
block_sigmask(ka, sig);
487+
/* A signal was successfully delivered, and the
488+
saved sigmask was stored on the signal frame,
489+
and will be restored by sigreturn. So we can
490+
simply clear the restore sigmask flag. */
491+
clear_thread_flag(TIF_RESTORE_SIGMASK);
503492
}
504493

505494
static inline void
@@ -547,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
547536
int signr;
548537
unsigned long single_stepping = ptrace_cancel_bpt(current);
549538
struct k_sigaction ka;
550-
sigset_t *oldset;
551-
552-
if (test_thread_flag(TIF_RESTORE_SIGMASK))
553-
oldset = &current->saved_sigmask;
554-
else
555-
oldset = &current->blocked;
556539

557540
/* This lets the debugger run, ... */
558541
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -564,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
564547
/* Whee! Actually deliver the signal. */
565548
if (r0)
566549
syscall_restart(r0, r19, regs, &ka);
567-
if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
568-
/* A signal was successfully delivered, and the
569-
saved sigmask was stored on the signal frame,
570-
and will be restored by sigreturn. So we can
571-
simply clear the restore sigmask flag. */
572-
if (test_thread_flag(TIF_RESTORE_SIGMASK))
573-
clear_thread_flag(TIF_RESTORE_SIGMASK);
574-
}
550+
handle_signal(signr, &ka, &info, regs, sw);
575551
if (single_stepping)
576552
ptrace_set_bpt(current); /* re-set bpt */
577553
return;
@@ -596,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
596572
}
597573

598574
/* If there's no signal to deliver, we just restore the saved mask. */
599-
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
600-
clear_thread_flag(TIF_RESTORE_SIGMASK);
601-
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
602-
}
575+
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
576+
set_current_blocked(&current->saved_sigmask);
603577

604578
if (single_stepping)
605579
ptrace_set_bpt(current); /* re-set breakpoint */
@@ -610,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
610584
unsigned long thread_info_flags,
611585
unsigned long r0, unsigned long r19)
612586
{
613-
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
587+
if (thread_info_flags & _TIF_SIGPENDING)
614588
do_signal(regs, sw, r0, r19);
615589

616590
if (thread_info_flags & _TIF_NOTIFY_RESUME) {

arch/arm/kernel/signal.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,8 @@ const unsigned long syscall_restart_code[2] = {
6767
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
6868
{
6969
sigset_t blocked;
70-
71-
current->saved_sigmask = current->blocked;
72-
73-
mask &= _BLOCKABLE;
7470
siginitset(&blocked, mask);
75-
set_current_blocked(&blocked);
76-
77-
current->state = TASK_INTERRUPTIBLE;
78-
schedule();
79-
set_restore_sigmask();
80-
return -ERESTARTNOHAND;
71+
return sigsuspend(&blocked);
8172
}
8273

8374
asmlinkage int

arch/avr32/include/asm/signal.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,6 @@ typedef unsigned long sigset_t;
115115
#include <asm-generic/signal-defs.h>
116116

117117
#ifdef __KERNEL__
118-
struct old_sigaction {
119-
__sighandler_t sa_handler;
120-
old_sigset_t sa_mask;
121-
unsigned long sa_flags;
122-
__sigrestore_t sa_restorer;
123-
};
124-
125118
struct sigaction {
126119
__sighandler_t sa_handler;
127120
unsigned long sa_flags;

arch/avr32/kernel/signal.c

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
7777
struct rt_sigframe __user *frame;
7878
sigset_t set;
7979

80+
/* Always make any pending restarted system calls return -EINTR */
81+
current_thread_info()->restart_block.fn = do_no_restart_syscall;
82+
8083
frame = (struct rt_sigframe __user *)regs->sp;
8184
pr_debug("SIG return: frame = %p\n", frame);
8285

@@ -87,10 +90,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
8790
goto badframe;
8891

8992
sigdelsetmask(&set, ~_BLOCKABLE);
90-
spin_lock_irq(&current->sighand->siglock);
91-
current->blocked = set;
92-
recalc_sigpending();
93-
spin_unlock_irq(&current->sighand->siglock);
93+
set_current_blocked(&set);
9494

9595
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
9696
goto badframe;
@@ -238,22 +238,16 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
238238
*/
239239
ret |= !valid_user_regs(regs);
240240

241-
/*
242-
* Block the signal if we were unsuccessful.
243-
*/
244-
if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
245-
spin_lock_irq(&current->sighand->siglock);
246-
sigorsets(&current->blocked, &current->blocked,
247-
&ka->sa.sa_mask);
248-
sigaddset(&current->blocked, sig);
249-
recalc_sigpending();
250-
spin_unlock_irq(&current->sighand->siglock);
251-
}
252-
253-
if (ret == 0)
241+
if (ret != 0) {
242+
force_sigsegv(sig, current);
254243
return;
244+
}
255245

256-
force_sigsegv(sig, current);
246+
/*
247+
* Block the signal if we were successful.
248+
*/
249+
block_sigmask(ka, sig);
250+
clear_thread_flag(TIF_RESTORE_SIGMASK);
257251
}
258252

259253
/*

arch/blackfin/kernel/signal.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
9999
goto badframe;
100100

101101
sigdelsetmask(&set, ~_BLOCKABLE);
102-
spin_lock_irq(&current->sighand->siglock);
103-
current->blocked = set;
104-
recalc_sigpending();
105-
spin_unlock_irq(&current->sighand->siglock);
102+
set_current_blocked(&set);
106103

107104
if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
108105
goto badframe;
@@ -213,9 +210,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
213210
return 0;
214211

215212
give_sigsegv:
216-
if (sig == SIGSEGV)
217-
ka->sa.sa_handler = SIG_DFL;
218-
force_sig(SIGSEGV, current);
213+
force_sigsegv(sig, current);
219214
return -EFAULT;
220215
}
221216

@@ -266,15 +261,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
266261
/* set up the stack frame */
267262
ret = setup_rt_frame(sig, ka, info, oldset, regs);
268263

269-
if (ret == 0) {
270-
spin_lock_irq(&current->sighand->siglock);
271-
sigorsets(&current->blocked, &current->blocked,
272-
&ka->sa.sa_mask);
273-
if (!(ka->sa.sa_flags & SA_NODEFER))
274-
sigaddset(&current->blocked, sig);
275-
recalc_sigpending();
276-
spin_unlock_irq(&current->sighand->siglock);
277-
}
264+
if (ret == 0)
265+
block_sigmask(ka, sig);
266+
278267
return ret;
279268
}
280269

arch/c6x/kernel/signal.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
6969
struct rt_sigframe __user *frame;
7070
sigset_t set;
7171

72+
/* Always make any pending restarted system calls return -EINTR */
73+
current_thread_info()->restart_block.fn = do_no_restart_syscall;
74+
7275
/*
7376
* Since we stacked the signal on a dword boundary,
7477
* 'sp' should be dword aligned here. If it's

0 commit comments

Comments
 (0)