diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/sys-i386/signal.c | 59 | ||||
-rw-r--r-- | arch/um/sys-x86_64/signal.c | 56 |
2 files changed, 85 insertions, 30 deletions
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 7cd1a82dc8c2..33a40f5ef0d2 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c | |||
@@ -58,7 +58,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs, | |||
58 | } | 58 | } |
59 | 59 | ||
60 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | 60 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, |
61 | struct pt_regs *regs) | 61 | struct pt_regs *regs, unsigned long sp) |
62 | { | 62 | { |
63 | struct sigcontext sc; | 63 | struct sigcontext sc; |
64 | unsigned long fpregs[HOST_FP_SIZE]; | 64 | unsigned long fpregs[HOST_FP_SIZE]; |
@@ -72,7 +72,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | |||
72 | sc.edi = REGS_EDI(regs->regs.skas.regs); | 72 | sc.edi = REGS_EDI(regs->regs.skas.regs); |
73 | sc.esi = REGS_ESI(regs->regs.skas.regs); | 73 | sc.esi = REGS_ESI(regs->regs.skas.regs); |
74 | sc.ebp = REGS_EBP(regs->regs.skas.regs); | 74 | sc.ebp = REGS_EBP(regs->regs.skas.regs); |
75 | sc.esp = REGS_SP(regs->regs.skas.regs); | 75 | sc.esp = sp; |
76 | sc.ebx = REGS_EBX(regs->regs.skas.regs); | 76 | sc.ebx = REGS_EBX(regs->regs.skas.regs); |
77 | sc.edx = REGS_EDX(regs->regs.skas.regs); | 77 | sc.edx = REGS_EDX(regs->regs.skas.regs); |
78 | sc.ecx = REGS_ECX(regs->regs.skas.regs); | 78 | sc.ecx = REGS_ECX(regs->regs.skas.regs); |
@@ -132,7 +132,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | |||
132 | } | 132 | } |
133 | 133 | ||
134 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | 134 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, |
135 | struct sigcontext *from, int fpsize) | 135 | struct sigcontext *from, int fpsize, unsigned long sp) |
136 | { | 136 | { |
137 | struct _fpstate *to_fp, *from_fp; | 137 | struct _fpstate *to_fp, *from_fp; |
138 | int err; | 138 | int err; |
@@ -140,11 +140,18 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | |||
140 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); | 140 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); |
141 | from_fp = from->fpstate; | 141 | from_fp = from->fpstate; |
142 | err = copy_to_user(to, from, sizeof(*to)); | 142 | err = copy_to_user(to, from, sizeof(*to)); |
143 | |||
144 | /* The SP in the sigcontext is the updated one for the signal | ||
145 | * delivery. The sp passed in is the original, and this needs | ||
146 | * to be restored, so we stick it in separately. | ||
147 | */ | ||
148 | err |= copy_to_user(&SC_SP(to), sp, sizeof(sp)); | ||
149 | |||
143 | if(from_fp != NULL){ | 150 | if(from_fp != NULL){ |
144 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | 151 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); |
145 | err |= copy_to_user(to_fp, from_fp, fpsize); | 152 | err |= copy_to_user(to_fp, from_fp, fpsize); |
146 | } | 153 | } |
147 | return(err); | 154 | return err; |
148 | } | 155 | } |
149 | #endif | 156 | #endif |
150 | 157 | ||
@@ -159,11 +166,11 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from) | |||
159 | } | 166 | } |
160 | 167 | ||
161 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, | 168 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, |
162 | struct pt_regs *from) | 169 | struct pt_regs *from, unsigned long sp) |
163 | { | 170 | { |
164 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | 171 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), |
165 | sizeof(*fp)), | 172 | sizeof(*fp), sp), |
166 | copy_sc_to_user_skas(to, fp, from))); | 173 | copy_sc_to_user_skas(to, fp, from, sp))); |
167 | } | 174 | } |
168 | 175 | ||
169 | static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, | 176 | static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, |
@@ -174,7 +181,7 @@ static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, | |||
174 | err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); | 181 | err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); |
175 | err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); | 182 | err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); |
176 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); | 183 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); |
177 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs); | 184 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); |
178 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); | 185 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); |
179 | return(err); | 186 | return(err); |
180 | } | 187 | } |
@@ -207,6 +214,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
207 | { | 214 | { |
208 | struct sigframe __user *frame; | 215 | struct sigframe __user *frame; |
209 | void *restorer; | 216 | void *restorer; |
217 | unsigned long save_sp = PT_REGS_SP(regs); | ||
210 | int err = 0; | 218 | int err = 0; |
211 | 219 | ||
212 | stack_top &= -8UL; | 220 | stack_top &= -8UL; |
@@ -218,9 +226,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
218 | if(ka->sa.sa_flags & SA_RESTORER) | 226 | if(ka->sa.sa_flags & SA_RESTORER) |
219 | restorer = ka->sa.sa_restorer; | 227 | restorer = ka->sa.sa_restorer; |
220 | 228 | ||
229 | /* Update SP now because the page fault handler refuses to extend | ||
230 | * the stack if the faulting address is too far below the current | ||
231 | * SP, which frame now certainly is. If there's an error, the original | ||
232 | * value is restored on the way out. | ||
233 | * When writing the sigcontext to the stack, we have to write the | ||
234 | * original value, so that's passed to copy_sc_to_user, which does | ||
235 | * the right thing with it. | ||
236 | */ | ||
237 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
238 | |||
221 | err |= __put_user(restorer, &frame->pretcode); | 239 | err |= __put_user(restorer, &frame->pretcode); |
222 | err |= __put_user(sig, &frame->sig); | 240 | err |= __put_user(sig, &frame->sig); |
223 | err |= copy_sc_to_user(&frame->sc, NULL, regs); | 241 | err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp); |
224 | err |= __put_user(mask->sig[0], &frame->sc.oldmask); | 242 | err |= __put_user(mask->sig[0], &frame->sc.oldmask); |
225 | if (_NSIG_WORDS > 1) | 243 | if (_NSIG_WORDS > 1) |
226 | err |= __copy_to_user(&frame->extramask, &mask->sig[1], | 244 | err |= __copy_to_user(&frame->extramask, &mask->sig[1], |
@@ -238,7 +256,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
238 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); | 256 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); |
239 | 257 | ||
240 | if(err) | 258 | if(err) |
241 | return(err); | 259 | goto err; |
242 | 260 | ||
243 | PT_REGS_SP(regs) = (unsigned long) frame; | 261 | PT_REGS_SP(regs) = (unsigned long) frame; |
244 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; | 262 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; |
@@ -248,7 +266,11 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
248 | 266 | ||
249 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | 267 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) |
250 | ptrace_notify(SIGTRAP); | 268 | ptrace_notify(SIGTRAP); |
251 | return(0); | 269 | return 0; |
270 | |||
271 | err: | ||
272 | PT_REGS_SP(regs) = save_sp; | ||
273 | return err; | ||
252 | } | 274 | } |
253 | 275 | ||
254 | int setup_signal_stack_si(unsigned long stack_top, int sig, | 276 | int setup_signal_stack_si(unsigned long stack_top, int sig, |
@@ -257,6 +279,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
257 | { | 279 | { |
258 | struct rt_sigframe __user *frame; | 280 | struct rt_sigframe __user *frame; |
259 | void *restorer; | 281 | void *restorer; |
282 | unsigned long save_sp = PT_REGS_SP(regs); | ||
260 | int err = 0; | 283 | int err = 0; |
261 | 284 | ||
262 | stack_top &= -8UL; | 285 | stack_top &= -8UL; |
@@ -268,13 +291,16 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
268 | if(ka->sa.sa_flags & SA_RESTORER) | 291 | if(ka->sa.sa_flags & SA_RESTORER) |
269 | restorer = ka->sa.sa_restorer; | 292 | restorer = ka->sa.sa_restorer; |
270 | 293 | ||
294 | /* See comment above about why this is here */ | ||
295 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
296 | |||
271 | err |= __put_user(restorer, &frame->pretcode); | 297 | err |= __put_user(restorer, &frame->pretcode); |
272 | err |= __put_user(sig, &frame->sig); | 298 | err |= __put_user(sig, &frame->sig); |
273 | err |= __put_user(&frame->info, &frame->pinfo); | 299 | err |= __put_user(&frame->info, &frame->pinfo); |
274 | err |= __put_user(&frame->uc, &frame->puc); | 300 | err |= __put_user(&frame->uc, &frame->puc); |
275 | err |= copy_siginfo_to_user(&frame->info, info); | 301 | err |= copy_siginfo_to_user(&frame->info, info); |
276 | err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, | 302 | err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, |
277 | PT_REGS_SP(regs)); | 303 | save_sp); |
278 | 304 | ||
279 | /* | 305 | /* |
280 | * This is movl $,%eax ; int $0x80 | 306 | * This is movl $,%eax ; int $0x80 |
@@ -288,9 +314,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
288 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); | 314 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); |
289 | 315 | ||
290 | if(err) | 316 | if(err) |
291 | return(err); | 317 | goto err; |
292 | 318 | ||
293 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
294 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; | 319 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; |
295 | PT_REGS_EAX(regs) = (unsigned long) sig; | 320 | PT_REGS_EAX(regs) = (unsigned long) sig; |
296 | PT_REGS_EDX(regs) = (unsigned long) &frame->info; | 321 | PT_REGS_EDX(regs) = (unsigned long) &frame->info; |
@@ -298,7 +323,11 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
298 | 323 | ||
299 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | 324 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) |
300 | ptrace_notify(SIGTRAP); | 325 | ptrace_notify(SIGTRAP); |
301 | return(0); | 326 | return 0; |
327 | |||
328 | err: | ||
329 | PT_REGS_SP(regs) = save_sp; | ||
330 | return err; | ||
302 | } | 331 | } |
303 | 332 | ||
304 | long sys_sigreturn(struct pt_regs regs) | 333 | long sys_sigreturn(struct pt_regs regs) |
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index fe1d065332b1..e75c4e1838b0 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c | |||
@@ -55,7 +55,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs, | |||
55 | } | 55 | } |
56 | 56 | ||
57 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | 57 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, |
58 | struct pt_regs *regs, unsigned long mask) | 58 | struct pt_regs *regs, unsigned long mask, |
59 | unsigned long sp) | ||
59 | { | 60 | { |
60 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | 61 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; |
61 | int err = 0; | 62 | int err = 0; |
@@ -70,7 +71,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | |||
70 | err |= PUTREG(regs, RDI, to, rdi); | 71 | err |= PUTREG(regs, RDI, to, rdi); |
71 | err |= PUTREG(regs, RSI, to, rsi); | 72 | err |= PUTREG(regs, RSI, to, rsi); |
72 | err |= PUTREG(regs, RBP, to, rbp); | 73 | err |= PUTREG(regs, RBP, to, rbp); |
73 | err |= PUTREG(regs, RSP, to, rsp); | 74 | /* Must use orignal RSP, which is passed in, rather than what's in |
75 | * the pt_regs, because that's already been updated to point at the | ||
76 | * signal frame. | ||
77 | */ | ||
78 | err |= __put_user(sp, &to->rsp); | ||
74 | err |= PUTREG(regs, RBX, to, rbx); | 79 | err |= PUTREG(regs, RBX, to, rbx); |
75 | err |= PUTREG(regs, RDX, to, rdx); | 80 | err |= PUTREG(regs, RDX, to, rdx); |
76 | err |= PUTREG(regs, RCX, to, rcx); | 81 | err |= PUTREG(regs, RCX, to, rcx); |
@@ -102,7 +107,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | |||
102 | 107 | ||
103 | #ifdef CONFIG_MODE_TT | 108 | #ifdef CONFIG_MODE_TT |
104 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | 109 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, |
105 | int fpsize) | 110 | int fpsize) |
106 | { | 111 | { |
107 | struct _fpstate *to_fp, *from_fp; | 112 | struct _fpstate *to_fp, *from_fp; |
108 | unsigned long sigs; | 113 | unsigned long sigs; |
@@ -120,7 +125,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | |||
120 | } | 125 | } |
121 | 126 | ||
122 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | 127 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, |
123 | struct sigcontext *from, int fpsize) | 128 | struct sigcontext *from, int fpsize, unsigned long sp) |
124 | { | 129 | { |
125 | struct _fpstate *to_fp, *from_fp; | 130 | struct _fpstate *to_fp, *from_fp; |
126 | int err; | 131 | int err; |
@@ -128,11 +133,17 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | |||
128 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); | 133 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); |
129 | from_fp = from->fpstate; | 134 | from_fp = from->fpstate; |
130 | err = copy_to_user(to, from, sizeof(*to)); | 135 | err = copy_to_user(to, from, sizeof(*to)); |
136 | /* The SP in the sigcontext is the updated one for the signal | ||
137 | * delivery. The sp passed in is the original, and this needs | ||
138 | * to be restored, so we stick it in separately. | ||
139 | */ | ||
140 | err |= copy_to_user(&SC_SP(to), sp, sizeof(sp)); | ||
141 | |||
131 | if(from_fp != NULL){ | 142 | if(from_fp != NULL){ |
132 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | 143 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); |
133 | err |= copy_to_user(to_fp, from_fp, fpsize); | 144 | err |= copy_to_user(to_fp, from_fp, fpsize); |
134 | } | 145 | } |
135 | return(err); | 146 | return err; |
136 | } | 147 | } |
137 | 148 | ||
138 | #endif | 149 | #endif |
@@ -148,11 +159,12 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from) | |||
148 | } | 159 | } |
149 | 160 | ||
150 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, | 161 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, |
151 | struct pt_regs *from, unsigned long mask) | 162 | struct pt_regs *from, unsigned long mask, |
163 | unsigned long sp) | ||
152 | { | 164 | { |
153 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | 165 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), |
154 | sizeof(*fp)), | 166 | sizeof(*fp), sp), |
155 | copy_sc_to_user_skas(to, fp, from, mask))); | 167 | copy_sc_to_user_skas(to, fp, from, mask, sp))); |
156 | } | 168 | } |
157 | 169 | ||
158 | struct rt_sigframe | 170 | struct rt_sigframe |
@@ -170,6 +182,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
170 | { | 182 | { |
171 | struct rt_sigframe __user *frame; | 183 | struct rt_sigframe __user *frame; |
172 | struct _fpstate __user *fp = NULL; | 184 | struct _fpstate __user *fp = NULL; |
185 | unsigned long save_sp = PT_REGS_RSP(regs); | ||
173 | int err = 0; | 186 | int err = 0; |
174 | struct task_struct *me = current; | 187 | struct task_struct *me = current; |
175 | 188 | ||
@@ -193,14 +206,25 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
193 | goto out; | 206 | goto out; |
194 | } | 207 | } |
195 | 208 | ||
209 | /* Update SP now because the page fault handler refuses to extend | ||
210 | * the stack if the faulting address is too far below the current | ||
211 | * SP, which frame now certainly is. If there's an error, the original | ||
212 | * value is restored on the way out. | ||
213 | * When writing the sigcontext to the stack, we have to write the | ||
214 | * original value, so that's passed to copy_sc_to_user, which does | ||
215 | * the right thing with it. | ||
216 | */ | ||
217 | PT_REGS_RSP(regs) = (unsigned long) frame; | ||
218 | |||
196 | /* Create the ucontext. */ | 219 | /* Create the ucontext. */ |
197 | err |= __put_user(0, &frame->uc.uc_flags); | 220 | err |= __put_user(0, &frame->uc.uc_flags); |
198 | err |= __put_user(0, &frame->uc.uc_link); | 221 | err |= __put_user(0, &frame->uc.uc_link); |
199 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 222 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
200 | err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), | 223 | err |= __put_user(sas_ss_flags(save_sp), |
201 | &frame->uc.uc_stack.ss_flags); | 224 | &frame->uc.uc_stack.ss_flags); |
202 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 225 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
203 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | 226 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0], |
227 | save_sp); | ||
204 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | 228 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); |
205 | if (sizeof(*set) == 16) { | 229 | if (sizeof(*set) == 16) { |
206 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | 230 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
@@ -217,10 +241,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
217 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 241 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
218 | else | 242 | else |
219 | /* could use a vstub here */ | 243 | /* could use a vstub here */ |
220 | goto out; | 244 | goto restore_sp; |
221 | 245 | ||
222 | if (err) | 246 | if (err) |
223 | goto out; | 247 | goto restore_sp; |
224 | 248 | ||
225 | /* Set up registers for signal handler */ | 249 | /* Set up registers for signal handler */ |
226 | { | 250 | { |
@@ -238,10 +262,12 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
238 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; | 262 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; |
239 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; | 263 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; |
240 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; | 264 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; |
241 | |||
242 | PT_REGS_RSP(regs) = (unsigned long) frame; | ||
243 | out: | 265 | out: |
244 | return(err); | 266 | return err; |
267 | |||
268 | restore_sp: | ||
269 | PT_REGS_RSP(regs) = save_sp; | ||
270 | return err; | ||
245 | } | 271 | } |
246 | 272 | ||
247 | long sys_rt_sigreturn(struct pt_regs *regs) | 273 | long sys_rt_sigreturn(struct pt_regs *regs) |