aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/um/signal_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/um/signal_64.c')
-rw-r--r--arch/x86/um/signal_64.c33
1 files changed, 7 insertions, 26 deletions
diff --git a/arch/x86/um/signal_64.c b/arch/x86/um/signal_64.c
index 4e5b9b07a8c7..74c2598b0b31 100644
--- a/arch/x86/um/signal_64.c
+++ b/arch/x86/um/signal_64.c
@@ -68,7 +68,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
68 68
69static int copy_sc_to_user(struct sigcontext __user *to, 69static int copy_sc_to_user(struct sigcontext __user *to,
70 struct _fpstate __user *to_fp, struct pt_regs *regs, 70 struct _fpstate __user *to_fp, struct pt_regs *regs,
71 unsigned long mask, unsigned long sp) 71 unsigned long mask)
72{ 72{
73 struct faultinfo * fi = &current->thread.arch.faultinfo; 73 struct faultinfo * fi = &current->thread.arch.faultinfo;
74 struct sigcontext sc; 74 struct sigcontext sc;
@@ -81,11 +81,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
81 PUTREG(DI, di); 81 PUTREG(DI, di);
82 PUTREG(SI, si); 82 PUTREG(SI, si);
83 PUTREG(BP, bp); 83 PUTREG(BP, bp);
84 /* 84 PUTREG(SP, sp);
85 * Must use original RSP, which is passed in, rather than what's in
86 * signal frame.
87 */
88 sc.sp = sp;
89 PUTREG(BX, bx); 85 PUTREG(BX, bx);
90 PUTREG(DX, dx); 86 PUTREG(DX, dx);
91 PUTREG(CX, cx); 87 PUTREG(CX, cx);
@@ -141,7 +137,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
141 siginfo_t *info, sigset_t *set) 137 siginfo_t *info, sigset_t *set)
142{ 138{
143 struct rt_sigframe __user *frame; 139 struct rt_sigframe __user *frame;
144 unsigned long save_sp = PT_REGS_RSP(regs);
145 int err = 0; 140 int err = 0;
146 struct task_struct *me = current; 141 struct task_struct *me = current;
147 142
@@ -159,26 +154,15 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
159 goto out; 154 goto out;
160 } 155 }
161 156
162 /*
163 * Update SP now because the page fault handler refuses to extend
164 * the stack if the faulting address is too far below the current
165 * SP, which frame now certainly is. If there's an error, the original
166 * value is restored on the way out.
167 * When writing the sigcontext to the stack, we have to write the
168 * original value, so that's passed to copy_sc_to_user, which does
169 * the right thing with it.
170 */
171 PT_REGS_RSP(regs) = (unsigned long) frame;
172
173 /* Create the ucontext. */ 157 /* Create the ucontext. */
174 err |= __put_user(0, &frame->uc.uc_flags); 158 err |= __put_user(0, &frame->uc.uc_flags);
175 err |= __put_user(0, &frame->uc.uc_link); 159 err |= __put_user(0, &frame->uc.uc_link);
176 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 160 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
177 err |= __put_user(sas_ss_flags(save_sp), 161 err |= __put_user(sas_ss_flags(PT_REGS_RSP(regs)),
178 &frame->uc.uc_stack.ss_flags); 162 &frame->uc.uc_stack.ss_flags);
179 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); 163 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
180 err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, 164 err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
181 set->sig[0], save_sp); 165 set->sig[0]);
182 err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); 166 err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
183 if (sizeof(*set) == 16) { 167 if (sizeof(*set) == 16) {
184 __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); 168 __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
@@ -197,10 +181,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
197 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); 181 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
198 else 182 else
199 /* could use a vstub here */ 183 /* could use a vstub here */
200 goto restore_sp; 184 return err;
201 185
202 if (err) 186 if (err)
203 goto restore_sp; 187 return err;
204 188
205 /* Set up registers for signal handler */ 189 /* Set up registers for signal handler */
206 { 190 {
@@ -209,6 +193,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
209 sig = ed->signal_invmap[sig]; 193 sig = ed->signal_invmap[sig];
210 } 194 }
211 195
196 PT_REGS_RSP(regs) = (unsigned long) frame;
212 PT_REGS_RDI(regs) = sig; 197 PT_REGS_RDI(regs) = sig;
213 /* In case the signal handler was declared without prototypes */ 198 /* In case the signal handler was declared without prototypes */
214 PT_REGS_RAX(regs) = 0; 199 PT_REGS_RAX(regs) = 0;
@@ -222,10 +207,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
222 PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; 207 PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;
223 out: 208 out:
224 return err; 209 return err;
225
226restore_sp:
227 PT_REGS_RSP(regs) = save_sp;
228 return err;
229} 210}
230 211
231long sys_rt_sigreturn(struct pt_regs *regs) 212long sys_rt_sigreturn(struct pt_regs *regs)