]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - arch/x86/ia32/ia32_signal.c
x86: signal: use {get|put}_user_try and catch
[mirror_ubuntu-focal-kernel.git] / arch / x86 / ia32 / ia32_signal.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/x86_64/ia32/ia32_signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
8 * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
1da177e4
LT
9 */
10
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
1da177e4
LT
14#include <linux/kernel.h>
15#include <linux/signal.h>
16#include <linux/errno.h>
17#include <linux/wait.h>
18#include <linux/ptrace.h>
19#include <linux/unistd.h>
20#include <linux/stddef.h>
21#include <linux/personality.h>
22#include <linux/compat.h>
9fbbd4dd 23#include <linux/binfmts.h>
1da177e4
LT
24#include <asm/ucontext.h>
25#include <asm/uaccess.h>
26#include <asm/i387.h>
1da177e4
LT
27#include <asm/ptrace.h>
28#include <asm/ia32_unistd.h>
29#include <asm/user32.h>
30#include <asm/sigcontext32.h>
1da177e4 31#include <asm/proto.h>
af65d648 32#include <asm/vdso.h>
d98f9d84 33#include <asm/sigframe.h>
2f06de06 34#include <asm/sys_ia32.h>
d98f9d84 35
1da177e4
LT
36#define DEBUG_SIG 0
37
38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39
fbdb7da9
HS
40#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
41 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
42 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
43 X86_EFLAGS_CF)
44
1da177e4
LT
45void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
46
47int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
48{
49 int err;
99b9cdf7
TG
50
51 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
1da177e4
LT
52 return -EFAULT;
53
54 /* If you change siginfo_t structure, please make sure that
55 this code is fixed accordingly.
56 It should never copy any pad contained in the structure
57 to avoid security leaks, but must copy the generic
58 3 ints plus the relevant union member. */
59 err = __put_user(from->si_signo, &to->si_signo);
60 err |= __put_user(from->si_errno, &to->si_errno);
99b9cdf7 61 err |= __put_user((short)from->si_code, &to->si_code);
1da177e4
LT
62
63 if (from->si_code < 0) {
64 err |= __put_user(from->si_pid, &to->si_pid);
99b9cdf7
TG
65 err |= __put_user(from->si_uid, &to->si_uid);
66 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
1da177e4 67 } else {
99b9cdf7
TG
68 /*
69 * First 32bits of unions are always present:
70 * si_pid === si_band === si_tid === si_addr(LS half)
71 */
72 err |= __put_user(from->_sifields._pad[0],
73 &to->_sifields._pad[0]);
1da177e4
LT
74 switch (from->si_code >> 16) {
75 case __SI_FAULT >> 16:
76 break;
77 case __SI_CHLD >> 16:
78 err |= __put_user(from->si_utime, &to->si_utime);
79 err |= __put_user(from->si_stime, &to->si_stime);
80 err |= __put_user(from->si_status, &to->si_status);
81 /* FALL THROUGH */
82 default:
83 case __SI_KILL >> 16:
84 err |= __put_user(from->si_uid, &to->si_uid);
85 break;
86 case __SI_POLL >> 16:
99b9cdf7 87 err |= __put_user(from->si_fd, &to->si_fd);
1da177e4
LT
88 break;
89 case __SI_TIMER >> 16:
99b9cdf7 90 err |= __put_user(from->si_overrun, &to->si_overrun);
1da177e4 91 err |= __put_user(ptr_to_compat(from->si_ptr),
99b9cdf7 92 &to->si_ptr);
1da177e4 93 break;
99b9cdf7
TG
94 /* This is not generated by the kernel as of now. */
95 case __SI_RT >> 16:
1da177e4
LT
96 case __SI_MESGQ >> 16:
97 err |= __put_user(from->si_uid, &to->si_uid);
98 err |= __put_user(from->si_int, &to->si_int);
99 break;
100 }
101 }
102 return err;
103}
104
105int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
106{
107 int err;
108 u32 ptr32;
99b9cdf7
TG
109
110 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
1da177e4
LT
111 return -EFAULT;
112
113 err = __get_user(to->si_signo, &from->si_signo);
114 err |= __get_user(to->si_errno, &from->si_errno);
115 err |= __get_user(to->si_code, &from->si_code);
116
117 err |= __get_user(to->si_pid, &from->si_pid);
118 err |= __get_user(to->si_uid, &from->si_uid);
119 err |= __get_user(ptr32, &from->si_ptr);
120 to->si_ptr = compat_ptr(ptr32);
121
122 return err;
123}
124
99b9cdf7 125asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
1da177e4 126{
1da177e4
LT
127 mask &= _BLOCKABLE;
128 spin_lock_irq(&current->sighand->siglock);
1d001df1 129 current->saved_sigmask = current->blocked;
1da177e4
LT
130 siginitset(&current->blocked, mask);
131 recalc_sigpending();
132 spin_unlock_irq(&current->sighand->siglock);
133
1d001df1
AK
134 current->state = TASK_INTERRUPTIBLE;
135 schedule();
5a8da0ea 136 set_restore_sigmask();
1d001df1 137 return -ERESTARTNOHAND;
1da177e4
LT
138}
139
99b9cdf7
TG
140asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
141 stack_ia32_t __user *uoss_ptr,
142 struct pt_regs *regs)
1da177e4 143{
99b9cdf7 144 stack_t uss, uoss;
1da177e4 145 int ret;
99b9cdf7
TG
146 mm_segment_t seg;
147
148 if (uss_ptr) {
1da177e4 149 u32 ptr;
99b9cdf7
TG
150
151 memset(&uss, 0, sizeof(stack_t));
152 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
1da177e4
LT
153 __get_user(ptr, &uss_ptr->ss_sp) ||
154 __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
155 __get_user(uss.ss_size, &uss_ptr->ss_size))
156 return -EFAULT;
157 uss.ss_sp = compat_ptr(ptr);
158 }
99b9cdf7
TG
159 seg = get_fs();
160 set_fs(KERNEL_DS);
65ea5b03 161 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
99b9cdf7 162 set_fs(seg);
1da177e4 163 if (ret >= 0 && uoss_ptr) {
99b9cdf7 164 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
1da177e4
LT
165 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
166 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
167 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
168 ret = -EFAULT;
99b9cdf7
TG
169 }
170 return ret;
1da177e4
LT
171}
172
173/*
174 * Do a signal return; undo the signal stack.
175 */
b78a5b52
HS
176#define COPY(x) { \
177 err |= __get_user(regs->x, &sc->x); \
1da177e4 178}
1da177e4 179
d71a68dc
HS
180#define COPY_SEG_CPL3(seg) { \
181 unsigned short tmp; \
182 err |= __get_user(tmp, &sc->seg); \
183 regs->seg = tmp | 3; \
1da177e4
LT
184}
185
8c6e5ce0
HS
186#define RELOAD_SEG(seg) { \
187 unsigned int cur, pre; \
188 err |= __get_user(pre, &sc->seg); \
189 savesegment(seg, cur); \
190 pre |= 3; \
191 if (pre != cur) \
192 loadsegment(seg, pre); \
193}
99b9cdf7
TG
194
195static int ia32_restore_sigcontext(struct pt_regs *regs,
196 struct sigcontext_ia32 __user *sc,
047ce935 197 unsigned int *pax)
99b9cdf7
TG
198{
199 unsigned int tmpflags, gs, oldgs, err = 0;
ab513701 200 void __user *buf;
99b9cdf7
TG
201 u32 tmp;
202
203 /* Always make any pending restarted system calls return -EINTR */
204 current_thread_info()->restart_block.fn = do_no_restart_syscall;
205
206#if DEBUG_SIG
207 printk(KERN_DEBUG "SIG restore_sigcontext: "
208 "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
65ea5b03 209 sc, sc->err, sc->ip, sc->cs, sc->flags);
99b9cdf7
TG
210#endif
211
212 /*
213 * Reload fs and gs if they have changed in the signal
214 * handler. This does not handle long fs/gs base changes in
215 * the handler, but does not clobber them at least in the
216 * normal case.
217 */
218 err |= __get_user(gs, &sc->gs);
219 gs |= 3;
b6edbb1e 220 savesegment(gs, oldgs);
99b9cdf7
TG
221 if (gs != oldgs)
222 load_gs_index(gs);
223
8c6e5ce0
HS
224 RELOAD_SEG(fs);
225 RELOAD_SEG(ds);
226 RELOAD_SEG(es);
1da177e4
LT
227
228 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
229 COPY(dx); COPY(cx); COPY(ip);
99b9cdf7
TG
230 /* Don't touch extended registers */
231
d71a68dc
HS
232 COPY_SEG_CPL3(cs);
233 COPY_SEG_CPL3(ss);
99b9cdf7 234
742fa54a 235 err |= __get_user(tmpflags, &sc->flags);
fbdb7da9 236 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
99b9cdf7 237 /* disable syscall checks */
65ea5b03 238 regs->orig_ax = -1;
99b9cdf7
TG
239
240 err |= __get_user(tmp, &sc->fpstate);
241 buf = compat_ptr(tmp);
ab513701 242 err |= restore_i387_xstate_ia32(buf);
1da177e4 243
047ce935 244 err |= __get_user(*pax, &sc->ax);
1da177e4 245 return err;
1da177e4
LT
246}
247
248asmlinkage long sys32_sigreturn(struct pt_regs *regs)
249{
3b0d29ee 250 struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
1da177e4 251 sigset_t set;
65ea5b03 252 unsigned int ax;
1da177e4
LT
253
254 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
255 goto badframe;
256 if (__get_user(set.sig[0], &frame->sc.oldmask)
257 || (_COMPAT_NSIG_WORDS > 1
99b9cdf7
TG
258 && __copy_from_user((((char *) &set.sig) + 4),
259 &frame->extramask,
1da177e4
LT
260 sizeof(frame->extramask))))
261 goto badframe;
262
263 sigdelsetmask(&set, ~_BLOCKABLE);
264 spin_lock_irq(&current->sighand->siglock);
265 current->blocked = set;
266 recalc_sigpending();
267 spin_unlock_irq(&current->sighand->siglock);
99b9cdf7 268
65ea5b03 269 if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
1da177e4 270 goto badframe;
65ea5b03 271 return ax;
1da177e4
LT
272
273badframe:
274 signal_fault(regs, frame, "32bit sigreturn");
275 return 0;
99b9cdf7 276}
1da177e4
LT
277
278asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
279{
3b0d29ee 280 struct rt_sigframe_ia32 __user *frame;
1da177e4 281 sigset_t set;
65ea5b03 282 unsigned int ax;
1da177e4
LT
283 struct pt_regs tregs;
284
3b0d29ee 285 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
1da177e4
LT
286
287 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
288 goto badframe;
289 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
290 goto badframe;
291
292 sigdelsetmask(&set, ~_BLOCKABLE);
293 spin_lock_irq(&current->sighand->siglock);
294 current->blocked = set;
295 recalc_sigpending();
296 spin_unlock_irq(&current->sighand->siglock);
99b9cdf7 297
65ea5b03 298 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
1da177e4
LT
299 goto badframe;
300
301 tregs = *regs;
302 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
303 goto badframe;
304
65ea5b03 305 return ax;
1da177e4
LT
306
307badframe:
99b9cdf7 308 signal_fault(regs, frame, "32bit rt sigreturn");
1da177e4 309 return 0;
99b9cdf7 310}
1da177e4
LT
311
312/*
313 * Set up a signal frame.
314 */
315
99b9cdf7 316static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
ab513701 317 void __user *fpstate,
99b9cdf7 318 struct pt_regs *regs, unsigned int mask)
1da177e4
LT
319{
320 int tmp, err = 0;
1da177e4 321
b6edbb1e 322 savesegment(gs, tmp);
1da177e4 323 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
b6edbb1e 324 savesegment(fs, tmp);
1da177e4 325 err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
b6edbb1e 326 savesegment(ds, tmp);
1da177e4 327 err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
b6edbb1e 328 savesegment(es, tmp);
1da177e4
LT
329 err |= __put_user(tmp, (unsigned int __user *)&sc->es);
330
bff0aa4b
HS
331 err |= __put_user(regs->di, &sc->di);
332 err |= __put_user(regs->si, &sc->si);
333 err |= __put_user(regs->bp, &sc->bp);
334 err |= __put_user(regs->sp, &sc->sp);
335 err |= __put_user(regs->bx, &sc->bx);
336 err |= __put_user(regs->dx, &sc->dx);
337 err |= __put_user(regs->cx, &sc->cx);
338 err |= __put_user(regs->ax, &sc->ax);
1da177e4
LT
339 err |= __put_user(current->thread.trap_no, &sc->trapno);
340 err |= __put_user(current->thread.error_code, &sc->err);
bff0aa4b 341 err |= __put_user(regs->ip, &sc->ip);
64977609 342 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
bff0aa4b
HS
343 err |= __put_user(regs->flags, &sc->flags);
344 err |= __put_user(regs->sp, &sc->sp_at_signal);
64977609 345 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
1da177e4 346
99ea1b93 347 err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate);
1da177e4
LT
348
349 /* non-iBCS2 extensions.. */
350 err |= __put_user(mask, &sc->oldmask);
351 err |= __put_user(current->thread.cr2, &sc->cr2);
352
353 return err;
354}
355
356/*
357 * Determine which stack to use..
358 */
99b9cdf7 359static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
3c1c7f10 360 size_t frame_size,
ab513701 361 void **fpstate)
1da177e4 362{
65ea5b03 363 unsigned long sp;
1da177e4
LT
364
365 /* Default to using normal stack */
65ea5b03 366 sp = regs->sp;
1da177e4
LT
367
368 /* This is the X/Open sanctioned signal stack switching. */
369 if (ka->sa.sa_flags & SA_ONSTACK) {
65ea5b03
PA
370 if (sas_ss_flags(sp) == 0)
371 sp = current->sas_ss_sp + current->sas_ss_size;
1da177e4
LT
372 }
373
374 /* This is the legacy signal stack switching. */
8bee3f0a 375 else if ((regs->ss & 0xffff) != __USER32_DS &&
1da177e4 376 !(ka->sa.sa_flags & SA_RESTORER) &&
99b9cdf7 377 ka->sa.sa_restorer)
65ea5b03 378 sp = (unsigned long) ka->sa.sa_restorer;
1da177e4 379
3c1c7f10
SS
380 if (used_math()) {
381 sp = sp - sig_xstate_ia32_size;
382 *fpstate = (struct _fpstate_ia32 *) sp;
99ea1b93
HS
383 if (save_i387_xstate_ia32(*fpstate) < 0)
384 return (void __user *) -1L;
3c1c7f10
SS
385 }
386
65ea5b03 387 sp -= frame_size;
d347f372
MO
388 /* Align the stack pointer according to the i386 ABI,
389 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
65ea5b03
PA
390 sp = ((sp + 4) & -16ul) - 4;
391 return (void __user *) sp;
1da177e4
LT
392}
393
0928d6ef 394int ia32_setup_frame(int sig, struct k_sigaction *ka,
99b9cdf7 395 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 396{
3b0d29ee 397 struct sigframe_ia32 __user *frame;
99b9cdf7 398 void __user *restorer;
1da177e4 399 int err = 0;
ab513701 400 void __user *fpstate = NULL;
1da177e4 401
99b9cdf7
TG
402 /* copy_to_user optimizes that into a single 8 byte store */
403 static const struct {
404 u16 poplmovl;
405 u32 val;
406 u16 int80;
99b9cdf7
TG
407 } __attribute__((packed)) code = {
408 0xb858, /* popl %eax ; movl $...,%eax */
409 __NR_ia32_sigreturn,
410 0x80cd, /* int $0x80 */
99b9cdf7
TG
411 };
412
3c1c7f10 413 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4
LT
414
415 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 416 return -EFAULT;
1da177e4 417
2ba48e16 418 if (__put_user(sig, &frame->sig))
3d0aedd9 419 return -EFAULT;
1da177e4 420
2ba48e16 421 if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
3d0aedd9 422 return -EFAULT;
1da177e4
LT
423
424 if (_COMPAT_NSIG_WORDS > 1) {
2ba48e16
HS
425 if (__copy_to_user(frame->extramask, &set->sig[1],
426 sizeof(frame->extramask)))
3d0aedd9 427 return -EFAULT;
1da177e4 428 }
1da177e4 429
af65d648 430 if (ka->sa.sa_flags & SA_RESTORER) {
99b9cdf7 431 restorer = ka->sa.sa_restorer;
af65d648
RM
432 } else {
433 /* Return stub is in 32bit vsyscall page */
1a3e4ca4 434 if (current->mm->context.vdso)
af65d648
RM
435 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
436 sigreturn);
437 else
ade1af77 438 restorer = &frame->retcode;
af65d648 439 }
99b9cdf7
TG
440 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
441
442 /*
443 * These are actually not used anymore, but left because some
444 * gdb versions depend on them as a marker.
445 */
d0b48ca1 446 err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
1da177e4 447 if (err)
3d0aedd9 448 return -EFAULT;
1da177e4
LT
449
450 /* Set up registers for signal handler */
65ea5b03
PA
451 regs->sp = (unsigned long) frame;
452 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 453
536e3ee4 454 /* Make -mregparm=3 work */
65ea5b03
PA
455 regs->ax = sig;
456 regs->dx = 0;
457 regs->cx = 0;
536e3ee4 458
b6edbb1e
JF
459 loadsegment(ds, __USER32_DS);
460 loadsegment(es, __USER32_DS);
1da177e4 461
99b9cdf7
TG
462 regs->cs = __USER32_CS;
463 regs->ss = __USER32_DS;
1da177e4 464
1da177e4 465#if DEBUG_SIG
99b9cdf7 466 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
65ea5b03 467 current->comm, current->pid, frame, regs->ip, frame->pretcode);
1da177e4
LT
468#endif
469
1d001df1 470 return 0;
1da177e4
LT
471}
472
0928d6ef 473int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
99b9cdf7 474 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 475{
3b0d29ee 476 struct rt_sigframe_ia32 __user *frame;
af65d648 477 void __user *restorer;
1da177e4 478 int err = 0;
ab513701 479 void __user *fpstate = NULL;
1da177e4 480
99b9cdf7
TG
481 /* __copy_to_user optimizes that into a single 8 byte store */
482 static const struct {
483 u8 movl;
484 u32 val;
485 u16 int80;
9cc3c49e 486 u8 pad;
99b9cdf7
TG
487 } __attribute__((packed)) code = {
488 0xb8,
489 __NR_ia32_rt_sigreturn,
490 0x80cd,
491 0,
492 };
493
3c1c7f10 494 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4
LT
495
496 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 497 return -EFAULT;
1da177e4 498
812b121d 499 err |= __put_user(sig, &frame->sig);
1da177e4
LT
500 err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
501 err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
502 err |= copy_siginfo_to_user32(&frame->info, info);
503 if (err)
3d0aedd9 504 return -EFAULT;
1da177e4
LT
505
506 /* Create the ucontext. */
c37b5efe
SS
507 if (cpu_has_xsave)
508 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
509 else
510 err |= __put_user(0, &frame->uc.uc_flags);
1da177e4
LT
511 err |= __put_user(0, &frame->uc.uc_link);
512 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
65ea5b03 513 err |= __put_user(sas_ss_flags(regs->sp),
1da177e4
LT
514 &frame->uc.uc_stack.ss_flags);
515 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
3c1c7f10 516 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
99b9cdf7 517 regs, set->sig[0]);
1da177e4
LT
518 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
519 if (err)
3d0aedd9 520 return -EFAULT;
1da177e4 521
99b9cdf7
TG
522 if (ka->sa.sa_flags & SA_RESTORER)
523 restorer = ka->sa.sa_restorer;
af65d648
RM
524 else
525 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
526 rt_sigreturn);
99b9cdf7 527 err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
1da177e4 528
99b9cdf7
TG
529 /*
530 * Not actually used anymore, but left because some gdb
531 * versions need it.
532 */
d0b48ca1 533 err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
1da177e4 534 if (err)
3d0aedd9 535 return -EFAULT;
1da177e4
LT
536
537 /* Set up registers for signal handler */
65ea5b03
PA
538 regs->sp = (unsigned long) frame;
539 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 540
a7aacdf9 541 /* Make -mregparm=3 work */
65ea5b03
PA
542 regs->ax = sig;
543 regs->dx = (unsigned long) &frame->info;
544 regs->cx = (unsigned long) &frame->uc;
a7aacdf9 545
b6edbb1e
JF
546 loadsegment(ds, __USER32_DS);
547 loadsegment(es, __USER32_DS);
99b9cdf7
TG
548
549 regs->cs = __USER32_CS;
550 regs->ss = __USER32_DS;
1da177e4 551
1da177e4 552#if DEBUG_SIG
99b9cdf7 553 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
65ea5b03 554 current->comm, current->pid, frame, regs->ip, frame->pretcode);
1da177e4
LT
555#endif
556
1d001df1 557 return 0;
1da177e4 558}