aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
commit86c47b70f62a7072d441ba212aab33c2f82627c2 (patch)
treed03988bd2226966352bb7f3c2e82ff545353d2c4 /arch/powerpc
parent1193755ac6328ad240ba987e6ec41d5e8baf0680 (diff)
parent44fbbb3dc687c9709a6f2236197316e5c79ab1eb (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull third pile of signal handling patches from Al Viro: "This time it's mostly helpers and conversions to them; there's a lot of stuff remaining in the tree, but that'll either go in -rc2 (isolated bug fixes, ideally via arch maintainers' trees) or will sit there until the next cycle." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: x86: get rid of calling do_notify_resume() when returning to kernel mode blackfin: check __get_user() return value whack-a-mole with TIF_FREEZE FRV: Optimise the system call exit path in entry.S [ver #2] FRV: Shrink TIF_WORK_MASK [ver #2] FRV: Prevent syscall exit tracing and notify_resume at end of kernel exceptions new helper: signal_delivered() powerpc: get rid of restore_sigmask() most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set set_restore_sigmask() is never called without SIGPENDING (and never should be) TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set don't call try_to_freeze() from do_signal() pull clearing RESTORE_SIGMASK into block_sigmask() sh64: failure to build sigframe != signal without handler openrisc: tracehook_signal_handler() is supposed to be called on success new helper: sigmask_to_save() new helper: restore_saved_sigmask() new helpers: {clear,test,test_and_clear}_restore_sigmask() HAVE_RESTORE_SIGMASK is defined on all architectures now
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/thread_info.h18
-rw-r--r--arch/powerpc/kernel/signal.c36
-rw-r--r--arch/powerpc/kernel/signal.h3
-rw-r--r--arch/powerpc/kernel/signal_32.c4
-rw-r--r--arch/powerpc/kernel/signal_64.c4
5 files changed, 24 insertions, 41 deletions
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index a556ccc16b58..68831e9cf82f 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -140,7 +140,23 @@ static inline void set_restore_sigmask(void)
140{ 140{
141 struct thread_info *ti = current_thread_info(); 141 struct thread_info *ti = current_thread_info();
142 ti->local_flags |= _TLF_RESTORE_SIGMASK; 142 ti->local_flags |= _TLF_RESTORE_SIGMASK;
143 set_bit(TIF_SIGPENDING, &ti->flags); 143 WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
144}
145static inline void clear_restore_sigmask(void)
146{
147 current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
148}
149static inline bool test_restore_sigmask(void)
150{
151 return current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK;
152}
153static inline bool test_and_clear_restore_sigmask(void)
154{
155 struct thread_info *ti = current_thread_info();
156 if (!(ti->local_flags & _TLF_RESTORE_SIGMASK))
157 return false;
158 ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
159 return true;
144} 160}
145 161
146static inline bool test_thread_local_flags(unsigned int flags) 162static inline bool test_thread_local_flags(unsigned int flags)
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index bfc3ec1382fb..5c023c9cf16e 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -51,16 +51,6 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
51 return (void __user *)newsp; 51 return (void __user *)newsp;
52} 52}
53 53
54
55/*
56 * Restore the user process's signal mask
57 */
58void restore_sigmask(sigset_t *set)
59{
60 sigdelsetmask(set, ~_BLOCKABLE);
61 set_current_blocked(set);
62}
63
64static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, 54static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
65 int has_handler) 55 int has_handler)
66{ 56{
@@ -114,30 +104,21 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
114 104
115static int do_signal(struct pt_regs *regs) 105static int do_signal(struct pt_regs *regs)
116{ 106{
117 sigset_t *oldset; 107 sigset_t *oldset = sigmask_to_save();
118 siginfo_t info; 108 siginfo_t info;
119 int signr; 109 int signr;
120 struct k_sigaction ka; 110 struct k_sigaction ka;
121 int ret; 111 int ret;
122 int is32 = is_32bit_task(); 112 int is32 = is_32bit_task();
123 113
124 if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
125 oldset = &current->saved_sigmask;
126 else
127 oldset = &current->blocked;
128
129 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 114 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
130 115
131 /* Is there any syscall restart business here ? */ 116 /* Is there any syscall restart business here ? */
132 check_syscall_restart(regs, &ka, signr > 0); 117 check_syscall_restart(regs, &ka, signr > 0);
133 118
134 if (signr <= 0) { 119 if (signr <= 0) {
135 struct thread_info *ti = current_thread_info();
136 /* No signal to deliver -- put the saved sigmask back */ 120 /* No signal to deliver -- put the saved sigmask back */
137 if (ti->local_flags & _TLF_RESTORE_SIGMASK) { 121 restore_saved_sigmask();
138 ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
139 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
140 }
141 regs->trap = 0; 122 regs->trap = 0;
142 return 0; /* no signals delivered */ 123 return 0; /* no signals delivered */
143 } 124 }
@@ -167,18 +148,7 @@ static int do_signal(struct pt_regs *regs)
167 148
168 regs->trap = 0; 149 regs->trap = 0;
169 if (ret) { 150 if (ret) {
170 block_sigmask(&ka, signr); 151 signal_delivered(signr, &info, &ka, regs,
171
172 /*
173 * A signal was successfully delivered; the saved sigmask is in
174 * its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
175 */
176 current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
177
178 /*
179 * Let tracing know that we've done the handler setup.
180 */
181 tracehook_signal_handler(signr, &info, &ka, regs,
182 test_thread_flag(TIF_SINGLESTEP)); 152 test_thread_flag(TIF_SINGLESTEP));
183 } 153 }
184 154
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index 8dde973aaaf5..e00acb413934 100644
--- a/arch/powerpc/kernel/signal.h
+++ b/arch/powerpc/kernel/signal.h
@@ -10,13 +10,10 @@
10#ifndef _POWERPC_ARCH_SIGNAL_H 10#ifndef _POWERPC_ARCH_SIGNAL_H
11#define _POWERPC_ARCH_SIGNAL_H 11#define _POWERPC_ARCH_SIGNAL_H
12 12
13#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
14
15extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); 13extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
16 14
17extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, 15extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
18 size_t frame_size, int is_32); 16 size_t frame_size, int is_32);
19extern void restore_sigmask(sigset_t *set);
20 17
21extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, 18extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
22 siginfo_t *info, sigset_t *oldset, 19 siginfo_t *info, sigset_t *oldset,
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 61f6aff25edc..8b4c049aee20 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -919,7 +919,7 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
919 if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp))) 919 if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
920 return -EFAULT; 920 return -EFAULT;
921#endif 921#endif
922 restore_sigmask(&set); 922 set_current_blocked(&set);
923 if (restore_user_regs(regs, mcp, sig)) 923 if (restore_user_regs(regs, mcp, sig))
924 return -EFAULT; 924 return -EFAULT;
925 925
@@ -1273,7 +1273,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
1273 set.sig[0] = sigctx.oldmask; 1273 set.sig[0] = sigctx.oldmask;
1274 set.sig[1] = sigctx._unused[3]; 1274 set.sig[1] = sigctx._unused[3];
1275#endif 1275#endif
1276 restore_sigmask(&set); 1276 set_current_blocked(&set);
1277 1277
1278 sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); 1278 sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
1279 addr = sr; 1279 addr = sr;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 2692efdb154e..d183f8719a50 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -335,7 +335,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
335 335
336 if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set))) 336 if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set)))
337 do_exit(SIGSEGV); 337 do_exit(SIGSEGV);
338 restore_sigmask(&set); 338 set_current_blocked(&set);
339 if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext)) 339 if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext))
340 do_exit(SIGSEGV); 340 do_exit(SIGSEGV);
341 341
@@ -364,7 +364,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
364 364
365 if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) 365 if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
366 goto badframe; 366 goto badframe;
367 restore_sigmask(&set); 367 set_current_blocked(&set);
368 if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) 368 if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext))
369 goto badframe; 369 goto badframe;
370 370