Commit 39f16c1c authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent d2d2728d
...@@ -326,35 +326,34 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, ...@@ -326,35 +326,34 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate); frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
if (!access_ok(frame, sizeof(*frame))) if (!user_access_begin(frame, sizeof(*frame)))
return -EFAULT; return -EFAULT;
put_user_try { unsafe_put_user(sig, &frame->sig, Efault);
put_user_ex(sig, &frame->sig); unsafe_put_user(ptr_to_compat(&frame->info), &frame->pinfo, Efault);
put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); unsafe_put_user(ptr_to_compat(&frame->uc), &frame->puc, Efault);
put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
/* Create the ucontext. */ /* Create the ucontext. */
if (static_cpu_has(X86_FEATURE_XSAVE)) if (static_cpu_has(X86_FEATURE_XSAVE))
put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
else else
put_user_ex(0, &frame->uc.uc_flags); unsafe_put_user(0, &frame->uc.uc_flags, Efault);
put_user_ex(0, &frame->uc.uc_link); unsafe_put_user(0, &frame->uc.uc_link, Efault);
compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
if (ksig->ka.sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer; restorer = ksig->ka.sa.sa_restorer;
else else
restorer = current->mm->context.vdso + restorer = current->mm->context.vdso +
vdso_image_32.sym___kernel_rt_sigreturn; vdso_image_32.sym___kernel_rt_sigreturn;
put_user_ex(ptr_to_compat(restorer), &frame->pretcode); unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault);
/* /*
* Not actually used anymore, but left because some gdb * Not actually used anymore, but left because some gdb
* versions need it. * versions need it.
*/ */
put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault);
} put_user_catch(err); user_access_end();
err |= __copy_siginfo_to_user32(&frame->info, &ksig->info, false); err |= __copy_siginfo_to_user32(&frame->info, &ksig->info, false);
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
...@@ -380,4 +379,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, ...@@ -380,4 +379,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
regs->ss = __USER32_DS; regs->ss = __USER32_DS;
return 0; return 0;
Efault:
user_access_end();
return -EFAULT;
} }
...@@ -529,6 +529,9 @@ static int x32_setup_rt_frame(struct ksignal *ksig, ...@@ -529,6 +529,9 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
int err = 0; int err = 0;
void __user *fpstate = NULL; void __user *fpstate = NULL;
if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
return -EFAULT;
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate);
if (!access_ok(frame, sizeof(*frame))) if (!access_ok(frame, sizeof(*frame)))
...@@ -541,22 +544,17 @@ static int x32_setup_rt_frame(struct ksignal *ksig, ...@@ -541,22 +544,17 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
uc_flags = frame_uc_flags(regs); uc_flags = frame_uc_flags(regs);
put_user_try { if (!user_access_begin(frame, sizeof(*frame)))
/* Create the ucontext. */ return -EFAULT;
put_user_ex(uc_flags, &frame->uc.uc_flags);
put_user_ex(0, &frame->uc.uc_link);
compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
put_user_ex(0, &frame->uc.uc__pad0);
if (ksig->ka.sa.sa_flags & SA_RESTORER) { /* Create the ucontext. */
restorer = ksig->ka.sa.sa_restorer; unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
} else { unsafe_put_user(0, &frame->uc.uc_link, Efault);
/* could use a vstub here */ unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
restorer = NULL; unsafe_put_user(0, &frame->uc.uc__pad0, Efault);
err |= -EFAULT; restorer = ksig->ka.sa.sa_restorer;
} unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault);
put_user_ex(restorer, (unsigned long __user *)&frame->pretcode); user_access_end();
} put_user_catch(err);
err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
regs, set->sig[0]); regs, set->sig[0]);
...@@ -582,6 +580,11 @@ static int x32_setup_rt_frame(struct ksignal *ksig, ...@@ -582,6 +580,11 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
#endif /* CONFIG_X86_X32_ABI */ #endif /* CONFIG_X86_X32_ABI */
return 0; return 0;
#ifdef CONFIG_X86_X32_ABI
Efault:
user_access_end();
return -EFAULT;
#endif
} }
/* /*
......
...@@ -483,12 +483,13 @@ extern void __user *compat_alloc_user_space(unsigned long len); ...@@ -483,12 +483,13 @@ extern void __user *compat_alloc_user_space(unsigned long len);
int compat_restore_altstack(const compat_stack_t __user *uss); int compat_restore_altstack(const compat_stack_t __user *uss);
int __compat_save_altstack(compat_stack_t __user *, unsigned long); int __compat_save_altstack(compat_stack_t __user *, unsigned long);
#define compat_save_altstack_ex(uss, sp) do { \ #define unsafe_compat_save_altstack(uss, sp, label) do { \
compat_stack_t __user *__uss = uss; \ compat_stack_t __user *__uss = uss; \
struct task_struct *t = current; \ struct task_struct *t = current; \
put_user_ex(ptr_to_compat((void __user *)t->sas_ss_sp), &__uss->ss_sp); \ unsafe_put_user(ptr_to_compat((void __user *)t->sas_ss_sp), \
put_user_ex(t->sas_ss_flags, &__uss->ss_flags); \ &__uss->ss_sp, label); \
put_user_ex(t->sas_ss_size, &__uss->ss_size); \ unsafe_put_user(t->sas_ss_flags, &__uss->ss_flags, label); \
unsafe_put_user(t->sas_ss_size, &__uss->ss_size, label); \
if (t->sas_ss_flags & SS_AUTODISARM) \ if (t->sas_ss_flags & SS_AUTODISARM) \
sas_ss_reset(t); \ sas_ss_reset(t); \
} while (0); } while (0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment