/arch/um/sys-i386/signal.c
C | 508 lines | 395 code | 78 blank | 35 comment | 44 complexity | 1124bd9688d2a89e41fe8f8871744158 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* 2 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL 4 */ 5 6#include <linux/ptrace.h> 7#include <asm/unistd.h> 8#include <asm/uaccess.h> 9#include <asm/ucontext.h> 10#include "frame_kern.h" 11#include "skas.h" 12 13void copy_sc(struct uml_pt_regs *regs, void *from) 14{ 15 struct sigcontext *sc = from; 16 17 REGS_GS(regs->gp) = sc->gs; 18 REGS_FS(regs->gp) = sc->fs; 19 REGS_ES(regs->gp) = sc->es; 20 REGS_DS(regs->gp) = sc->ds; 21 REGS_EDI(regs->gp) = sc->di; 22 REGS_ESI(regs->gp) = sc->si; 23 REGS_EBP(regs->gp) = sc->bp; 24 REGS_SP(regs->gp) = sc->sp; 25 REGS_EBX(regs->gp) = sc->bx; 26 REGS_EDX(regs->gp) = sc->dx; 27 REGS_ECX(regs->gp) = sc->cx; 28 REGS_EAX(regs->gp) = sc->ax; 29 REGS_IP(regs->gp) = sc->ip; 30 REGS_CS(regs->gp) = sc->cs; 31 REGS_EFLAGS(regs->gp) = sc->flags; 32 REGS_SS(regs->gp) = sc->ss; 33} 34 35/* 36 * FPU tag word conversions. 37 */ 38 39static inline unsigned short twd_i387_to_fxsr(unsigned short twd) 40{ 41 unsigned int tmp; /* to avoid 16 bit prefixes in the code */ 42 43 /* Transform each pair of bits into 01 (valid) or 00 (empty) */ 44 tmp = ~twd; 45 tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ 46 /* and move the valid bits to the lower byte. */ 47 tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ 48 tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ 49 tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ 50 return tmp; 51} 52 53static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) 54{ 55 struct _fpxreg *st = NULL; 56 unsigned long twd = (unsigned long) fxsave->twd; 57 unsigned long tag; 58 unsigned long ret = 0xffff0000; 59 int i; 60 61#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); 62 63 for (i = 0; i < 8; i++) { 64 if (twd & 0x1) { 65 st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); 66 67 switch (st->exponent & 0x7fff) { 68 case 0x7fff: 69 tag = 2; /* Special */ 70 break; 71 case 0x0000: 72 if ( !st->significand[0] && 73 !st->significand[1] && 74 !st->significand[2] && 75 !st->significand[3] ) { 76 tag = 1; /* Zero */ 77 } else { 78 tag = 2; /* Special */ 79 } 80 break; 81 default: 82 if (st->significand[3] & 0x8000) { 83 tag = 0; /* Valid */ 84 } else { 85 tag = 2; /* Special */ 86 } 87 break; 88 } 89 } else { 90 tag = 3; /* Empty */ 91 } 92 ret |= (tag << (2 * i)); 93 twd = twd >> 1; 94 } 95 return ret; 96} 97 98static int convert_fxsr_to_user(struct _fpstate __user *buf, 99 struct user_fxsr_struct *fxsave) 100{ 101 unsigned long env[7]; 102 struct _fpreg __user *to; 103 struct _fpxreg *from; 104 int i; 105 106 env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; 107 env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; 108 env[2] = twd_fxsr_to_i387(fxsave); 109 env[3] = fxsave->fip; 110 env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); 111 env[5] = fxsave->foo; 112 env[6] = fxsave->fos; 113 114 if (__copy_to_user(buf, env, 7 * sizeof(unsigned long))) 115 return 1; 116 117 to = &buf->_st[0]; 118 from = (struct _fpxreg *) &fxsave->st_space[0]; 119 for (i = 0; i < 8; i++, to++, from++) { 120 unsigned long __user *t = (unsigned long __user *)to; 121 unsigned long *f = (unsigned long *)from; 122 123 if (__put_user(*f, t) || 124 __put_user(*(f + 1), t + 1) || 125 __put_user(from->exponent, &to->exponent)) 126 return 1; 127 } 128 return 0; 129} 130 131static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, 132 struct _fpstate __user *buf) 133{ 134 unsigned long env[7]; 135 struct _fpxreg *to; 136 struct _fpreg __user *from; 137 int i; 138 139 if (copy_from_user( env, buf, 7 * sizeof(long))) 140 return 1; 141 142 fxsave->cwd = (unsigned short)(env[0] & 0xffff); 143 fxsave->swd = (unsigned short)(env[1] & 0xffff); 144 fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); 145 fxsave->fip = env[3]; 146 fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); 147 fxsave->fcs = (env[4] & 0xffff); 148 fxsave->foo = env[5]; 149 fxsave->fos = env[6]; 150 151 to = (struct _fpxreg *) &fxsave->st_space[0]; 152 from = &buf->_st[0]; 153 for (i = 0; i < 8; i++, to++, from++) { 154 unsigned long *t = (unsigned long *)to; 155 unsigned long __user *f = (unsigned long __user *)from; 156 157 if (__get_user(*t, f) || 158 __get_user(*(t + 1), f + 1) || 159 __get_user(to->exponent, &from->exponent)) 160 return 1; 161 } 162 return 0; 163} 164 165extern int have_fpx_regs; 166 167static int copy_sc_from_user(struct pt_regs *regs, 168 struct sigcontext __user *from) 169{ 170 struct sigcontext sc; 171 int err, pid; 172 173 err = copy_from_user(&sc, from, sizeof(sc)); 174 if (err) 175 return err; 176 177 pid = userspace_pid[current_thread_info()->cpu]; 178 copy_sc(®s->regs, &sc); 179 if (have_fpx_regs) { 180 struct user_fxsr_struct fpx; 181 182 err = copy_from_user(&fpx, 183 &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0], 184 sizeof(struct user_fxsr_struct)); 185 if (err) 186 return 1; 187 188 err = convert_fxsr_from_user(&fpx, sc.fpstate); 189 if (err) 190 return 1; 191 192 err = restore_fpx_registers(pid, (unsigned long *) &fpx); 193 if (err < 0) { 194 printk(KERN_ERR "copy_sc_from_user - " 195 "restore_fpx_registers failed, errno = %d\n", 196 -err); 197 return 1; 198 } 199 } 200 else { 201 struct user_i387_struct fp; 202 203 err = copy_from_user(&fp, sc.fpstate, 204 sizeof(struct user_i387_struct)); 205 if (err) 206 return 1; 207 208 err = restore_fp_registers(pid, (unsigned long *) &fp); 209 if (err < 0) { 210 printk(KERN_ERR "copy_sc_from_user - " 211 "restore_fp_registers failed, errno = %d\n", 212 -err); 213 return 1; 214 } 215 } 216 217 return 0; 218} 219 220static int copy_sc_to_user(struct sigcontext __user *to, 221 struct _fpstate __user *to_fp, struct pt_regs *regs, 222 unsigned long sp) 223{ 224 struct sigcontext sc; 225 struct faultinfo * fi = ¤t->thread.arch.faultinfo; 226 int err, pid; 227 228 sc.gs = REGS_GS(regs->regs.gp); 229 sc.fs = REGS_FS(regs->regs.gp); 230 sc.es = REGS_ES(regs->regs.gp); 231 sc.ds = REGS_DS(regs->regs.gp); 232 sc.di = REGS_EDI(regs->regs.gp); 233 sc.si = REGS_ESI(regs->regs.gp); 234 sc.bp = REGS_EBP(regs->regs.gp); 235 sc.sp = sp; 236 sc.bx = REGS_EBX(regs->regs.gp); 237 sc.dx = REGS_EDX(regs->regs.gp); 238 sc.cx = REGS_ECX(regs->regs.gp); 239 sc.ax = REGS_EAX(regs->regs.gp); 240 sc.ip = REGS_IP(regs->regs.gp); 241 sc.cs = REGS_CS(regs->regs.gp); 242 sc.flags = REGS_EFLAGS(regs->regs.gp); 243 sc.sp_at_signal = regs->regs.gp[UESP]; 244 sc.ss = regs->regs.gp[SS]; 245 sc.cr2 = fi->cr2; 246 sc.err = fi->error_code; 247 sc.trapno = fi->trap_no; 248 249 to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); 250 sc.fpstate = to_fp; 251 252 pid = userspace_pid[current_thread_info()->cpu]; 253 if (have_fpx_regs) { 254 struct user_fxsr_struct fpx; 255 256 err = save_fpx_registers(pid, (unsigned long *) &fpx); 257 if (err < 0){ 258 printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " 259 "failed, errno = %d\n", err); 260 return 1; 261 } 262 263 err = convert_fxsr_to_user(to_fp, &fpx); 264 if (err) 265 return 1; 266 267 err |= __put_user(fpx.swd, &to_fp->status); 268 err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); 269 if (err) 270 return 1; 271 272 if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, 273 sizeof(struct user_fxsr_struct))) 274 return 1; 275 } 276 else { 277 struct user_i387_struct fp; 278 279 err = save_fp_registers(pid, (unsigned long *) &fp); 280 if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) 281 return 1; 282 } 283 284 return copy_to_user(to, &sc, sizeof(sc)); 285} 286 287static int copy_ucontext_to_user(struct ucontext __user *uc, 288 struct _fpstate __user *fp, sigset_t *set, 289 unsigned long sp) 290{ 291 int err = 0; 292 293 err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); 294 err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); 295 err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); 296 err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); 297 err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); 298 return err; 299} 300 301struct sigframe 302{ 303 char __user *pretcode; 304 int sig; 305 struct sigcontext sc; 306 struct _fpstate fpstate; 307 unsigned long extramask[_NSIG_WORDS-1]; 308 char retcode[8]; 309}; 310 311struct rt_sigframe 312{ 313 char __user *pretcode; 314 int sig; 315 struct siginfo __user *pinfo; 316 void __user *puc; 317 struct siginfo info; 318 struct ucontext uc; 319 struct _fpstate fpstate; 320 char retcode[8]; 321}; 322 323int setup_signal_stack_sc(unsigned long stack_top, int sig, 324 struct k_sigaction *ka, struct pt_regs *regs, 325 sigset_t *mask) 326{ 327 struct sigframe __user *frame; 328 void __user *restorer; 329 unsigned long save_sp = PT_REGS_SP(regs); 330 int err = 0; 331 332 /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */ 333 stack_top = ((stack_top + 4) & -16UL) - 4; 334 frame = (struct sigframe __user *) stack_top - 1; 335 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 336 return 1; 337 338 restorer = frame->retcode; 339 if (ka->sa.sa_flags & SA_RESTORER) 340 restorer = ka->sa.sa_restorer; 341 342 /* Update SP now because the page fault handler refuses to extend 343 * the stack if the faulting address is too far below the current 344 * SP, which frame now certainly is. If there's an error, the original 345 * value is restored on the way out. 346 * When writing the sigcontext to the stack, we have to write the 347 * original value, so that's passed to copy_sc_to_user, which does 348 * the right thing with it. 349 */ 350 PT_REGS_SP(regs) = (unsigned long) frame; 351 352 err |= __put_user(restorer, &frame->pretcode); 353 err |= __put_user(sig, &frame->sig); 354 err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp); 355 err |= __put_user(mask->sig[0], &frame->sc.oldmask); 356 if (_NSIG_WORDS > 1) 357 err |= __copy_to_user(&frame->extramask, &mask->sig[1], 358 sizeof(frame->extramask)); 359 360 /* 361 * This is popl %eax ; movl $,%eax ; int $0x80 362 * 363 * WE DO NOT USE IT ANY MORE! It's only left here for historical 364 * reasons and because gdb uses it as a signature to notice 365 * signal handler stack frames. 366 */ 367 err |= __put_user(0xb858, (short __user *)(frame->retcode+0)); 368 err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); 369 err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); 370 371 if (err) 372 goto err; 373 374 PT_REGS_SP(regs) = (unsigned long) frame; 375 PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; 376 PT_REGS_EAX(regs) = (unsigned long) sig; 377 PT_REGS_EDX(regs) = (unsigned long) 0; 378 PT_REGS_ECX(regs) = (unsigned long) 0; 379 380 if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) 381 ptrace_notify(SIGTRAP); 382 return 0; 383 384err: 385 PT_REGS_SP(regs) = save_sp; 386 return err; 387} 388 389int setup_signal_stack_si(unsigned long stack_top, int sig, 390 struct k_sigaction *ka, struct pt_regs *regs, 391 siginfo_t *info, sigset_t *mask) 392{ 393 struct rt_sigframe __user *frame; 394 void __user *restorer; 395 unsigned long save_sp = PT_REGS_SP(regs); 396 int err = 0; 397 398 stack_top &= -8UL; 399 frame = (struct rt_sigframe __user *) stack_top - 1; 400 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 401 return 1; 402 403 restorer = frame->retcode; 404 if (ka->sa.sa_flags & SA_RESTORER) 405 restorer = ka->sa.sa_restorer; 406 407 /* See comment above about why this is here */ 408 PT_REGS_SP(regs) = (unsigned long) frame; 409 410 err |= __put_user(restorer, &frame->pretcode); 411 err |= __put_user(sig, &frame->sig); 412 err |= __put_user(&frame->info, &frame->pinfo); 413 err |= __put_user(&frame->uc, &frame->puc); 414 err |= copy_siginfo_to_user(&frame->info, info); 415 err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, 416 save_sp); 417 418 /* 419 * This is movl $,%eax ; int $0x80 420 * 421 * WE DO NOT USE IT ANY MORE! It's only left here for historical 422 * reasons and because gdb uses it as a signature to notice 423 * signal handler stack frames. 424 */ 425 err |= __put_user(0xb8, (char __user *)(frame->retcode+0)); 426 err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); 427 err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); 428 429 if (err) 430 goto err; 431 432 PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; 433 PT_REGS_EAX(regs) = (unsigned long) sig; 434 PT_REGS_EDX(regs) = (unsigned long) &frame->info; 435 PT_REGS_ECX(regs) = (unsigned long) &frame->uc; 436 437 if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) 438 ptrace_notify(SIGTRAP); 439 return 0; 440 441err: 442 PT_REGS_SP(regs) = save_sp; 443 return err; 444} 445 446long sys_sigreturn(struct pt_regs regs) 447{ 448 unsigned long sp = PT_REGS_SP(¤t->thread.regs); 449 struct sigframe __user *frame = (struct sigframe __user *)(sp - 8); 450 sigset_t set; 451 struct sigcontext __user *sc = &frame->sc; 452 unsigned long __user *oldmask = &sc->oldmask; 453 unsigned long __user *extramask = frame->extramask; 454 int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); 455 456 if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || 457 copy_from_user(&set.sig[1], extramask, sig_size)) 458 goto segfault; 459 460 sigdelsetmask(&set, ~_BLOCKABLE); 461 462 spin_lock_irq(¤t->sighand->siglock); 463 current->blocked = set; 464 recalc_sigpending(); 465 spin_unlock_irq(¤t->sighand->siglock); 466 467 if (copy_sc_from_user(¤t->thread.regs, sc)) 468 goto segfault; 469 470 /* Avoid ERESTART handling */ 471 PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; 472 return PT_REGS_SYSCALL_RET(¤t->thread.regs); 473 474 segfault: 475 force_sig(SIGSEGV, current); 476 return 0; 477} 478 479long sys_rt_sigreturn(struct pt_regs regs) 480{ 481 unsigned long sp = PT_REGS_SP(¤t->thread.regs); 482 struct rt_sigframe __user *frame = 483 (struct rt_sigframe __user *) (sp - 4); 484 sigset_t set; 485 struct ucontext __user *uc = &frame->uc; 486 int sig_size = _NSIG_WORDS * sizeof(unsigned long); 487 488 if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) 489 goto segfault; 490 491 sigdelsetmask(&set, ~_BLOCKABLE); 492 493 spin_lock_irq(¤t->sighand->siglock); 494 current->blocked = set; 495 recalc_sigpending(); 496 spin_unlock_irq(¤t->sighand->siglock); 497 498 if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) 499 goto segfault; 500 501 /* Avoid ERESTART handling */ 502 PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; 503 return PT_REGS_SYSCALL_RET(¤t->thread.regs); 504 505 segfault: 506 force_sig(SIGSEGV, current); 507 return 0; 508}