Skip to content

Commit 39f16c1

Browse files
author
Al Viro
committed
x86: get rid of put_user_try in {ia32,x32}_setup_rt_frame()
Straightforward, except for compat_save_altstack_ex() stuck in those. Replace that thing with an analogue that would use unsafe_put_user() instead of put_user_ex() (called unsafe_compat_save_altstack()) and be done with that... Signed-off-by: Al Viro <[email protected]>
1 parent d2d2728 commit 39f16c1

File tree

3 files changed

+49
-43
lines changed

3 files changed

+49
-43
lines changed

arch/x86/ia32/ia32_signal.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -326,35 +326,34 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
326326

327327
frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
328328

329-
if (!access_ok(frame, sizeof(*frame)))
329+
if (!user_access_begin(frame, sizeof(*frame)))
330330
return -EFAULT;
331331

332-
put_user_try {
333-
put_user_ex(sig, &frame->sig);
334-
put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
335-
put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
332+
unsafe_put_user(sig, &frame->sig, Efault);
333+
unsafe_put_user(ptr_to_compat(&frame->info), &frame->pinfo, Efault);
334+
unsafe_put_user(ptr_to_compat(&frame->uc), &frame->puc, Efault);
336335

337-
/* Create the ucontext. */
338-
if (static_cpu_has(X86_FEATURE_XSAVE))
339-
put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
340-
else
341-
put_user_ex(0, &frame->uc.uc_flags);
342-
put_user_ex(0, &frame->uc.uc_link);
343-
compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
336+
/* Create the ucontext. */
337+
if (static_cpu_has(X86_FEATURE_XSAVE))
338+
unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
339+
else
340+
unsafe_put_user(0, &frame->uc.uc_flags, Efault);
341+
unsafe_put_user(0, &frame->uc.uc_link, Efault);
342+
unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
344343

345-
if (ksig->ka.sa.sa_flags & SA_RESTORER)
346-
restorer = ksig->ka.sa.sa_restorer;
347-
else
348-
restorer = current->mm->context.vdso +
349-
vdso_image_32.sym___kernel_rt_sigreturn;
350-
put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
344+
if (ksig->ka.sa.sa_flags & SA_RESTORER)
345+
restorer = ksig->ka.sa.sa_restorer;
346+
else
347+
restorer = current->mm->context.vdso +
348+
vdso_image_32.sym___kernel_rt_sigreturn;
349+
unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault);
351350

352-
/*
353-
* Not actually used anymore, but left because some gdb
354-
* versions need it.
355-
*/
356-
put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
357-
} put_user_catch(err);
351+
/*
352+
* Not actually used anymore, but left because some gdb
353+
* versions need it.
354+
*/
355+
unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault);
356+
user_access_end();
358357

359358
err |= __copy_siginfo_to_user32(&frame->info, &ksig->info, false);
360359
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
@@ -380,4 +379,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
380379
regs->ss = __USER32_DS;
381380

382381
return 0;
382+
Efault:
383+
user_access_end();
384+
return -EFAULT;
383385
}

arch/x86/kernel/signal.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,9 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
529529
int err = 0;
530530
void __user *fpstate = NULL;
531531

532+
if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
533+
return -EFAULT;
534+
532535
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate);
533536

534537
if (!access_ok(frame, sizeof(*frame)))
@@ -541,22 +544,17 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
541544

542545
uc_flags = frame_uc_flags(regs);
543546

544-
put_user_try {
545-
/* Create the ucontext. */
546-
put_user_ex(uc_flags, &frame->uc.uc_flags);
547-
put_user_ex(0, &frame->uc.uc_link);
548-
compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
549-
put_user_ex(0, &frame->uc.uc__pad0);
547+
if (!user_access_begin(frame, sizeof(*frame)))
548+
return -EFAULT;
550549

551-
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
552-
restorer = ksig->ka.sa.sa_restorer;
553-
} else {
554-
/* could use a vstub here */
555-
restorer = NULL;
556-
err |= -EFAULT;
557-
}
558-
put_user_ex(restorer, (unsigned long __user *)&frame->pretcode);
559-
} put_user_catch(err);
550+
/* Create the ucontext. */
551+
unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
552+
unsafe_put_user(0, &frame->uc.uc_link, Efault);
553+
unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
554+
unsafe_put_user(0, &frame->uc.uc__pad0, Efault);
555+
restorer = ksig->ka.sa.sa_restorer;
556+
unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault);
557+
user_access_end();
560558

561559
err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
562560
regs, set->sig[0]);
@@ -582,6 +580,11 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
582580
#endif /* CONFIG_X86_X32_ABI */
583581

584582
return 0;
583+
#ifdef CONFIG_X86_X32_ABI
584+
Efault:
585+
user_access_end();
586+
return -EFAULT;
587+
#endif
585588
}
586589

587590
/*

include/linux/compat.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,13 @@ extern void __user *compat_alloc_user_space(unsigned long len);
483483

484484
int compat_restore_altstack(const compat_stack_t __user *uss);
485485
int __compat_save_altstack(compat_stack_t __user *, unsigned long);
486-
#define compat_save_altstack_ex(uss, sp) do { \
486+
#define unsafe_compat_save_altstack(uss, sp, label) do { \
487487
compat_stack_t __user *__uss = uss; \
488488
struct task_struct *t = current; \
489-
put_user_ex(ptr_to_compat((void __user *)t->sas_ss_sp), &__uss->ss_sp); \
490-
put_user_ex(t->sas_ss_flags, &__uss->ss_flags); \
491-
put_user_ex(t->sas_ss_size, &__uss->ss_size); \
489+
unsafe_put_user(ptr_to_compat((void __user *)t->sas_ss_sp), \
490+
&__uss->ss_sp, label); \
491+
unsafe_put_user(t->sas_ss_flags, &__uss->ss_flags, label); \
492+
unsafe_put_user(t->sas_ss_size, &__uss->ss_size, label); \
492493
if (t->sas_ss_flags & SS_AUTODISARM) \
493494
sas_ss_reset(t); \
494495
} while (0);

0 commit comments

Comments
 (0)