Skip to content

Commit 119cd59

Browse files
author
Al Viro
committed
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. Signed-off-by: Al Viro <[email protected]>
1 parent 57d563c commit 119cd59

File tree

2 files changed

+52
-47
lines changed

2 files changed

+52
-47
lines changed

arch/x86/kernel/signal.c

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -365,38 +365,37 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
365365

366366
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate);
367367

368-
if (!access_ok(frame, sizeof(*frame)))
368+
if (!user_access_begin(frame, sizeof(*frame)))
369369
return -EFAULT;
370370

371-
put_user_try {
372-
put_user_ex(sig, &frame->sig);
373-
put_user_ex(&frame->info, &frame->pinfo);
374-
put_user_ex(&frame->uc, &frame->puc);
371+
unsafe_put_user(sig, &frame->sig, Efault);
372+
unsafe_put_user(&frame->info, &frame->pinfo, Efault);
373+
unsafe_put_user(&frame->uc, &frame->puc, Efault);
375374

376-
/* Create the ucontext. */
377-
if (static_cpu_has(X86_FEATURE_XSAVE))
378-
put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
379-
else
380-
put_user_ex(0, &frame->uc.uc_flags);
381-
put_user_ex(0, &frame->uc.uc_link);
382-
save_altstack_ex(&frame->uc.uc_stack, regs->sp);
375+
/* Create the ucontext. */
376+
if (static_cpu_has(X86_FEATURE_XSAVE))
377+
unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
378+
else
379+
unsafe_put_user(0, &frame->uc.uc_flags, Efault);
380+
unsafe_put_user(0, &frame->uc.uc_link, Efault);
381+
unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
383382

384-
/* Set up to return from userspace. */
385-
restorer = current->mm->context.vdso +
386-
vdso_image_32.sym___kernel_rt_sigreturn;
387-
if (ksig->ka.sa.sa_flags & SA_RESTORER)
388-
restorer = ksig->ka.sa.sa_restorer;
389-
put_user_ex(restorer, &frame->pretcode);
383+
/* Set up to return from userspace. */
384+
restorer = current->mm->context.vdso +
385+
vdso_image_32.sym___kernel_rt_sigreturn;
386+
if (ksig->ka.sa.sa_flags & SA_RESTORER)
387+
restorer = ksig->ka.sa.sa_restorer;
388+
unsafe_put_user(restorer, &frame->pretcode, Efault);
390389

391-
/*
392-
* This is movl $__NR_rt_sigreturn, %ax ; int $0x80
393-
*
394-
* 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 notice
396-
* signal handler stack frames.
397-
*/
398-
put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
399-
} put_user_catch(err);
390+
/*
391+
* This is movl $__NR_rt_sigreturn, %ax ; int $0x80
392+
*
393+
* WE DO NOT USE IT ANY MORE! It's only left here for historical
394+
* reasons and because gdb uses it as a signature to notice
395+
* signal handler stack frames.
396+
*/
397+
unsafe_put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode, Efault);
398+
user_access_end();
400399

401400
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
402401
err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
@@ -419,6 +418,9 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
419418
regs->cs = __USER_CS;
420419

421420
return 0;
421+
Efault:
422+
user_access_end();
423+
return -EFAULT;
422424
}
423425
#else /* !CONFIG_X86_32 */
424426
static unsigned long frame_uc_flags(struct pt_regs *regs)
@@ -444,6 +446,10 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
444446
unsigned long uc_flags;
445447
int err = 0;
446448

449+
/* x86-64 should always use SA_RESTORER. */
450+
if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
451+
return -EFAULT;
452+
447453
frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp);
448454

449455
if (!access_ok(frame, sizeof(*frame)))
@@ -455,23 +461,18 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
455461
}
456462

457463
uc_flags = frame_uc_flags(regs);
464+
if (!user_access_begin(frame, sizeof(*frame)))
465+
return -EFAULT;
458466

459-
put_user_try {
460-
/* Create the ucontext. */
461-
put_user_ex(uc_flags, &frame->uc.uc_flags);
462-
put_user_ex(0, &frame->uc.uc_link);
463-
save_altstack_ex(&frame->uc.uc_stack, regs->sp);
464-
465-
/* Set up to return from userspace. If provided, use a stub
466-
already in userspace. */
467-
/* x86-64 should always use SA_RESTORER. */
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);
467+
/* Create the ucontext. */
468+
unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
469+
unsafe_put_user(0, &frame->uc.uc_link, Efault);
470+
unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
471+
472+
/* Set up to return from userspace. If provided, use a stub
473+
already in userspace. */
474+
unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault);
475+
user_access_end();
475476

476477
err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
477478
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,
515516
force_valid_ss(regs);
516517

517518
return 0;
519+
520+
Efault:
521+
user_access_end();
522+
return -EFAULT;
518523
}
519524
#endif /* CONFIG_X86_32 */
520525

include/linux/signal.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,12 @@ void signals_init(void);
444444
int restore_altstack(const stack_t __user *);
445445
int __save_altstack(stack_t __user *, unsigned long);
446446

447-
#define save_altstack_ex(uss, sp) do { \
447+
#define unsafe_save_altstack(uss, sp, label) do { \
448448
stack_t __user *__uss = uss; \
449449
struct task_struct *t = current; \
450-
put_user_ex((void __user *)t->sas_ss_sp, &__uss->ss_sp); \
451-
put_user_ex(t->sas_ss_flags, &__uss->ss_flags); \
452-
put_user_ex(t->sas_ss_size, &__uss->ss_size); \
450+
unsafe_put_user((void __user *)t->sas_ss_sp, &__uss->ss_sp, label); \
451+
unsafe_put_user(t->sas_ss_flags, &__uss->ss_flags, label); \
452+
unsafe_put_user(t->sas_ss_size, &__uss->ss_size, label); \
453453
if (t->sas_ss_flags & SS_AUTODISARM) \
454454
sas_ss_reset(t); \
455455
} while (0);

0 commit comments

Comments
 (0)