aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-04-16 14:55:06 -0400
committerEric W. Biederman <ebiederm@xmission.com>2018-09-27 15:57:52 -0400
commit8b9c6b28312cc51a87055e292b11c5aa28f0c935 (patch)
tree72d2fb5a392dd97c11799884f8982ba44943588d
parent795a83714526754a2b8089a0533bfef24287bcb9 (diff)
signal/ia64: Use the generic force_sigsegv in setup_frame
The ia64 handling of failure to setup a signal frame has been trying to set overlapping fields in struct siginfo since 2.3.43. The si_pid and si_uid fields are stomped when the si_addr field is set. The si_code of SI_KERNEL indicates that si_pid and si_uid should be valid, and that si_addr does not exist. Being at odds with the definition of SI_KERNEL and with nothing to indicate that this was a signal frame setup failure there is no way for userspace to know that si_addr was filled out instead. In practice failure to setup a signal frame is rare, and si_pid and si_uid are always set to 0 when si_code is SI_KERNEL so I expect no one has looked closely enough before to see this weirdness. Further the only difference between force_sigsegv_info and the generic force_sigsegv other than the return code is that force_sigsegv_info stomps the si_uid and si_pid fields. Remove the bug and simplify the code by using force_sigsegv in this case just like other architectures. Fixes: 2.3.43 Cc: Tony Luck <tony.luck@intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: linux-ia64@vger.kernel.org Acked-by: Tony Luck <tony.luck@intel.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--arch/ia64/kernel/signal.c50
1 files changed, 12 insertions, 38 deletions
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index d1234a5ba4c5..01fc133b2e4c 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -232,37 +232,6 @@ rbs_on_sig_stack (unsigned long bsp)
232} 232}
233 233
234static long 234static long
235force_sigsegv_info (int sig, void __user *addr)
236{
237 unsigned long flags;
238 struct siginfo si;
239
240 clear_siginfo(&si);
241 if (sig == SIGSEGV) {
242 /*
243 * Acquiring siglock around the sa_handler-update is almost
244 * certainly overkill, but this isn't a
245 * performance-critical path and I'd rather play it safe
246 * here than having to debug a nasty race if and when
247 * something changes in kernel/signal.c that would make it
248 * no longer safe to modify sa_handler without holding the
249 * lock.
250 */
251 spin_lock_irqsave(&current->sighand->siglock, flags);
252 current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL;
253 spin_unlock_irqrestore(&current->sighand->siglock, flags);
254 }
255 si.si_signo = SIGSEGV;
256 si.si_errno = 0;
257 si.si_code = SI_KERNEL;
258 si.si_pid = task_pid_vnr(current);
259 si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
260 si.si_addr = addr;
261 force_sig_info(SIGSEGV, &si, current);
262 return 1;
263}
264
265static long
266setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr) 235setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
267{ 236{
268 extern char __kernel_sigtramp[]; 237 extern char __kernel_sigtramp[];
@@ -295,15 +264,18 @@ setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
295 * instead so we will die with SIGSEGV. 264 * instead so we will die with SIGSEGV.
296 */ 265 */
297 check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN; 266 check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
298 if (!likely(on_sig_stack(check_sp))) 267 if (!likely(on_sig_stack(check_sp))) {
299 return force_sigsegv_info(ksig->sig, (void __user *) 268 force_sigsegv(ksig->sig, current);
300 check_sp); 269 return 1;
270 }
301 } 271 }
302 } 272 }
303 frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); 273 frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
304 274
305 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 275 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
306 return force_sigsegv_info(ksig->sig, frame); 276 force_sigsegv(ksig->sig, current);
277 return 1;
278 }
307 279
308 err = __put_user(ksig->sig, &frame->arg0); 280 err = __put_user(ksig->sig, &frame->arg0);
309 err |= __put_user(&frame->info, &frame->arg1); 281 err |= __put_user(&frame->info, &frame->arg1);
@@ -317,8 +289,10 @@ setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
317 err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12); 289 err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12);
318 err |= setup_sigcontext(&frame->sc, set, scr); 290 err |= setup_sigcontext(&frame->sc, set, scr);
319 291
320 if (unlikely(err)) 292 if (unlikely(err)) {
321 return force_sigsegv_info(ksig->sig, frame); 293 force_sigsegv(ksig->sig, current);
294 return 1;
295 }
322 296
323 scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ 297 scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */
324 scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ 298 scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */