]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - arch/x86/ia32/ia32_signal.c
x86/fpu: Rename restore_xstate_sig() to fpu__restore_sig()
[mirror_ubuntu-hirsute-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 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>
78f7f1e5 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
9dfe99b7 200 err |= fpu__restore_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{
c5bedc68 310 struct fpu *fpu = &current->thread.fpu;
65ea5b03 311 unsigned long sp;
1da177e4
LT
312
313 /* Default to using normal stack */
65ea5b03 314 sp = regs->sp;
1da177e4
LT
315
316 /* This is the X/Open sanctioned signal stack switching. */
235b8022
AV
317 if (ksig->ka.sa.sa_flags & SA_ONSTACK)
318 sp = sigsp(sp, ksig);
1da177e4 319 /* This is the legacy signal stack switching. */
8bee3f0a 320 else if ((regs->ss & 0xffff) != __USER32_DS &&
235b8022
AV
321 !(ksig->ka.sa.sa_flags & SA_RESTORER) &&
322 ksig->ka.sa.sa_restorer)
323 sp = (unsigned long) ksig->ka.sa.sa_restorer;
1da177e4 324
c5bedc68 325 if (fpu->fpstate_active) {
72a671ce
SS
326 unsigned long fx_aligned, math_size;
327
328 sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size);
0ff8fef4 329 *fpstate = (struct _fpstate_ia32 __user *) sp;
c8e14041 330 if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned,
72a671ce 331 math_size) < 0)
99ea1b93 332 return (void __user *) -1L;
3c1c7f10
SS
333 }
334
65ea5b03 335 sp -= frame_size;
d347f372
MO
336 /* Align the stack pointer according to the i386 ABI,
337 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
65ea5b03
PA
338 sp = ((sp + 4) & -16ul) - 4;
339 return (void __user *) sp;
1da177e4
LT
340}
341
235b8022 342int ia32_setup_frame(int sig, struct ksignal *ksig,
99b9cdf7 343 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 344{
3b0d29ee 345 struct sigframe_ia32 __user *frame;
99b9cdf7 346 void __user *restorer;
1da177e4 347 int err = 0;
ab513701 348 void __user *fpstate = NULL;
1da177e4 349
99b9cdf7
TG
350 /* copy_to_user optimizes that into a single 8 byte store */
351 static const struct {
352 u16 poplmovl;
353 u32 val;
354 u16 int80;
99b9cdf7
TG
355 } __attribute__((packed)) code = {
356 0xb858, /* popl %eax ; movl $...,%eax */
357 __NR_ia32_sigreturn,
358 0x80cd, /* int $0x80 */
99b9cdf7
TG
359 };
360
235b8022 361 frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
1da177e4
LT
362
363 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 364 return -EFAULT;
1da177e4 365
2ba48e16 366 if (__put_user(sig, &frame->sig))
3d0aedd9 367 return -EFAULT;
1da177e4 368
2ba48e16 369 if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
3d0aedd9 370 return -EFAULT;
1da177e4
LT
371
372 if (_COMPAT_NSIG_WORDS > 1) {
2ba48e16
HS
373 if (__copy_to_user(frame->extramask, &set->sig[1],
374 sizeof(frame->extramask)))
3d0aedd9 375 return -EFAULT;
1da177e4 376 }
1da177e4 377
235b8022
AV
378 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
379 restorer = ksig->ka.sa.sa_restorer;
af65d648
RM
380 } else {
381 /* Return stub is in 32bit vsyscall page */
1a3e4ca4 382 if (current->mm->context.vdso)
6f121e54
AL
383 restorer = current->mm->context.vdso +
384 selected_vdso32->sym___kernel_sigreturn;
af65d648 385 else
ade1af77 386 restorer = &frame->retcode;
af65d648 387 }
99b9cdf7 388
3b4b7570
HS
389 put_user_try {
390 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
391
392 /*
393 * These are actually not used anymore, but left because some
394 * gdb versions depend on them as a marker.
395 */
0ff8fef4 396 put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
3b4b7570
HS
397 } put_user_catch(err);
398
1da177e4 399 if (err)
3d0aedd9 400 return -EFAULT;
1da177e4
LT
401
402 /* Set up registers for signal handler */
65ea5b03 403 regs->sp = (unsigned long) frame;
235b8022 404 regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
1da177e4 405
536e3ee4 406 /* Make -mregparm=3 work */
65ea5b03
PA
407 regs->ax = sig;
408 regs->dx = 0;
409 regs->cx = 0;
536e3ee4 410
b6edbb1e
JF
411 loadsegment(ds, __USER32_DS);
412 loadsegment(es, __USER32_DS);
1da177e4 413
99b9cdf7
TG
414 regs->cs = __USER32_CS;
415 regs->ss = __USER32_DS;
1da177e4 416
1d001df1 417 return 0;
1da177e4
LT
418}
419
235b8022 420int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
99b9cdf7 421 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 422{
3b0d29ee 423 struct rt_sigframe_ia32 __user *frame;
af65d648 424 void __user *restorer;
1da177e4 425 int err = 0;
ab513701 426 void __user *fpstate = NULL;
1da177e4 427
99b9cdf7
TG
428 /* __copy_to_user optimizes that into a single 8 byte store */
429 static const struct {
430 u8 movl;
431 u32 val;
432 u16 int80;
9cc3c49e 433 u8 pad;
99b9cdf7
TG
434 } __attribute__((packed)) code = {
435 0xb8,
436 __NR_ia32_rt_sigreturn,
437 0x80cd,
438 0,
439 };
440
235b8022 441 frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
1da177e4
LT
442
443 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 444 return -EFAULT;
1da177e4 445
3b4b7570
HS
446 put_user_try {
447 put_user_ex(sig, &frame->sig);
448 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
449 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
1da177e4 450
3b4b7570
HS
451 /* Create the ucontext. */
452 if (cpu_has_xsave)
453 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
454 else
455 put_user_ex(0, &frame->uc.uc_flags);
456 put_user_ex(0, &frame->uc.uc_link);
bd1c149a 457 compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
3b4b7570 458
235b8022
AV
459 if (ksig->ka.sa.sa_flags & SA_RESTORER)
460 restorer = ksig->ka.sa.sa_restorer;
3b4b7570 461 else
6f121e54
AL
462 restorer = current->mm->context.vdso +
463 selected_vdso32->sym___kernel_rt_sigreturn;
3b4b7570
HS
464 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
465
466 /*
467 * Not actually used anymore, but left because some gdb
468 * versions need it.
469 */
0ff8fef4 470 put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
3b4b7570 471 } put_user_catch(err);
1da177e4 472
235b8022 473 err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
5e88353d
PA
474 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
475 regs, set->sig[0]);
476 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
477
1da177e4 478 if (err)
3d0aedd9 479 return -EFAULT;
1da177e4
LT
480
481 /* Set up registers for signal handler */
65ea5b03 482 regs->sp = (unsigned long) frame;
235b8022 483 regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
1da177e4 484
a7aacdf9 485 /* Make -mregparm=3 work */
65ea5b03
PA
486 regs->ax = sig;
487 regs->dx = (unsigned long) &frame->info;
488 regs->cx = (unsigned long) &frame->uc;
a7aacdf9 489
b6edbb1e
JF
490 loadsegment(ds, __USER32_DS);
491 loadsegment(es, __USER32_DS);
99b9cdf7
TG
492
493 regs->cs = __USER32_CS;
494 regs->ss = __USER32_DS;
1da177e4 495
1d001df1 496 return 0;
1da177e4 497}