aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/ia32/ia32_signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/ia32/ia32_signal.c')
-rw-r--r--arch/x86/ia32/ia32_signal.c110
1 files changed, 38 insertions, 72 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 4bc02b23674b..9dabd00e9805 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -24,13 +24,14 @@
24#include <asm/ucontext.h> 24#include <asm/ucontext.h>
25#include <asm/uaccess.h> 25#include <asm/uaccess.h>
26#include <asm/i387.h> 26#include <asm/i387.h>
27#include <asm/ia32.h>
28#include <asm/ptrace.h> 27#include <asm/ptrace.h>
29#include <asm/ia32_unistd.h> 28#include <asm/ia32_unistd.h>
30#include <asm/user32.h> 29#include <asm/user32.h>
31#include <asm/sigcontext32.h> 30#include <asm/sigcontext32.h>
32#include <asm/proto.h> 31#include <asm/proto.h>
33#include <asm/vdso.h> 32#include <asm/vdso.h>
33#include <asm/sigframe.h>
34#include <asm/sys_ia32.h>
34 35
35#define DEBUG_SIG 0 36#define DEBUG_SIG 0
36 37
@@ -41,7 +42,6 @@
41 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \ 42 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
42 X86_EFLAGS_CF) 43 X86_EFLAGS_CF)
43 44
44asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
45void signal_fault(struct pt_regs *regs, void __user *frame, char *where); 45void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
46 46
47int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 47int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
@@ -173,47 +173,28 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
173/* 173/*
174 * Do a signal return; undo the signal stack. 174 * Do a signal return; undo the signal stack.
175 */ 175 */
176#define COPY(x) { \
177 err |= __get_user(regs->x, &sc->x); \
178}
176 179
177struct sigframe 180#define COPY_SEG_CPL3(seg) { \
178{ 181 unsigned short tmp; \
179 u32 pretcode; 182 err |= __get_user(tmp, &sc->seg); \
180 int sig; 183 regs->seg = tmp | 3; \
181 struct sigcontext_ia32 sc;
182 struct _fpstate_ia32 fpstate_unused; /* look at kernel/sigframe.h */
183 unsigned int extramask[_COMPAT_NSIG_WORDS-1];
184 char retcode[8];
185 /* fp state follows here */
186};
187
188struct rt_sigframe
189{
190 u32 pretcode;
191 int sig;
192 u32 pinfo;
193 u32 puc;
194 compat_siginfo_t info;
195 struct ucontext_ia32 uc;
196 char retcode[8];
197 /* fp state follows here */
198};
199
200#define COPY(x) { \
201 unsigned int reg; \
202 err |= __get_user(reg, &sc->x); \
203 regs->x = reg; \
204} 184}
205 185
206#define RELOAD_SEG(seg,mask) \ 186#define RELOAD_SEG(seg) { \
207 { unsigned int cur; \ 187 unsigned int cur, pre; \
208 unsigned short pre; \ 188 err |= __get_user(pre, &sc->seg); \
209 err |= __get_user(pre, &sc->seg); \ 189 savesegment(seg, cur); \
210 savesegment(seg, cur); \ 190 pre |= 3; \
211 pre |= mask; \ 191 if (pre != cur) \
212 if (pre != cur) loadsegment(seg, pre); } 192 loadsegment(seg, pre); \
193}
213 194
214static int ia32_restore_sigcontext(struct pt_regs *regs, 195static int ia32_restore_sigcontext(struct pt_regs *regs,
215 struct sigcontext_ia32 __user *sc, 196 struct sigcontext_ia32 __user *sc,
216 unsigned int *peax) 197 unsigned int *pax)
217{ 198{
218 unsigned int tmpflags, gs, oldgs, err = 0; 199 unsigned int tmpflags, gs, oldgs, err = 0;
219 void __user *buf; 200 void __user *buf;
@@ -240,18 +221,16 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
240 if (gs != oldgs) 221 if (gs != oldgs)
241 load_gs_index(gs); 222 load_gs_index(gs);
242 223
243 RELOAD_SEG(fs, 3); 224 RELOAD_SEG(fs);
244 RELOAD_SEG(ds, 3); 225 RELOAD_SEG(ds);
245 RELOAD_SEG(es, 3); 226 RELOAD_SEG(es);
246 227
247 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); 228 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
248 COPY(dx); COPY(cx); COPY(ip); 229 COPY(dx); COPY(cx); COPY(ip);
249 /* Don't touch extended registers */ 230 /* Don't touch extended registers */
250 231
251 err |= __get_user(regs->cs, &sc->cs); 232 COPY_SEG_CPL3(cs);
252 regs->cs |= 3; 233 COPY_SEG_CPL3(ss);
253 err |= __get_user(regs->ss, &sc->ss);
254 regs->ss |= 3;
255 234
256 err |= __get_user(tmpflags, &sc->flags); 235 err |= __get_user(tmpflags, &sc->flags);
257 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); 236 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
@@ -262,15 +241,13 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
262 buf = compat_ptr(tmp); 241 buf = compat_ptr(tmp);
263 err |= restore_i387_xstate_ia32(buf); 242 err |= restore_i387_xstate_ia32(buf);
264 243
265 err |= __get_user(tmp, &sc->ax); 244 err |= __get_user(*pax, &sc->ax);
266 *peax = tmp;
267
268 return err; 245 return err;
269} 246}
270 247
271asmlinkage long sys32_sigreturn(struct pt_regs *regs) 248asmlinkage long sys32_sigreturn(struct pt_regs *regs)
272{ 249{
273 struct sigframe __user *frame = (struct sigframe __user *)(regs->sp-8); 250 struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
274 sigset_t set; 251 sigset_t set;
275 unsigned int ax; 252 unsigned int ax;
276 253
@@ -300,12 +277,12 @@ badframe:
300 277
301asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) 278asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
302{ 279{
303 struct rt_sigframe __user *frame; 280 struct rt_sigframe_ia32 __user *frame;
304 sigset_t set; 281 sigset_t set;
305 unsigned int ax; 282 unsigned int ax;
306 struct pt_regs tregs; 283 struct pt_regs tregs;
307 284
308 frame = (struct rt_sigframe __user *)(regs->sp - 4); 285 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
309 286
310 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 287 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
311 goto badframe; 288 goto badframe;
@@ -359,20 +336,15 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
359 err |= __put_user(regs->dx, &sc->dx); 336 err |= __put_user(regs->dx, &sc->dx);
360 err |= __put_user(regs->cx, &sc->cx); 337 err |= __put_user(regs->cx, &sc->cx);
361 err |= __put_user(regs->ax, &sc->ax); 338 err |= __put_user(regs->ax, &sc->ax);
362 err |= __put_user(regs->cs, &sc->cs);
363 err |= __put_user(regs->ss, &sc->ss);
364 err |= __put_user(current->thread.trap_no, &sc->trapno); 339 err |= __put_user(current->thread.trap_no, &sc->trapno);
365 err |= __put_user(current->thread.error_code, &sc->err); 340 err |= __put_user(current->thread.error_code, &sc->err);
366 err |= __put_user(regs->ip, &sc->ip); 341 err |= __put_user(regs->ip, &sc->ip);
342 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
367 err |= __put_user(regs->flags, &sc->flags); 343 err |= __put_user(regs->flags, &sc->flags);
368 err |= __put_user(regs->sp, &sc->sp_at_signal); 344 err |= __put_user(regs->sp, &sc->sp_at_signal);
345 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
369 346
370 tmp = save_i387_xstate_ia32(fpstate); 347 err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate);
371 if (tmp < 0)
372 err = -EFAULT;
373 else
374 err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
375 &sc->fpstate);
376 348
377 /* non-iBCS2 extensions.. */ 349 /* non-iBCS2 extensions.. */
378 err |= __put_user(mask, &sc->oldmask); 350 err |= __put_user(mask, &sc->oldmask);
@@ -400,7 +372,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
400 } 372 }
401 373
402 /* This is the legacy signal stack switching. */ 374 /* This is the legacy signal stack switching. */
403 else if ((regs->ss & 0xffff) != __USER_DS && 375 else if ((regs->ss & 0xffff) != __USER32_DS &&
404 !(ka->sa.sa_flags & SA_RESTORER) && 376 !(ka->sa.sa_flags & SA_RESTORER) &&
405 ka->sa.sa_restorer) 377 ka->sa.sa_restorer)
406 sp = (unsigned long) ka->sa.sa_restorer; 378 sp = (unsigned long) ka->sa.sa_restorer;
@@ -408,6 +380,8 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
408 if (used_math()) { 380 if (used_math()) {
409 sp = sp - sig_xstate_ia32_size; 381 sp = sp - sig_xstate_ia32_size;
410 *fpstate = (struct _fpstate_ia32 *) sp; 382 *fpstate = (struct _fpstate_ia32 *) sp;
383 if (save_i387_xstate_ia32(*fpstate) < 0)
384 return (void __user *) -1L;
411 } 385 }
412 386
413 sp -= frame_size; 387 sp -= frame_size;
@@ -420,7 +394,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
420int ia32_setup_frame(int sig, struct k_sigaction *ka, 394int ia32_setup_frame(int sig, struct k_sigaction *ka,
421 compat_sigset_t *set, struct pt_regs *regs) 395 compat_sigset_t *set, struct pt_regs *regs)
422{ 396{
423 struct sigframe __user *frame; 397 struct sigframe_ia32 __user *frame;
424 void __user *restorer; 398 void __user *restorer;
425 int err = 0; 399 int err = 0;
426 void __user *fpstate = NULL; 400 void __user *fpstate = NULL;
@@ -430,12 +404,10 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
430 u16 poplmovl; 404 u16 poplmovl;
431 u32 val; 405 u32 val;
432 u16 int80; 406 u16 int80;
433 u16 pad;
434 } __attribute__((packed)) code = { 407 } __attribute__((packed)) code = {
435 0xb858, /* popl %eax ; movl $...,%eax */ 408 0xb858, /* popl %eax ; movl $...,%eax */
436 __NR_ia32_sigreturn, 409 __NR_ia32_sigreturn,
437 0x80cd, /* int $0x80 */ 410 0x80cd, /* int $0x80 */
438 0,
439 }; 411 };
440 412
441 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); 413 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
@@ -471,7 +443,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
471 * These are actually not used anymore, but left because some 443 * These are actually not used anymore, but left because some
472 * gdb versions depend on them as a marker. 444 * gdb versions depend on them as a marker.
473 */ 445 */
474 err |= __copy_to_user(frame->retcode, &code, 8); 446 err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
475 if (err) 447 if (err)
476 return -EFAULT; 448 return -EFAULT;
477 449
@@ -501,7 +473,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
501int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 473int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
502 compat_sigset_t *set, struct pt_regs *regs) 474 compat_sigset_t *set, struct pt_regs *regs)
503{ 475{
504 struct rt_sigframe __user *frame; 476 struct rt_sigframe_ia32 __user *frame;
505 void __user *restorer; 477 void __user *restorer;
506 int err = 0; 478 int err = 0;
507 void __user *fpstate = NULL; 479 void __user *fpstate = NULL;
@@ -511,8 +483,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
511 u8 movl; 483 u8 movl;
512 u32 val; 484 u32 val;
513 u16 int80; 485 u16 int80;
514 u16 pad; 486 u8 pad;
515 u8 pad2;
516 } __attribute__((packed)) code = { 487 } __attribute__((packed)) code = {
517 0xb8, 488 0xb8,
518 __NR_ia32_rt_sigreturn, 489 __NR_ia32_rt_sigreturn,
@@ -559,7 +530,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
559 * Not actually used anymore, but left because some gdb 530 * Not actually used anymore, but left because some gdb
560 * versions need it. 531 * versions need it.
561 */ 532 */
562 err |= __copy_to_user(frame->retcode, &code, 8); 533 err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
563 if (err) 534 if (err)
564 return -EFAULT; 535 return -EFAULT;
565 536
@@ -572,11 +543,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
572 regs->dx = (unsigned long) &frame->info; 543 regs->dx = (unsigned long) &frame->info;
573 regs->cx = (unsigned long) &frame->uc; 544 regs->cx = (unsigned long) &frame->uc;
574 545
575 /* Make -mregparm=3 work */
576 regs->ax = sig;
577 regs->dx = (unsigned long) &frame->info;
578 regs->cx = (unsigned long) &frame->uc;
579
580 loadsegment(ds, __USER32_DS); 546 loadsegment(ds, __USER32_DS);
581 loadsegment(es, __USER32_DS); 547 loadsegment(es, __USER32_DS);
582 548