x86/fpu: Document fpu__unlazy_stopped()
[deliverable/linux.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 14#include <linux/kernel.h>
1da177e4
LT
15#include <linux/errno.h>
16#include <linux/wait.h>
1da177e4
LT
17#include <linux/unistd.h>
18#include <linux/stddef.h>
19#include <linux/personality.h>
20#include <linux/compat.h>
9fbbd4dd 21#include <linux/binfmts.h>
1da177e4
LT
22#include <asm/ucontext.h>
23#include <asm/uaccess.h>
1361b83a 24#include <asm/fpu-internal.h>
1da177e4
LT
25#include <asm/ptrace.h>
26#include <asm/ia32_unistd.h>
27#include <asm/user32.h>
28#include <asm/sigcontext32.h>
1da177e4 29#include <asm/proto.h>
af65d648 30#include <asm/vdso.h>
d98f9d84 31#include <asm/sigframe.h>
f28f0c23 32#include <asm/sighandling.h>
2f06de06 33#include <asm/sys_ia32.h>
49b8c695 34#include <asm/smap.h>
d98f9d84 35
ce395960 36int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
1da177e4 37{
3b4b7570 38 int err = 0;
0b91f45b 39 bool ia32 = test_thread_flag(TIF_IA32);
99b9cdf7
TG
40
41 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
1da177e4
LT
42 return -EFAULT;
43
3b4b7570
HS
44 put_user_try {
45 /* If you change siginfo_t structure, please make sure that
46 this code is fixed accordingly.
47 It should never copy any pad contained in the structure
48 to avoid security leaks, but must copy the generic
49 3 ints plus the relevant union member. */
50 put_user_ex(from->si_signo, &to->si_signo);
51 put_user_ex(from->si_errno, &to->si_errno);
52 put_user_ex((short)from->si_code, &to->si_code);
53
54 if (from->si_code < 0) {
55 put_user_ex(from->si_pid, &to->si_pid);
56 put_user_ex(from->si_uid, &to->si_uid);
57 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
58 } else {
59 /*
60 * First 32bits of unions are always present:
61 * si_pid === si_band === si_tid === si_addr(LS half)
62 */
63 put_user_ex(from->_sifields._pad[0],
64 &to->_sifields._pad[0]);
65 switch (from->si_code >> 16) {
66 case __SI_FAULT >> 16:
67 break;
a0727e8c
WD
68 case __SI_SYS >> 16:
69 put_user_ex(from->si_syscall, &to->si_syscall);
70 put_user_ex(from->si_arch, &to->si_arch);
71 break;
3b4b7570 72 case __SI_CHLD >> 16:
e7084fd5
PA
73 if (ia32) {
74 put_user_ex(from->si_utime, &to->si_utime);
75 put_user_ex(from->si_stime, &to->si_stime);
76 } else {
77 put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
78 put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
79 }
3b4b7570
HS
80 put_user_ex(from->si_status, &to->si_status);
81 /* FALL THROUGH */
82 default:
83 case __SI_KILL >> 16:
84 put_user_ex(from->si_uid, &to->si_uid);
85 break;
86 case __SI_POLL >> 16:
87 put_user_ex(from->si_fd, &to->si_fd);
88 break;
89 case __SI_TIMER >> 16:
90 put_user_ex(from->si_overrun, &to->si_overrun);
91 put_user_ex(ptr_to_compat(from->si_ptr),
92 &to->si_ptr);
93 break;
94 /* This is not generated by the kernel as of now. */
95 case __SI_RT >> 16:
96 case __SI_MESGQ >> 16:
97 put_user_ex(from->si_uid, &to->si_uid);
98 put_user_ex(from->si_int, &to->si_int);
99 break;
100 }
1da177e4 101 }
3b4b7570
HS
102 } put_user_catch(err);
103
1da177e4
LT
104 return err;
105}
106
107int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
108{
3b4b7570 109 int err = 0;
1da177e4 110 u32 ptr32;
99b9cdf7
TG
111
112 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
1da177e4
LT
113 return -EFAULT;
114
3b4b7570
HS
115 get_user_try {
116 get_user_ex(to->si_signo, &from->si_signo);
117 get_user_ex(to->si_errno, &from->si_errno);
118 get_user_ex(to->si_code, &from->si_code);
1da177e4 119
3b4b7570
HS
120 get_user_ex(to->si_pid, &from->si_pid);
121 get_user_ex(to->si_uid, &from->si_uid);
122 get_user_ex(ptr32, &from->si_ptr);
123 to->si_ptr = compat_ptr(ptr32);
124 } get_user_catch(err);
1da177e4
LT
125
126 return err;
127}
128
1da177e4
LT
129/*
130 * Do a signal return; undo the signal stack.
131 */
a967bb3f
HS
132#define loadsegment_gs(v) load_gs_index(v)
133#define loadsegment_fs(v) loadsegment(fs, v)
134#define loadsegment_ds(v) loadsegment(ds, v)
135#define loadsegment_es(v) loadsegment(es, v)
136
137#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
138#define set_user_seg(seg, v) loadsegment_##seg(v)
139
b78a5b52 140#define COPY(x) { \
3b4b7570 141 get_user_ex(regs->x, &sc->x); \
1da177e4 142}
1da177e4 143
8801ead4
HS
144#define GET_SEG(seg) ({ \
145 unsigned short tmp; \
146 get_user_ex(tmp, &sc->seg); \
147 tmp; \
148})
149
150#define COPY_SEG_CPL3(seg) do { \
151 regs->seg = GET_SEG(seg) | 3; \
152} while (0)
1da177e4 153
8c6e5ce0 154#define RELOAD_SEG(seg) { \
a967bb3f
HS
155 unsigned int pre = GET_SEG(seg); \
156 unsigned int cur = get_user_seg(seg); \
8c6e5ce0
HS
157 pre |= 3; \
158 if (pre != cur) \
a967bb3f 159 set_user_seg(seg, pre); \
8c6e5ce0 160}
99b9cdf7
TG
161
162static int ia32_restore_sigcontext(struct pt_regs *regs,
6a3713f0 163 struct sigcontext_ia32 __user *sc)
99b9cdf7 164{
a967bb3f 165 unsigned int tmpflags, err = 0;
ab513701 166 void __user *buf;
99b9cdf7
TG
167 u32 tmp;
168
169 /* Always make any pending restarted system calls return -EINTR */
f56141e3 170 current->restart_block.fn = do_no_restart_syscall;
99b9cdf7 171
3b4b7570
HS
172 get_user_try {
173 /*
174 * Reload fs and gs if they have changed in the signal
175 * handler. This does not handle long fs/gs base changes in
176 * the handler, but does not clobber them at least in the
177 * normal case.
178 */
a967bb3f 179 RELOAD_SEG(gs);
3b4b7570
HS
180 RELOAD_SEG(fs);
181 RELOAD_SEG(ds);
182 RELOAD_SEG(es);
183
184 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
6a3713f0 185 COPY(dx); COPY(cx); COPY(ip); COPY(ax);
3b4b7570
HS
186 /* Don't touch extended registers */
187
188 COPY_SEG_CPL3(cs);
189 COPY_SEG_CPL3(ss);
190
191 get_user_ex(tmpflags, &sc->flags);
192 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
193 /* disable syscall checks */
194 regs->orig_ax = -1;
195
196 get_user_ex(tmp, &sc->fpstate);
197 buf = compat_ptr(tmp);
3b4b7570
HS
198 } get_user_catch(err);
199
49b8c695 200 err |= restore_xstate_sig(buf, 1);
5e88353d 201
1daeaa31
BG
202 force_iret();
203
1da177e4 204 return err;
1da177e4
LT
205}
206
3fe26fa3 207asmlinkage long sys32_sigreturn(void)
1da177e4 208{
3fe26fa3 209 struct pt_regs *regs = current_pt_regs();
3b0d29ee 210 struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
1da177e4 211 sigset_t set;
1da177e4
LT
212
213 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
214 goto badframe;
215 if (__get_user(set.sig[0], &frame->sc.oldmask)
216 || (_COMPAT_NSIG_WORDS > 1
99b9cdf7
TG
217 && __copy_from_user((((char *) &set.sig) + 4),
218 &frame->extramask,
1da177e4
LT
219 sizeof(frame->extramask))))
220 goto badframe;
221
905f29e2 222 set_current_blocked(&set);
99b9cdf7 223
6a3713f0 224 if (ia32_restore_sigcontext(regs, &frame->sc))
1da177e4 225 goto badframe;
6a3713f0 226 return regs->ax;
1da177e4
LT
227
228badframe:
229 signal_fault(regs, frame, "32bit sigreturn");
230 return 0;
99b9cdf7 231}
1da177e4 232
3fe26fa3 233asmlinkage long sys32_rt_sigreturn(void)
1da177e4 234{
3fe26fa3 235 struct pt_regs *regs = current_pt_regs();
3b0d29ee 236 struct rt_sigframe_ia32 __user *frame;
1da177e4 237 sigset_t set;
1da177e4 238
3b0d29ee 239 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
1da177e4
LT
240
241 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
242 goto badframe;
243 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
244 goto badframe;
245
905f29e2 246 set_current_blocked(&set);
99b9cdf7 247
6a3713f0 248 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext))
1da177e4
LT
249 goto badframe;
250
90268439 251 if (compat_restore_altstack(&frame->uc.uc_stack))
1da177e4
LT
252 goto badframe;
253
6a3713f0 254 return regs->ax;
1da177e4
LT
255
256badframe:
99b9cdf7 257 signal_fault(regs, frame, "32bit rt sigreturn");
1da177e4 258 return 0;
99b9cdf7 259}
1da177e4
LT
260
261/*
262 * Set up a signal frame.
263 */
264
99b9cdf7 265static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
ab513701 266 void __user *fpstate,
99b9cdf7 267 struct pt_regs *regs, unsigned int mask)
1da177e4 268{
a967bb3f 269 int err = 0;
1da177e4 270
3b4b7570 271 put_user_try {
a967bb3f
HS
272 put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
273 put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
274 put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
275 put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
3b4b7570
HS
276
277 put_user_ex(regs->di, &sc->di);
278 put_user_ex(regs->si, &sc->si);
279 put_user_ex(regs->bp, &sc->bp);
280 put_user_ex(regs->sp, &sc->sp);
281 put_user_ex(regs->bx, &sc->bx);
282 put_user_ex(regs->dx, &sc->dx);
283 put_user_ex(regs->cx, &sc->cx);
284 put_user_ex(regs->ax, &sc->ax);
51e7dc70 285 put_user_ex(current->thread.trap_nr, &sc->trapno);
3b4b7570
HS
286 put_user_ex(current->thread.error_code, &sc->err);
287 put_user_ex(regs->ip, &sc->ip);
288 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
289 put_user_ex(regs->flags, &sc->flags);
290 put_user_ex(regs->sp, &sc->sp_at_signal);
291 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
292
293 put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
294
295 /* non-iBCS2 extensions.. */
296 put_user_ex(mask, &sc->oldmask);
297 put_user_ex(current->thread.cr2, &sc->cr2);
298 } put_user_catch(err);
1da177e4
LT
299
300 return err;
301}
302
303/*
304 * Determine which stack to use..
305 */
235b8022 306static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
3c1c7f10 307 size_t frame_size,
0ff8fef4 308 void __user **fpstate)
1da177e4 309{
65ea5b03 310 unsigned long sp;
1da177e4
LT
311
312 /* Default to using normal stack */
65ea5b03 313 sp = regs->sp;
1da177e4
LT
314
315 /* This is the X/Open sanctioned signal stack switching. */
235b8022
AV
316 if (ksig->ka.sa.sa_flags & SA_ONSTACK)
317 sp = sigsp(sp, ksig);
1da177e4 318 /* This is the legacy signal stack switching. */
8bee3f0a 319 else if ((regs->ss & 0xffff) != __USER32_DS &&
235b8022
AV
320 !(ksig->ka.sa.sa_flags & SA_RESTORER) &&
321 ksig->ka.sa.sa_restorer)
322 sp = (unsigned long) ksig->ka.sa.sa_restorer;
1da177e4 323
4c138410 324 if (current->flags & PF_USED_MATH) {
72a671ce
SS
325 unsigned long fx_aligned, math_size;
326
327 sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size);
0ff8fef4 328 *fpstate = (struct _fpstate_ia32 __user *) sp;
72a671ce
SS
329 if (save_xstate_sig(*fpstate, (void __user *)fx_aligned,
330 math_size) < 0)
99ea1b93 331 return (void __user *) -1L;
3c1c7f10
SS
332 }
333
65ea5b03 334 sp -= frame_size;
d347f372
MO
335 /* Align the stack pointer according to the i386 ABI,
336 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
65ea5b03
PA
337 sp = ((sp + 4) & -16ul) - 4;
338 return (void __user *) sp;
1da177e4
LT
339}
340
235b8022 341int ia32_setup_frame(int sig, struct ksignal *ksig,
99b9cdf7 342 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 343{
3b0d29ee 344 struct sigframe_ia32 __user *frame;
99b9cdf7 345 void __user *restorer;
1da177e4 346 int err = 0;
ab513701 347 void __user *fpstate = NULL;
1da177e4 348
99b9cdf7
TG
349 /* copy_to_user optimizes that into a single 8 byte store */
350 static const struct {
351 u16 poplmovl;
352 u32 val;
353 u16 int80;
99b9cdf7
TG
354 } __attribute__((packed)) code = {
355 0xb858, /* popl %eax ; movl $...,%eax */
356 __NR_ia32_sigreturn,
357 0x80cd, /* int $0x80 */
99b9cdf7
TG
358 };
359
235b8022 360 frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
1da177e4
LT
361
362 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 363 return -EFAULT;
1da177e4 364
2ba48e16 365 if (__put_user(sig, &frame->sig))
3d0aedd9 366 return -EFAULT;
1da177e4 367
2ba48e16 368 if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
3d0aedd9 369 return -EFAULT;
1da177e4
LT
370
371 if (_COMPAT_NSIG_WORDS > 1) {
2ba48e16
HS
372 if (__copy_to_user(frame->extramask, &set->sig[1],
373 sizeof(frame->extramask)))
3d0aedd9 374 return -EFAULT;
1da177e4 375 }
1da177e4 376
235b8022
AV
377 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
378 restorer = ksig->ka.sa.sa_restorer;
af65d648
RM
379 } else {
380 /* Return stub is in 32bit vsyscall page */
1a3e4ca4 381 if (current->mm->context.vdso)
6f121e54
AL
382 restorer = current->mm->context.vdso +
383 selected_vdso32->sym___kernel_sigreturn;
af65d648 384 else
ade1af77 385 restorer = &frame->retcode;
af65d648 386 }
99b9cdf7 387
3b4b7570
HS
388 put_user_try {
389 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
390
391 /*
392 * These are actually not used anymore, but left because some
393 * gdb versions depend on them as a marker.
394 */
0ff8fef4 395 put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
3b4b7570
HS
396 } put_user_catch(err);
397
1da177e4 398 if (err)
3d0aedd9 399 return -EFAULT;
1da177e4
LT
400
401 /* Set up registers for signal handler */
65ea5b03 402 regs->sp = (unsigned long) frame;
235b8022 403 regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
1da177e4 404
536e3ee4 405 /* Make -mregparm=3 work */
65ea5b03
PA
406 regs->ax = sig;
407 regs->dx = 0;
408 regs->cx = 0;
536e3ee4 409
b6edbb1e
JF
410 loadsegment(ds, __USER32_DS);
411 loadsegment(es, __USER32_DS);
1da177e4 412
99b9cdf7
TG
413 regs->cs = __USER32_CS;
414 regs->ss = __USER32_DS;
1da177e4 415
1d001df1 416 return 0;
1da177e4
LT
417}
418
235b8022 419int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
99b9cdf7 420 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 421{
3b0d29ee 422 struct rt_sigframe_ia32 __user *frame;
af65d648 423 void __user *restorer;
1da177e4 424 int err = 0;
ab513701 425 void __user *fpstate = NULL;
1da177e4 426
99b9cdf7
TG
427 /* __copy_to_user optimizes that into a single 8 byte store */
428 static const struct {
429 u8 movl;
430 u32 val;
431 u16 int80;
9cc3c49e 432 u8 pad;
99b9cdf7
TG
433 } __attribute__((packed)) code = {
434 0xb8,
435 __NR_ia32_rt_sigreturn,
436 0x80cd,
437 0,
438 };
439
235b8022 440 frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
1da177e4
LT
441
442 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 443 return -EFAULT;
1da177e4 444
3b4b7570
HS
445 put_user_try {
446 put_user_ex(sig, &frame->sig);
447 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
448 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
1da177e4 449
3b4b7570
HS
450 /* Create the ucontext. */
451 if (cpu_has_xsave)
452 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
453 else
454 put_user_ex(0, &frame->uc.uc_flags);
455 put_user_ex(0, &frame->uc.uc_link);
bd1c149a 456 compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
3b4b7570 457
235b8022
AV
458 if (ksig->ka.sa.sa_flags & SA_RESTORER)
459 restorer = ksig->ka.sa.sa_restorer;
3b4b7570 460 else
6f121e54
AL
461 restorer = current->mm->context.vdso +
462 selected_vdso32->sym___kernel_rt_sigreturn;
3b4b7570
HS
463 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
464
465 /*
466 * Not actually used anymore, but left because some gdb
467 * versions need it.
468 */
0ff8fef4 469 put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
3b4b7570 470 } put_user_catch(err);
1da177e4 471
235b8022 472 err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
5e88353d
PA
473 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
474 regs, set->sig[0]);
475 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
476
1da177e4 477 if (err)
3d0aedd9 478 return -EFAULT;
1da177e4
LT
479
480 /* Set up registers for signal handler */
65ea5b03 481 regs->sp = (unsigned long) frame;
235b8022 482 regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
1da177e4 483
a7aacdf9 484 /* Make -mregparm=3 work */
65ea5b03
PA
485 regs->ax = sig;
486 regs->dx = (unsigned long) &frame->info;
487 regs->cx = (unsigned long) &frame->uc;
a7aacdf9 488
b6edbb1e
JF
489 loadsegment(ds, __USER32_DS);
490 loadsegment(es, __USER32_DS);
99b9cdf7
TG
491
492 regs->cs = __USER32_CS;
493 regs->ss = __USER32_DS;
1da177e4 494
1d001df1 495 return 0;
1da177e4 496}
This page took 1.174265 seconds and 5 git commands to generate.