History

x86: get rid of put_user_try in __setup_rt_frame() (both 32bit and 64bit)

Straightforward, except for save_altstack_ex() stuck in those. Replace that thing with an analogue that would use unsafe_put_user() instead of put_user_ex() (called compat_save_altstack()) and be done with that.

Al Viro committed 6 years ago

Commit 119cd591 parent 57d563c2 files · +52 −47Browse files

Unified · Split

2 files
  1. arch/x86/kernel/signal.c +48 −43
  2. include/linux/signal.h +4 −4
arch/x86/kernel/signal.c+48−43
@@ -365,38 +365,37 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, · 364 unmodified lines
365 365
366 frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate);366 frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate);
367 367
368 if (!access_ok(frame, sizeof(*frame)))368 if (!user_access_begin(frame, sizeof(*frame)))
369 return -EFAULT;369 return -EFAULT;
370 370
371 put_user_try {371 unsafe_put_user(sig, &frame->sig, Efault);
372 put_user_ex(sig, &frame->sig);372 unsafe_put_user(&frame->info, &frame->pinfo, Efault);
373 put_user_ex(&frame->info, &frame->pinfo);373 unsafe_put_user(&frame->uc, &frame->puc, Efault);
374 put_user_ex(&frame->uc, &frame->puc);
375 374
376 /* Create the ucontext. */375 /* Create the ucontext. */
377 if (static_cpu_has(X86_FEATURE_XSAVE))376 if (static_cpu_has(X86_FEATURE_XSAVE))
378 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);377 unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
379 else378 else
380 put_user_ex(0, &frame->uc.uc_flags);379 unsafe_put_user(0, &frame->uc.uc_flags, Efault);
381 put_user_ex(0, &frame->uc.uc_link);380 unsafe_put_user(0, &frame->uc.uc_link, Efault);
382 save_altstack_ex(&frame->uc.uc_stack, regs->sp);381 unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
383 382
384 /* Set up to return from userspace. */383 /* Set up to return from userspace. */
385 restorer = current->mm->context.vdso +384 restorer = current->mm->context.vdso +
386 vdso_image_32.sym___kernel_rt_sigreturn;385 vdso_image_32.sym___kernel_rt_sigreturn;
387 if (ksig->ka.sa.sa_flags & SA_RESTORER)386 if (ksig->ka.sa.sa_flags & SA_RESTORER)
388 restorer = ksig->ka.sa.sa_restorer;387 restorer = ksig->ka.sa.sa_restorer;
389 put_user_ex(restorer, &frame->pretcode);388 unsafe_put_user(restorer, &frame->pretcode, Efault);
390 389
391 /*390 /*
392 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80391 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
393 *392 *
394 * WE DO NOT USE IT ANY MORE! It's only left here for historical393 * WE DO NOT USE IT ANY MORE! It's only left here for historical
395 * reasons and because gdb uses it as a signature to notice394 * reasons and because gdb uses it as a signature to notice
396 * signal handler stack frames.395 * signal handler stack frames.
397 */396 */
398 put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);397 unsafe_put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode, Efault);
399 } put_user_catch(err);398 user_access_end();
400 399
401 err |= copy_siginfo_to_user(&frame->info, &ksig->info);400 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
402 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,401 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
@@ -419,6 +418,9 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, · 16 unmodified lines
419 regs->cs = __USER_CS;418 regs->cs = __USER_CS;
420 419
421 return 0;420 return 0;
421Efault:
422 user_access_end();
423 return -EFAULT;
422}424}
423#else /* !CONFIG_X86_32 */425#else /* !CONFIG_X86_32 */
424static unsigned long frame_uc_flags(struct pt_regs *regs)426static unsigned long frame_uc_flags(struct pt_regs *regs)
@@ -444,6 +446,10 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, · 19 unmodified lines
444 unsigned long uc_flags;446 unsigned long uc_flags;
445 int err = 0;447 int err = 0;
446 448
449 /* x86-64 should always use SA_RESTORER. */
450 if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
451 return -EFAULT;
452
447 frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp);453 frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp);
448 454
449 if (!access_ok(frame, sizeof(*frame)))455 if (!access_ok(frame, sizeof(*frame)))
@@ -455,23 +461,18 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, · 5 unmodified lines
455 }461 }
456 462
457 uc_flags = frame_uc_flags(regs);463 uc_flags = frame_uc_flags(regs);
464 if (!user_access_begin(frame, sizeof(*frame)))
465 return -EFAULT;
458 466
459 put_user_try {467 /* Create the ucontext. */
460 /* Create the ucontext. */468 unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
461 put_user_ex(uc_flags, &frame->uc.uc_flags);469 unsafe_put_user(0, &frame->uc.uc_link, Efault);
462 put_user_ex(0, &frame->uc.uc_link);470 unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
463 save_altstack_ex(&frame->uc.uc_stack, regs->sp);471
464 472 /* Set up to return from userspace. If provided, use a stub
465 /* Set up to return from userspace. If provided, use a stub473 already in userspace. */
466 already in userspace. */474 unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault);
467 /* x86-64 should always use SA_RESTORER. */475 user_access_end();
468 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
469 put_user_ex(ksig->ka.sa.sa_restorer, &frame->pretcode);
470 } else {
471 /* could use a vstub here */
472 err |= -EFAULT;
473 }
474 } put_user_catch(err);
475 476
476 err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);477 err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
477 err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);478 err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
@@ -515,6 +516,10 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, · 37 unmodified lines
515 force_valid_ss(regs);516 force_valid_ss(regs);
516 517
517 return 0;518 return 0;
519
520Efault:
521 user_access_end();
522 return -EFAULT;
518}523}
519#endif /* CONFIG_X86_32 */524#endif /* CONFIG_X86_32 */
520 525
include/linux/signal.h+4−4
@@ -444,12 +444,12 @@ void signals_init(void); · 443 unmodified lines
444int restore_altstack(const stack_t __user *);444int restore_altstack(const stack_t __user *);
445int __save_altstack(stack_t __user *, unsigned long);445int __save_altstack(stack_t __user *, unsigned long);
446 446
447#define save_altstack_ex(uss, sp) do { \447#define unsafe_save_altstack(uss, sp, label) do { \
448 stack_t __user *__uss = uss; \448 stack_t __user *__uss = uss; \
449 struct task_struct *t = current; \449 struct task_struct *t = current; \
450 put_user_ex((void __user *)t->sas_ss_sp, &__uss->ss_sp); \450 unsafe_put_user((void __user *)t->sas_ss_sp, &__uss->ss_sp, label); \
451 put_user_ex(t->sas_ss_flags, &__uss->ss_flags); \451 unsafe_put_user(t->sas_ss_flags, &__uss->ss_flags, label); \
452 put_user_ex(t->sas_ss_size, &__uss->ss_size); \452 unsafe_put_user(t->sas_ss_size, &__uss->ss_size, label); \
453 if (t->sas_ss_flags & SS_AUTODISARM) \453 if (t->sas_ss_flags & SS_AUTODISARM) \
454 sas_ss_reset(t); \454 sas_ss_reset(t); \
455} while (0);455} while (0);