diff options
| -rw-r--r-- | arch/ia64/include/asm/siginfo.h | 5 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/siginfo.h | 5 | ||||
| -rw-r--r-- | arch/x86/ia32/ia32_signal.c | 37 | ||||
| -rw-r--r-- | arch/x86/kernel/ptrace.c | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/signal_32.c | 136 | ||||
| -rw-r--r-- | arch/x86/kernel/signal_64.c | 139 | ||||
| -rw-r--r-- | arch/x86/kernel/traps_32.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/traps_64.c | 2 | ||||
| -rw-r--r-- | include/asm-generic/siginfo.h | 2 | ||||
| -rw-r--r-- | include/asm-parisc/siginfo.h | 5 | ||||
| -rw-r--r-- | include/asm-x86/ptrace.h | 6 | ||||
| -rw-r--r-- | include/asm-x86/traps.h | 12 |
12 files changed, 196 insertions, 164 deletions
diff --git a/arch/ia64/include/asm/siginfo.h b/arch/ia64/include/asm/siginfo.h index 9294e4b0c8bc..118d42979003 100644 --- a/arch/ia64/include/asm/siginfo.h +++ b/arch/ia64/include/asm/siginfo.h | |||
| @@ -113,11 +113,6 @@ typedef struct siginfo { | |||
| 113 | #undef NSIGSEGV | 113 | #undef NSIGSEGV |
| 114 | #define NSIGSEGV 3 | 114 | #define NSIGSEGV 3 |
| 115 | 115 | ||
| 116 | /* | ||
| 117 | * SIGTRAP si_codes | ||
| 118 | */ | ||
| 119 | #define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ | ||
| 120 | #define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */ | ||
| 121 | #undef NSIGTRAP | 116 | #undef NSIGTRAP |
| 122 | #define NSIGTRAP 4 | 117 | #define NSIGTRAP 4 |
| 123 | 118 | ||
diff --git a/arch/powerpc/include/asm/siginfo.h b/arch/powerpc/include/asm/siginfo.h index 12f1bce037be..49495b0534ed 100644 --- a/arch/powerpc/include/asm/siginfo.h +++ b/arch/powerpc/include/asm/siginfo.h | |||
| @@ -15,11 +15,6 @@ | |||
| 15 | 15 | ||
| 16 | #include <asm-generic/siginfo.h> | 16 | #include <asm-generic/siginfo.h> |
| 17 | 17 | ||
| 18 | /* | ||
| 19 | * SIGTRAP si_codes | ||
| 20 | */ | ||
| 21 | #define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ | ||
| 22 | #define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */ | ||
| 23 | #undef NSIGTRAP | 18 | #undef NSIGTRAP |
| 24 | #define NSIGTRAP 4 | 19 | #define NSIGTRAP 4 |
| 25 | 20 | ||
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 8d64c1bc8474..e47bed2440ee 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
| @@ -444,21 +444,18 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
| 444 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 444 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
| 445 | 445 | ||
| 446 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 446 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 447 | goto give_sigsegv; | 447 | return -EFAULT; |
| 448 | 448 | ||
| 449 | err |= __put_user(sig, &frame->sig); | 449 | if (__put_user(sig, &frame->sig)) |
| 450 | if (err) | 450 | return -EFAULT; |
| 451 | goto give_sigsegv; | ||
| 452 | 451 | ||
| 453 | err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); | 452 | if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) |
| 454 | if (err) | 453 | return -EFAULT; |
| 455 | goto give_sigsegv; | ||
| 456 | 454 | ||
| 457 | if (_COMPAT_NSIG_WORDS > 1) { | 455 | if (_COMPAT_NSIG_WORDS > 1) { |
| 458 | err |= __copy_to_user(frame->extramask, &set->sig[1], | 456 | if (__copy_to_user(frame->extramask, &set->sig[1], |
| 459 | sizeof(frame->extramask)); | 457 | sizeof(frame->extramask))) |
| 460 | if (err) | 458 | return -EFAULT; |
| 461 | goto give_sigsegv; | ||
| 462 | } | 459 | } |
| 463 | 460 | ||
| 464 | if (ka->sa.sa_flags & SA_RESTORER) { | 461 | if (ka->sa.sa_flags & SA_RESTORER) { |
| @@ -479,7 +476,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
| 479 | */ | 476 | */ |
| 480 | err |= __copy_to_user(frame->retcode, &code, 8); | 477 | err |= __copy_to_user(frame->retcode, &code, 8); |
| 481 | if (err) | 478 | if (err) |
| 482 | goto give_sigsegv; | 479 | return -EFAULT; |
| 483 | 480 | ||
| 484 | /* Set up registers for signal handler */ | 481 | /* Set up registers for signal handler */ |
| 485 | regs->sp = (unsigned long) frame; | 482 | regs->sp = (unsigned long) frame; |
| @@ -502,10 +499,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
| 502 | #endif | 499 | #endif |
| 503 | 500 | ||
| 504 | return 0; | 501 | return 0; |
| 505 | |||
| 506 | give_sigsegv: | ||
| 507 | force_sigsegv(sig, current); | ||
| 508 | return -EFAULT; | ||
| 509 | } | 502 | } |
| 510 | 503 | ||
| 511 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 504 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| @@ -533,14 +526,14 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 533 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 526 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
| 534 | 527 | ||
| 535 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 528 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 536 | goto give_sigsegv; | 529 | return -EFAULT; |
| 537 | 530 | ||
| 538 | err |= __put_user(sig, &frame->sig); | 531 | err |= __put_user(sig, &frame->sig); |
| 539 | err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); | 532 | err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); |
| 540 | err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); | 533 | err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); |
| 541 | err |= copy_siginfo_to_user32(&frame->info, info); | 534 | err |= copy_siginfo_to_user32(&frame->info, info); |
| 542 | if (err) | 535 | if (err) |
| 543 | goto give_sigsegv; | 536 | return -EFAULT; |
| 544 | 537 | ||
| 545 | /* Create the ucontext. */ | 538 | /* Create the ucontext. */ |
| 546 | if (cpu_has_xsave) | 539 | if (cpu_has_xsave) |
| @@ -556,7 +549,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 556 | regs, set->sig[0]); | 549 | regs, set->sig[0]); |
| 557 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 550 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 558 | if (err) | 551 | if (err) |
| 559 | goto give_sigsegv; | 552 | return -EFAULT; |
| 560 | 553 | ||
| 561 | if (ka->sa.sa_flags & SA_RESTORER) | 554 | if (ka->sa.sa_flags & SA_RESTORER) |
| 562 | restorer = ka->sa.sa_restorer; | 555 | restorer = ka->sa.sa_restorer; |
| @@ -571,7 +564,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 571 | */ | 564 | */ |
| 572 | err |= __copy_to_user(frame->retcode, &code, 8); | 565 | err |= __copy_to_user(frame->retcode, &code, 8); |
| 573 | if (err) | 566 | if (err) |
| 574 | goto give_sigsegv; | 567 | return -EFAULT; |
| 575 | 568 | ||
| 576 | /* Set up registers for signal handler */ | 569 | /* Set up registers for signal handler */ |
| 577 | regs->sp = (unsigned long) frame; | 570 | regs->sp = (unsigned long) frame; |
| @@ -599,8 +592,4 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 599 | #endif | 592 | #endif |
| 600 | 593 | ||
| 601 | return 0; | 594 | return 0; |
| 602 | |||
| 603 | give_sigsegv: | ||
| 604 | force_sigsegv(sig, current); | ||
| 605 | return -EFAULT; | ||
| 606 | } | 595 | } |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e375b658efc3..42ec4421e10b 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -1452,7 +1452,8 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
| 1452 | #endif | 1452 | #endif |
| 1453 | } | 1453 | } |
| 1454 | 1454 | ||
| 1455 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | 1455 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
| 1456 | int error_code, int si_code) | ||
| 1456 | { | 1457 | { |
| 1457 | struct siginfo info; | 1458 | struct siginfo info; |
| 1458 | 1459 | ||
| @@ -1461,7 +1462,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | |||
| 1461 | 1462 | ||
| 1462 | memset(&info, 0, sizeof(info)); | 1463 | memset(&info, 0, sizeof(info)); |
| 1463 | info.si_signo = SIGTRAP; | 1464 | info.si_signo = SIGTRAP; |
| 1464 | info.si_code = TRAP_BRKPT; | 1465 | info.si_code = si_code; |
| 1465 | 1466 | ||
| 1466 | /* User-mode ip? */ | 1467 | /* User-mode ip? */ |
| 1467 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; | 1468 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; |
| @@ -1548,5 +1549,5 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) | |||
| 1548 | */ | 1549 | */ |
| 1549 | if (test_thread_flag(TIF_SINGLESTEP) && | 1550 | if (test_thread_flag(TIF_SINGLESTEP) && |
| 1550 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) | 1551 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) |
| 1551 | send_sigtrap(current, regs, 0); | 1552 | send_sigtrap(current, regs, 0, TRAP_BRKPT); |
| 1552 | } | 1553 | } |
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b21070ea33a4..da3cf3270f83 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 28 | #include <asm/i387.h> | 28 | #include <asm/i387.h> |
| 29 | #include <asm/vdso.h> | 29 | #include <asm/vdso.h> |
| 30 | #include <asm/syscall.h> | ||
| 30 | #include <asm/syscalls.h> | 31 | #include <asm/syscalls.h> |
| 31 | 32 | ||
| 32 | #include "sigframe.h" | 33 | #include "sigframe.h" |
| @@ -214,9 +215,8 @@ badframe: | |||
| 214 | return 0; | 215 | return 0; |
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | 218 | static long do_rt_sigreturn(struct pt_regs *regs) |
| 218 | { | 219 | { |
| 219 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
| 220 | struct rt_sigframe __user *frame; | 220 | struct rt_sigframe __user *frame; |
| 221 | unsigned long ax; | 221 | unsigned long ax; |
| 222 | sigset_t set; | 222 | sigset_t set; |
| @@ -242,10 +242,17 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused) | |||
| 242 | return ax; | 242 | return ax; |
| 243 | 243 | ||
| 244 | badframe: | 244 | badframe: |
| 245 | force_sig(SIGSEGV, current); | 245 | signal_fault(regs, frame, "rt_sigreturn"); |
| 246 | return 0; | 246 | return 0; |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | ||
| 250 | { | ||
| 251 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
| 252 | |||
| 253 | return do_rt_sigreturn(regs); | ||
| 254 | } | ||
| 255 | |||
| 249 | /* | 256 | /* |
| 250 | * Set up a signal frame. | 257 | * Set up a signal frame. |
| 251 | */ | 258 | */ |
| @@ -337,39 +344,29 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | |||
| 337 | } | 344 | } |
| 338 | 345 | ||
| 339 | static int | 346 | static int |
| 340 | setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | 347 | __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, |
| 341 | struct pt_regs *regs) | 348 | struct pt_regs *regs) |
| 342 | { | 349 | { |
| 343 | struct sigframe __user *frame; | 350 | struct sigframe __user *frame; |
| 344 | void __user *restorer; | 351 | void __user *restorer; |
| 345 | int err = 0; | 352 | int err = 0; |
| 346 | int usig; | ||
| 347 | void __user *fpstate = NULL; | 353 | void __user *fpstate = NULL; |
| 348 | 354 | ||
| 349 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 355 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
| 350 | 356 | ||
| 351 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 357 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 352 | goto give_sigsegv; | 358 | return -EFAULT; |
| 353 | 359 | ||
| 354 | usig = current_thread_info()->exec_domain | 360 | if (__put_user(sig, &frame->sig)) |
| 355 | && current_thread_info()->exec_domain->signal_invmap | 361 | return -EFAULT; |
| 356 | && sig < 32 | ||
| 357 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
| 358 | : sig; | ||
| 359 | 362 | ||
| 360 | err = __put_user(usig, &frame->sig); | 363 | if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) |
| 361 | if (err) | 364 | return -EFAULT; |
| 362 | goto give_sigsegv; | ||
| 363 | |||
| 364 | err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); | ||
| 365 | if (err) | ||
| 366 | goto give_sigsegv; | ||
| 367 | 365 | ||
| 368 | if (_NSIG_WORDS > 1) { | 366 | if (_NSIG_WORDS > 1) { |
| 369 | err = __copy_to_user(&frame->extramask, &set->sig[1], | 367 | if (__copy_to_user(&frame->extramask, &set->sig[1], |
| 370 | sizeof(frame->extramask)); | 368 | sizeof(frame->extramask))) |
| 371 | if (err) | 369 | return -EFAULT; |
| 372 | goto give_sigsegv; | ||
| 373 | } | 370 | } |
| 374 | 371 | ||
| 375 | if (current->mm->context.vdso) | 372 | if (current->mm->context.vdso) |
| @@ -394,7 +391,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
| 394 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); | 391 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); |
| 395 | 392 | ||
| 396 | if (err) | 393 | if (err) |
| 397 | goto give_sigsegv; | 394 | return -EFAULT; |
| 398 | 395 | ||
| 399 | /* Set up registers for signal handler */ | 396 | /* Set up registers for signal handler */ |
| 400 | regs->sp = (unsigned long)frame; | 397 | regs->sp = (unsigned long)frame; |
| @@ -409,38 +406,27 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
| 409 | regs->cs = __USER_CS; | 406 | regs->cs = __USER_CS; |
| 410 | 407 | ||
| 411 | return 0; | 408 | return 0; |
| 412 | |||
| 413 | give_sigsegv: | ||
| 414 | force_sigsegv(sig, current); | ||
| 415 | return -EFAULT; | ||
| 416 | } | 409 | } |
| 417 | 410 | ||
| 418 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 411 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 419 | sigset_t *set, struct pt_regs *regs) | 412 | sigset_t *set, struct pt_regs *regs) |
| 420 | { | 413 | { |
| 421 | struct rt_sigframe __user *frame; | 414 | struct rt_sigframe __user *frame; |
| 422 | void __user *restorer; | 415 | void __user *restorer; |
| 423 | int err = 0; | 416 | int err = 0; |
| 424 | int usig; | ||
| 425 | void __user *fpstate = NULL; | 417 | void __user *fpstate = NULL; |
| 426 | 418 | ||
| 427 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 419 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
| 428 | 420 | ||
| 429 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 421 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 430 | goto give_sigsegv; | 422 | return -EFAULT; |
| 431 | 423 | ||
| 432 | usig = current_thread_info()->exec_domain | 424 | err |= __put_user(sig, &frame->sig); |
| 433 | && current_thread_info()->exec_domain->signal_invmap | ||
| 434 | && sig < 32 | ||
| 435 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
| 436 | : sig; | ||
| 437 | |||
| 438 | err |= __put_user(usig, &frame->sig); | ||
| 439 | err |= __put_user(&frame->info, &frame->pinfo); | 425 | err |= __put_user(&frame->info, &frame->pinfo); |
| 440 | err |= __put_user(&frame->uc, &frame->puc); | 426 | err |= __put_user(&frame->uc, &frame->puc); |
| 441 | err |= copy_siginfo_to_user(&frame->info, info); | 427 | err |= copy_siginfo_to_user(&frame->info, info); |
| 442 | if (err) | 428 | if (err) |
| 443 | goto give_sigsegv; | 429 | return -EFAULT; |
| 444 | 430 | ||
| 445 | /* Create the ucontext. */ | 431 | /* Create the ucontext. */ |
| 446 | if (cpu_has_xsave) | 432 | if (cpu_has_xsave) |
| @@ -456,7 +442,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 456 | regs, set->sig[0]); | 442 | regs, set->sig[0]); |
| 457 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 443 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 458 | if (err) | 444 | if (err) |
| 459 | goto give_sigsegv; | 445 | return -EFAULT; |
| 460 | 446 | ||
| 461 | /* Set up to return from userspace. */ | 447 | /* Set up to return from userspace. */ |
| 462 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | 448 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
| @@ -476,12 +462,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 476 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); | 462 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); |
| 477 | 463 | ||
| 478 | if (err) | 464 | if (err) |
| 479 | goto give_sigsegv; | 465 | return -EFAULT; |
| 480 | 466 | ||
| 481 | /* Set up registers for signal handler */ | 467 | /* Set up registers for signal handler */ |
| 482 | regs->sp = (unsigned long)frame; | 468 | regs->sp = (unsigned long)frame; |
| 483 | regs->ip = (unsigned long)ka->sa.sa_handler; | 469 | regs->ip = (unsigned long)ka->sa.sa_handler; |
| 484 | regs->ax = (unsigned long)usig; | 470 | regs->ax = (unsigned long)sig; |
| 485 | regs->dx = (unsigned long)&frame->info; | 471 | regs->dx = (unsigned long)&frame->info; |
| 486 | regs->cx = (unsigned long)&frame->uc; | 472 | regs->cx = (unsigned long)&frame->uc; |
| 487 | 473 | ||
| @@ -491,25 +477,48 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 491 | regs->cs = __USER_CS; | 477 | regs->cs = __USER_CS; |
| 492 | 478 | ||
| 493 | return 0; | 479 | return 0; |
| 494 | |||
| 495 | give_sigsegv: | ||
| 496 | force_sigsegv(sig, current); | ||
| 497 | return -EFAULT; | ||
| 498 | } | 480 | } |
| 499 | 481 | ||
| 500 | /* | 482 | /* |
| 501 | * OK, we're invoking a handler: | 483 | * OK, we're invoking a handler: |
| 502 | */ | 484 | */ |
| 503 | static int | 485 | static int |
| 486 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
| 487 | sigset_t *set, struct pt_regs *regs) | ||
| 488 | { | ||
| 489 | int ret; | ||
| 490 | int usig; | ||
| 491 | |||
| 492 | usig = current_thread_info()->exec_domain | ||
| 493 | && current_thread_info()->exec_domain->signal_invmap | ||
| 494 | && sig < 32 | ||
| 495 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
| 496 | : sig; | ||
| 497 | |||
| 498 | /* Set up the stack frame */ | ||
| 499 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 500 | ret = __setup_rt_frame(usig, ka, info, set, regs); | ||
| 501 | else | ||
| 502 | ret = __setup_frame(usig, ka, set, regs); | ||
| 503 | |||
| 504 | if (ret) { | ||
| 505 | force_sigsegv(sig, current); | ||
| 506 | return -EFAULT; | ||
| 507 | } | ||
| 508 | |||
| 509 | return ret; | ||
| 510 | } | ||
| 511 | |||
| 512 | static int | ||
| 504 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 513 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
| 505 | sigset_t *oldset, struct pt_regs *regs) | 514 | sigset_t *oldset, struct pt_regs *regs) |
| 506 | { | 515 | { |
| 507 | int ret; | 516 | int ret; |
| 508 | 517 | ||
| 509 | /* Are we from a system call? */ | 518 | /* Are we from a system call? */ |
| 510 | if ((long)regs->orig_ax >= 0) { | 519 | if (syscall_get_nr(current, regs) >= 0) { |
| 511 | /* If so, check system call restarting.. */ | 520 | /* If so, check system call restarting.. */ |
| 512 | switch (regs->ax) { | 521 | switch (syscall_get_error(current, regs)) { |
| 513 | case -ERESTART_RESTARTBLOCK: | 522 | case -ERESTART_RESTARTBLOCK: |
| 514 | case -ERESTARTNOHAND: | 523 | case -ERESTARTNOHAND: |
| 515 | regs->ax = -EINTR; | 524 | regs->ax = -EINTR; |
| @@ -536,11 +545,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 536 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 545 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
| 537 | regs->flags &= ~X86_EFLAGS_TF; | 546 | regs->flags &= ~X86_EFLAGS_TF; |
| 538 | 547 | ||
| 539 | /* Set up the stack frame */ | 548 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
| 540 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 541 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | ||
| 542 | else | ||
| 543 | ret = setup_frame(sig, ka, oldset, regs); | ||
| 544 | 549 | ||
| 545 | if (ret) | 550 | if (ret) |
| 546 | return ret; | 551 | return ret; |
| @@ -571,6 +576,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 571 | return 0; | 576 | return 0; |
| 572 | } | 577 | } |
| 573 | 578 | ||
| 579 | #define NR_restart_syscall __NR_restart_syscall | ||
| 574 | /* | 580 | /* |
| 575 | * Note that 'init' is a special process: it doesn't get signals it doesn't | 581 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
| 576 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 582 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| @@ -623,9 +629,9 @@ static void do_signal(struct pt_regs *regs) | |||
| 623 | } | 629 | } |
| 624 | 630 | ||
| 625 | /* Did we come from a system call? */ | 631 | /* Did we come from a system call? */ |
| 626 | if ((long)regs->orig_ax >= 0) { | 632 | if (syscall_get_nr(current, regs) >= 0) { |
| 627 | /* Restart the system call - no handlers present */ | 633 | /* Restart the system call - no handlers present */ |
| 628 | switch (regs->ax) { | 634 | switch (syscall_get_error(current, regs)) { |
| 629 | case -ERESTARTNOHAND: | 635 | case -ERESTARTNOHAND: |
| 630 | case -ERESTARTSYS: | 636 | case -ERESTARTSYS: |
| 631 | case -ERESTARTNOINTR: | 637 | case -ERESTARTNOINTR: |
| @@ -634,7 +640,7 @@ static void do_signal(struct pt_regs *regs) | |||
| 634 | break; | 640 | break; |
| 635 | 641 | ||
| 636 | case -ERESTART_RESTARTBLOCK: | 642 | case -ERESTART_RESTARTBLOCK: |
| 637 | regs->ax = __NR_restart_syscall; | 643 | regs->ax = NR_restart_syscall; |
| 638 | regs->ip -= 2; | 644 | regs->ip -= 2; |
| 639 | break; | 645 | break; |
| 640 | } | 646 | } |
| @@ -668,3 +674,19 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
| 668 | 674 | ||
| 669 | clear_thread_flag(TIF_IRET); | 675 | clear_thread_flag(TIF_IRET); |
| 670 | } | 676 | } |
| 677 | |||
| 678 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | ||
| 679 | { | ||
| 680 | struct task_struct *me = current; | ||
| 681 | |||
| 682 | if (show_unhandled_signals && printk_ratelimit()) { | ||
| 683 | printk(KERN_INFO | ||
| 684 | "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | ||
| 685 | me->comm, me->pid, where, frame, | ||
| 686 | regs->ip, regs->sp, regs->orig_ax); | ||
| 687 | print_vma_addr(" in ", regs->ip); | ||
| 688 | printk(KERN_CONT "\n"); | ||
| 689 | } | ||
| 690 | |||
| 691 | force_sig(SIGSEGV, me); | ||
| 692 | } | ||
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 823a55bf8c39..bf77d4789a2d 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
| @@ -94,7 +94,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | { | 96 | { |
| 97 | struct _fpstate __user *buf; | 97 | void __user *buf; |
| 98 | |||
| 98 | err |= __get_user(buf, &sc->fpstate); | 99 | err |= __get_user(buf, &sc->fpstate); |
| 99 | err |= restore_i387_xstate(buf); | 100 | err |= restore_i387_xstate(buf); |
| 100 | } | 101 | } |
| @@ -103,11 +104,11 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 103 | return err; | 104 | return err; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 107 | static long do_rt_sigreturn(struct pt_regs *regs) |
| 107 | { | 108 | { |
| 108 | struct rt_sigframe __user *frame; | 109 | struct rt_sigframe __user *frame; |
| 109 | sigset_t set; | ||
| 110 | unsigned long ax; | 110 | unsigned long ax; |
| 111 | sigset_t set; | ||
| 111 | 112 | ||
| 112 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); | 113 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); |
| 113 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 114 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -130,10 +131,15 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
| 130 | return ax; | 131 | return ax; |
| 131 | 132 | ||
| 132 | badframe: | 133 | badframe: |
| 133 | signal_fault(regs, frame, "sigreturn"); | 134 | signal_fault(regs, frame, "rt_sigreturn"); |
| 134 | return 0; | 135 | return 0; |
| 135 | } | 136 | } |
| 136 | 137 | ||
| 138 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
| 139 | { | ||
| 140 | return do_rt_sigreturn(regs); | ||
| 141 | } | ||
| 142 | |||
| 137 | /* | 143 | /* |
| 138 | * Set up a signal frame. | 144 | * Set up a signal frame. |
| 139 | */ | 145 | */ |
| @@ -195,8 +201,8 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) | |||
| 195 | return (void __user *)round_down(sp - size, 64); | 201 | return (void __user *)round_down(sp - size, 64); |
| 196 | } | 202 | } |
| 197 | 203 | ||
| 198 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 204 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 199 | sigset_t *set, struct pt_regs *regs) | 205 | sigset_t *set, struct pt_regs *regs) |
| 200 | { | 206 | { |
| 201 | struct rt_sigframe __user *frame; | 207 | struct rt_sigframe __user *frame; |
| 202 | void __user *fp = NULL; | 208 | void __user *fp = NULL; |
| @@ -209,17 +215,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 209 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | 215 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; |
| 210 | 216 | ||
| 211 | if (save_i387_xstate(fp) < 0) | 217 | if (save_i387_xstate(fp) < 0) |
| 212 | err |= -1; | 218 | return -EFAULT; |
| 213 | } else | 219 | } else |
| 214 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 220 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |
| 215 | 221 | ||
| 216 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 222 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 217 | goto give_sigsegv; | 223 | return -EFAULT; |
| 218 | 224 | ||
| 219 | if (ka->sa.sa_flags & SA_SIGINFO) { | 225 | if (ka->sa.sa_flags & SA_SIGINFO) { |
| 220 | err |= copy_siginfo_to_user(&frame->info, info); | 226 | if (copy_siginfo_to_user(&frame->info, info)) |
| 221 | if (err) | 227 | return -EFAULT; |
| 222 | goto give_sigsegv; | ||
| 223 | } | 228 | } |
| 224 | 229 | ||
| 225 | /* Create the ucontext. */ | 230 | /* Create the ucontext. */ |
| @@ -247,11 +252,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 247 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 252 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 248 | } else { | 253 | } else { |
| 249 | /* could use a vstub here */ | 254 | /* could use a vstub here */ |
| 250 | goto give_sigsegv; | 255 | return -EFAULT; |
| 251 | } | 256 | } |
| 252 | 257 | ||
| 253 | if (err) | 258 | if (err) |
| 254 | goto give_sigsegv; | 259 | return -EFAULT; |
| 255 | 260 | ||
| 256 | /* Set up registers for signal handler */ | 261 | /* Set up registers for signal handler */ |
| 257 | regs->di = sig; | 262 | regs->di = sig; |
| @@ -271,15 +276,34 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 271 | regs->cs = __USER_CS; | 276 | regs->cs = __USER_CS; |
| 272 | 277 | ||
| 273 | return 0; | 278 | return 0; |
| 274 | |||
| 275 | give_sigsegv: | ||
| 276 | force_sigsegv(sig, current); | ||
| 277 | return -EFAULT; | ||
| 278 | } | 279 | } |
| 279 | 280 | ||
| 280 | /* | 281 | /* |
| 281 | * OK, we're invoking a handler | 282 | * OK, we're invoking a handler |
| 282 | */ | 283 | */ |
| 284 | static int | ||
| 285 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
| 286 | sigset_t *set, struct pt_regs *regs) | ||
| 287 | { | ||
| 288 | int ret; | ||
| 289 | |||
| 290 | #ifdef CONFIG_IA32_EMULATION | ||
| 291 | if (test_thread_flag(TIF_IA32)) { | ||
| 292 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 293 | ret = ia32_setup_rt_frame(sig, ka, info, set, regs); | ||
| 294 | else | ||
| 295 | ret = ia32_setup_frame(sig, ka, set, regs); | ||
| 296 | } else | ||
| 297 | #endif | ||
| 298 | ret = __setup_rt_frame(sig, ka, info, set, regs); | ||
| 299 | |||
| 300 | if (ret) { | ||
| 301 | force_sigsegv(sig, current); | ||
| 302 | return -EFAULT; | ||
| 303 | } | ||
| 304 | |||
| 305 | return ret; | ||
| 306 | } | ||
| 283 | 307 | ||
| 284 | static int | 308 | static int |
| 285 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 309 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
| @@ -317,51 +341,46 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 317 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 341 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
| 318 | regs->flags &= ~X86_EFLAGS_TF; | 342 | regs->flags &= ~X86_EFLAGS_TF; |
| 319 | 343 | ||
| 320 | #ifdef CONFIG_IA32_EMULATION | ||
| 321 | if (test_thread_flag(TIF_IA32)) { | ||
| 322 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
| 323 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); | ||
| 324 | else | ||
| 325 | ret = ia32_setup_frame(sig, ka, oldset, regs); | ||
| 326 | } else | ||
| 327 | #endif | ||
| 328 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 344 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
| 329 | 345 | ||
| 330 | if (ret == 0) { | 346 | if (ret) |
| 331 | /* | 347 | return ret; |
| 332 | * This has nothing to do with segment registers, | ||
| 333 | * despite the name. This magic affects uaccess.h | ||
| 334 | * macros' behavior. Reset it to the normal setting. | ||
| 335 | */ | ||
| 336 | set_fs(USER_DS); | ||
| 337 | 348 | ||
| 338 | /* | 349 | /* |
| 339 | * Clear the direction flag as per the ABI for function entry. | 350 | * This has nothing to do with segment registers, |
| 340 | */ | 351 | * despite the name. This magic affects uaccess.h |
| 341 | regs->flags &= ~X86_EFLAGS_DF; | 352 | * macros' behavior. Reset it to the normal setting. |
| 353 | */ | ||
| 354 | set_fs(USER_DS); | ||
| 342 | 355 | ||
| 343 | /* | 356 | /* |
| 344 | * Clear TF when entering the signal handler, but | 357 | * Clear the direction flag as per the ABI for function entry. |
| 345 | * notify any tracer that was single-stepping it. | 358 | */ |
| 346 | * The tracer may want to single-step inside the | 359 | regs->flags &= ~X86_EFLAGS_DF; |
| 347 | * handler too. | ||
| 348 | */ | ||
| 349 | regs->flags &= ~X86_EFLAGS_TF; | ||
| 350 | 360 | ||
| 351 | spin_lock_irq(¤t->sighand->siglock); | 361 | /* |
| 352 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 362 | * Clear TF when entering the signal handler, but |
| 353 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 363 | * notify any tracer that was single-stepping it. |
| 354 | sigaddset(¤t->blocked, sig); | 364 | * The tracer may want to single-step inside the |
| 355 | recalc_sigpending(); | 365 | * handler too. |
| 356 | spin_unlock_irq(¤t->sighand->siglock); | 366 | */ |
| 367 | regs->flags &= ~X86_EFLAGS_TF; | ||
| 357 | 368 | ||
| 358 | tracehook_signal_handler(sig, info, ka, regs, | 369 | spin_lock_irq(¤t->sighand->siglock); |
| 359 | test_thread_flag(TIF_SINGLESTEP)); | 370 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
| 360 | } | 371 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
| 372 | sigaddset(¤t->blocked, sig); | ||
| 373 | recalc_sigpending(); | ||
| 374 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 361 | 375 | ||
| 362 | return ret; | 376 | tracehook_signal_handler(sig, info, ka, regs, |
| 377 | test_thread_flag(TIF_SINGLESTEP)); | ||
| 378 | |||
| 379 | return 0; | ||
| 363 | } | 380 | } |
| 364 | 381 | ||
| 382 | #define NR_restart_syscall \ | ||
| 383 | test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall | ||
| 365 | /* | 384 | /* |
| 366 | * Note that 'init' is a special process: it doesn't get signals it doesn't | 385 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
| 367 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 386 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| @@ -423,9 +442,7 @@ static void do_signal(struct pt_regs *regs) | |||
| 423 | regs->ip -= 2; | 442 | regs->ip -= 2; |
| 424 | break; | 443 | break; |
| 425 | case -ERESTART_RESTARTBLOCK: | 444 | case -ERESTART_RESTARTBLOCK: |
| 426 | regs->ax = test_thread_flag(TIF_IA32) ? | 445 | regs->ax = NR_restart_syscall; |
| 427 | __NR_ia32_restart_syscall : | ||
| 428 | __NR_restart_syscall; | ||
| 429 | regs->ip -= 2; | 446 | regs->ip -= 2; |
| 430 | break; | 447 | break; |
| 431 | } | 448 | } |
| @@ -463,12 +480,14 @@ void do_notify_resume(struct pt_regs *regs, void *unused, | |||
| 463 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 480 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
| 464 | { | 481 | { |
| 465 | struct task_struct *me = current; | 482 | struct task_struct *me = current; |
| 483 | |||
| 466 | if (show_unhandled_signals && printk_ratelimit()) { | 484 | if (show_unhandled_signals && printk_ratelimit()) { |
| 467 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | 485 | printk(KERN_INFO |
| 468 | me->comm, me->pid, where, frame, regs->ip, | 486 | "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", |
| 469 | regs->sp, regs->orig_ax); | 487 | me->comm, me->pid, where, frame, |
| 488 | regs->ip, regs->sp, regs->orig_ax); | ||
| 470 | print_vma_addr(" in ", regs->ip); | 489 | print_vma_addr(" in ", regs->ip); |
| 471 | printk("\n"); | 490 | printk(KERN_CONT "\n"); |
| 472 | } | 491 | } |
| 473 | 492 | ||
| 474 | force_sig(SIGSEGV, me); | 493 | force_sig(SIGSEGV, me); |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index da5a5964fccb..0429c5de5ea9 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
| @@ -891,6 +891,7 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 891 | { | 891 | { |
| 892 | struct task_struct *tsk = current; | 892 | struct task_struct *tsk = current; |
| 893 | unsigned int condition; | 893 | unsigned int condition; |
| 894 | int si_code; | ||
| 894 | 895 | ||
| 895 | trace_hardirqs_fixup(); | 896 | trace_hardirqs_fixup(); |
| 896 | 897 | ||
| @@ -935,8 +936,9 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 935 | goto clear_TF_reenable; | 936 | goto clear_TF_reenable; |
| 936 | } | 937 | } |
| 937 | 938 | ||
| 939 | si_code = get_si_code((unsigned long)condition); | ||
| 938 | /* Ok, finally something we can handle */ | 940 | /* Ok, finally something we can handle */ |
| 939 | send_sigtrap(tsk, regs, error_code); | 941 | send_sigtrap(tsk, regs, error_code, si_code); |
| 940 | 942 | ||
| 941 | /* | 943 | /* |
| 942 | * Disable additional traps. They'll be re-enabled when | 944 | * Disable additional traps. They'll be re-enabled when |
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 2887a789e38f..9c0ac0cab013 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c | |||
| @@ -940,7 +940,7 @@ asmlinkage void __kprobes do_debug(struct pt_regs *regs, | |||
| 940 | tsk->thread.error_code = error_code; | 940 | tsk->thread.error_code = error_code; |
| 941 | info.si_signo = SIGTRAP; | 941 | info.si_signo = SIGTRAP; |
| 942 | info.si_errno = 0; | 942 | info.si_errno = 0; |
| 943 | info.si_code = TRAP_BRKPT; | 943 | info.si_code = get_si_code(condition); |
| 944 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; | 944 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; |
| 945 | force_sig_info(SIGTRAP, &info, tsk); | 945 | force_sig_info(SIGTRAP, &info, tsk); |
| 946 | 946 | ||
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 8786e01e0db8..969570167e9e 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h | |||
| @@ -199,6 +199,8 @@ typedef struct siginfo { | |||
| 199 | */ | 199 | */ |
| 200 | #define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */ | 200 | #define TRAP_BRKPT (__SI_FAULT|1) /* process breakpoint */ |
| 201 | #define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */ | 201 | #define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */ |
| 202 | #define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ | ||
| 203 | #define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint/watchpoint */ | ||
| 202 | #define NSIGTRAP 2 | 204 | #define NSIGTRAP 2 |
| 203 | 205 | ||
| 204 | /* | 206 | /* |
diff --git a/include/asm-parisc/siginfo.h b/include/asm-parisc/siginfo.h index d4909f55fe35..d7034728f377 100644 --- a/include/asm-parisc/siginfo.h +++ b/include/asm-parisc/siginfo.h | |||
| @@ -3,11 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include <asm-generic/siginfo.h> | 4 | #include <asm-generic/siginfo.h> |
| 5 | 5 | ||
| 6 | /* | ||
| 7 | * SIGTRAP si_codes | ||
| 8 | */ | ||
| 9 | #define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ | ||
| 10 | #define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint or watchpoint */ | ||
| 11 | #undef NSIGTRAP | 6 | #undef NSIGTRAP |
| 12 | #define NSIGTRAP 4 | 7 | #define NSIGTRAP 4 |
| 13 | 8 | ||
diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index d64a61097165..ac578f11c1c5 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h | |||
| @@ -177,11 +177,11 @@ convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs); | |||
| 177 | 177 | ||
| 178 | #ifdef CONFIG_X86_32 | 178 | #ifdef CONFIG_X86_32 |
| 179 | extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, | 179 | extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
| 180 | int error_code); | 180 | int error_code, int si_code); |
| 181 | #else | ||
| 182 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where); | ||
| 183 | #endif | 181 | #endif |
| 184 | 182 | ||
| 183 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where); | ||
| 184 | |||
| 185 | extern long syscall_trace_enter(struct pt_regs *); | 185 | extern long syscall_trace_enter(struct pt_regs *); |
| 186 | extern void syscall_trace_leave(struct pt_regs *); | 186 | extern void syscall_trace_leave(struct pt_regs *); |
| 187 | 187 | ||
diff --git a/include/asm-x86/traps.h b/include/asm-x86/traps.h index 2ccebc6fb0b0..7a692baa51ae 100644 --- a/include/asm-x86/traps.h +++ b/include/asm-x86/traps.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #ifndef ASM_X86__TRAPS_H | 1 | #ifndef ASM_X86__TRAPS_H |
| 2 | #define ASM_X86__TRAPS_H | 2 | #define ASM_X86__TRAPS_H |
| 3 | 3 | ||
| 4 | #include <asm/debugreg.h> | ||
| 5 | |||
| 4 | /* Common in X86_32 and X86_64 */ | 6 | /* Common in X86_32 and X86_64 */ |
| 5 | asmlinkage void divide_error(void); | 7 | asmlinkage void divide_error(void); |
| 6 | asmlinkage void debug(void); | 8 | asmlinkage void debug(void); |
| @@ -36,6 +38,16 @@ void do_invalid_op(struct pt_regs *, long); | |||
| 36 | void do_general_protection(struct pt_regs *, long); | 38 | void do_general_protection(struct pt_regs *, long); |
| 37 | void do_nmi(struct pt_regs *, long); | 39 | void do_nmi(struct pt_regs *, long); |
| 38 | 40 | ||
| 41 | static inline int get_si_code(unsigned long condition) | ||
| 42 | { | ||
| 43 | if (condition & DR_STEP) | ||
| 44 | return TRAP_TRACE; | ||
| 45 | else if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) | ||
| 46 | return TRAP_HWBKPT; | ||
| 47 | else | ||
| 48 | return TRAP_BRKPT; | ||
| 49 | } | ||
| 50 | |||
| 39 | extern int panic_on_unrecovered_nmi; | 51 | extern int panic_on_unrecovered_nmi; |
| 40 | extern int kstack_depth_to_print; | 52 | extern int kstack_depth_to_print; |
| 41 | 53 | ||
