|
@@ -41,6 +41,8 @@
|
|
|
struct rt_sigframe {
|
|
|
struct siginfo info;
|
|
|
struct ucontext uc;
|
|
|
+ u64 fp;
|
|
|
+ u64 lr;
|
|
|
};
|
|
|
|
|
|
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
|
|
@@ -175,6 +177,10 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
|
|
|
struct aux_context __user *aux =
|
|
|
(struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
|
|
|
|
|
|
+ /* set up the stack frame for unwinding */
|
|
|
+ __put_user_error(regs->regs[29], &sf->fp, err);
|
|
|
+ __put_user_error(regs->regs[30], &sf->lr, err);
|
|
|
+
|
|
|
for (i = 0; i < 31; i++)
|
|
|
__put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
|
|
|
err);
|
|
@@ -210,9 +216,6 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
|
|
|
sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
|
|
|
|
|
|
- /* room for stack frame (FP, LR) */
|
|
|
- sp -= 16;
|
|
|
-
|
|
|
sp = (sp - framesize) & ~15;
|
|
|
frame = (void __user *)sp;
|
|
|
|
|
@@ -225,20 +228,14 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
|
|
return frame;
|
|
|
}
|
|
|
|
|
|
-static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
|
|
- void __user *frame, int usig)
|
|
|
+static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
|
|
+ void __user *frame, int usig)
|
|
|
{
|
|
|
- int err = 0;
|
|
|
__sigrestore_t sigtramp;
|
|
|
- unsigned long __user *sp = (unsigned long __user *)regs->sp;
|
|
|
-
|
|
|
- /* set up the stack frame */
|
|
|
- __put_user_error(regs->regs[29], sp - 2, err);
|
|
|
- __put_user_error(regs->regs[30], sp - 1, err);
|
|
|
|
|
|
regs->regs[0] = usig;
|
|
|
- regs->regs[29] = regs->sp - 16;
|
|
|
regs->sp = (unsigned long)frame;
|
|
|
+ regs->regs[29] = regs->sp + offsetof(struct rt_sigframe, fp);
|
|
|
regs->pc = (unsigned long)ka->sa.sa_handler;
|
|
|
|
|
|
if (ka->sa.sa_flags & SA_RESTORER)
|
|
@@ -247,8 +244,6 @@ static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
|
|
sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
|
|
|
|
|
|
regs->regs[30] = (unsigned long)sigtramp;
|
|
|
-
|
|
|
- return err;
|
|
|
}
|
|
|
|
|
|
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
|
@@ -272,13 +267,13 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
|
|
err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
|
|
|
|
|
|
err |= setup_sigframe(frame, regs, set);
|
|
|
- if (err == 0)
|
|
|
- err = setup_return(regs, ka, frame, usig);
|
|
|
-
|
|
|
- if (err == 0 && ka->sa.sa_flags & SA_SIGINFO) {
|
|
|
- err |= copy_siginfo_to_user(&frame->info, info);
|
|
|
- regs->regs[1] = (unsigned long)&frame->info;
|
|
|
- regs->regs[2] = (unsigned long)&frame->uc;
|
|
|
+ if (err == 0) {
|
|
|
+ setup_return(regs, ka, frame, usig);
|
|
|
+ if (ka->sa.sa_flags & SA_SIGINFO) {
|
|
|
+ err |= copy_siginfo_to_user(&frame->info, info);
|
|
|
+ regs->regs[1] = (unsigned long)&frame->info;
|
|
|
+ regs->regs[2] = (unsigned long)&frame->uc;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return err;
|