aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/ia32
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r--arch/x86/ia32/ia32_signal.c68
1 files changed, 29 insertions, 39 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 4bc02b23674b..9ddf2fa0129d 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -197,23 +197,28 @@ struct rt_sigframe
197 /* fp state follows here */ 197 /* fp state follows here */
198}; 198};
199 199
200#define COPY(x) { \ 200#define COPY(x) { \
201 unsigned int reg; \ 201 err |= __get_user(regs->x, &sc->x); \
202 err |= __get_user(reg, &sc->x); \
203 regs->x = reg; \
204} 202}
205 203
206#define RELOAD_SEG(seg,mask) \ 204#define COPY_SEG_CPL3(seg) { \
207 { unsigned int cur; \ 205 unsigned short tmp; \
208 unsigned short pre; \ 206 err |= __get_user(tmp, &sc->seg); \
209 err |= __get_user(pre, &sc->seg); \ 207 regs->seg = tmp | 3; \
210 savesegment(seg, cur); \ 208}
211 pre |= mask; \ 209
212 if (pre != cur) loadsegment(seg, pre); } 210#define RELOAD_SEG(seg) { \
211 unsigned int cur, pre; \
212 err |= __get_user(pre, &sc->seg); \
213 savesegment(seg, cur); \
214 pre |= 3; \
215 if (pre != cur) \
216 loadsegment(seg, pre); \
217}
213 218
214static int ia32_restore_sigcontext(struct pt_regs *regs, 219static int ia32_restore_sigcontext(struct pt_regs *regs,
215 struct sigcontext_ia32 __user *sc, 220 struct sigcontext_ia32 __user *sc,
216 unsigned int *peax) 221 unsigned int *pax)
217{ 222{
218 unsigned int tmpflags, gs, oldgs, err = 0; 223 unsigned int tmpflags, gs, oldgs, err = 0;
219 void __user *buf; 224 void __user *buf;
@@ -240,18 +245,16 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
240 if (gs != oldgs) 245 if (gs != oldgs)
241 load_gs_index(gs); 246 load_gs_index(gs);
242 247
243 RELOAD_SEG(fs, 3); 248 RELOAD_SEG(fs);
244 RELOAD_SEG(ds, 3); 249 RELOAD_SEG(ds);
245 RELOAD_SEG(es, 3); 250 RELOAD_SEG(es);
246 251
247 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); 252 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
248 COPY(dx); COPY(cx); COPY(ip); 253 COPY(dx); COPY(cx); COPY(ip);
249 /* Don't touch extended registers */ 254 /* Don't touch extended registers */
250 255
251 err |= __get_user(regs->cs, &sc->cs); 256 COPY_SEG_CPL3(cs);
252 regs->cs |= 3; 257 COPY_SEG_CPL3(ss);
253 err |= __get_user(regs->ss, &sc->ss);
254 regs->ss |= 3;
255 258
256 err |= __get_user(tmpflags, &sc->flags); 259 err |= __get_user(tmpflags, &sc->flags);
257 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); 260 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
@@ -262,9 +265,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
262 buf = compat_ptr(tmp); 265 buf = compat_ptr(tmp);
263 err |= restore_i387_xstate_ia32(buf); 266 err |= restore_i387_xstate_ia32(buf);
264 267
265 err |= __get_user(tmp, &sc->ax); 268 err |= __get_user(*pax, &sc->ax);
266 *peax = tmp;
267
268 return err; 269 return err;
269} 270}
270 271
@@ -359,20 +360,15 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
359 err |= __put_user(regs->dx, &sc->dx); 360 err |= __put_user(regs->dx, &sc->dx);
360 err |= __put_user(regs->cx, &sc->cx); 361 err |= __put_user(regs->cx, &sc->cx);
361 err |= __put_user(regs->ax, &sc->ax); 362 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); 363 err |= __put_user(current->thread.trap_no, &sc->trapno);
365 err |= __put_user(current->thread.error_code, &sc->err); 364 err |= __put_user(current->thread.error_code, &sc->err);
366 err |= __put_user(regs->ip, &sc->ip); 365 err |= __put_user(regs->ip, &sc->ip);
366 err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
367 err |= __put_user(regs->flags, &sc->flags); 367 err |= __put_user(regs->flags, &sc->flags);
368 err |= __put_user(regs->sp, &sc->sp_at_signal); 368 err |= __put_user(regs->sp, &sc->sp_at_signal);
369 err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
369 370
370 tmp = save_i387_xstate_ia32(fpstate); 371 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 372
377 /* non-iBCS2 extensions.. */ 373 /* non-iBCS2 extensions.. */
378 err |= __put_user(mask, &sc->oldmask); 374 err |= __put_user(mask, &sc->oldmask);
@@ -408,6 +404,8 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
408 if (used_math()) { 404 if (used_math()) {
409 sp = sp - sig_xstate_ia32_size; 405 sp = sp - sig_xstate_ia32_size;
410 *fpstate = (struct _fpstate_ia32 *) sp; 406 *fpstate = (struct _fpstate_ia32 *) sp;
407 if (save_i387_xstate_ia32(*fpstate) < 0)
408 return (void __user *) -1L;
411 } 409 }
412 410
413 sp -= frame_size; 411 sp -= frame_size;
@@ -430,12 +428,10 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
430 u16 poplmovl; 428 u16 poplmovl;
431 u32 val; 429 u32 val;
432 u16 int80; 430 u16 int80;
433 u16 pad;
434 } __attribute__((packed)) code = { 431 } __attribute__((packed)) code = {
435 0xb858, /* popl %eax ; movl $...,%eax */ 432 0xb858, /* popl %eax ; movl $...,%eax */
436 __NR_ia32_sigreturn, 433 __NR_ia32_sigreturn,
437 0x80cd, /* int $0x80 */ 434 0x80cd, /* int $0x80 */
438 0,
439 }; 435 };
440 436
441 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); 437 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
@@ -511,8 +507,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
511 u8 movl; 507 u8 movl;
512 u32 val; 508 u32 val;
513 u16 int80; 509 u16 int80;
514 u16 pad; 510 u8 pad;
515 u8 pad2;
516 } __attribute__((packed)) code = { 511 } __attribute__((packed)) code = {
517 0xb8, 512 0xb8,
518 __NR_ia32_rt_sigreturn, 513 __NR_ia32_rt_sigreturn,
@@ -572,11 +567,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
572 regs->dx = (unsigned long) &frame->info; 567 regs->dx = (unsigned long) &frame->info;
573 regs->cx = (unsigned long) &frame->uc; 568 regs->cx = (unsigned long) &frame->uc;
574 569
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); 570 loadsegment(ds, __USER32_DS);
581 loadsegment(es, __USER32_DS); 571 loadsegment(es, __USER32_DS);
582 572