diff options
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r-- | arch/x86/kernel/ptrace.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e375b658efc3..0a6d8c12e10d 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -40,7 +40,9 @@ enum x86_regset { | |||
40 | REGSET_GENERAL, | 40 | REGSET_GENERAL, |
41 | REGSET_FP, | 41 | REGSET_FP, |
42 | REGSET_XFP, | 42 | REGSET_XFP, |
43 | REGSET_IOPERM64 = REGSET_XFP, | ||
43 | REGSET_TLS, | 44 | REGSET_TLS, |
45 | REGSET_IOPERM32, | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | /* | 48 | /* |
@@ -555,6 +557,29 @@ static int ptrace_set_debugreg(struct task_struct *child, | |||
555 | return 0; | 557 | return 0; |
556 | } | 558 | } |
557 | 559 | ||
560 | /* | ||
561 | * These access the current or another (stopped) task's io permission | ||
562 | * bitmap for debugging or core dump. | ||
563 | */ | ||
564 | static int ioperm_active(struct task_struct *target, | ||
565 | const struct user_regset *regset) | ||
566 | { | ||
567 | return target->thread.io_bitmap_max / regset->size; | ||
568 | } | ||
569 | |||
570 | static int ioperm_get(struct task_struct *target, | ||
571 | const struct user_regset *regset, | ||
572 | unsigned int pos, unsigned int count, | ||
573 | void *kbuf, void __user *ubuf) | ||
574 | { | ||
575 | if (!target->thread.io_bitmap_ptr) | ||
576 | return -ENXIO; | ||
577 | |||
578 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
579 | target->thread.io_bitmap_ptr, | ||
580 | 0, IO_BITMAP_BYTES); | ||
581 | } | ||
582 | |||
558 | #ifdef CONFIG_X86_PTRACE_BTS | 583 | #ifdef CONFIG_X86_PTRACE_BTS |
559 | /* | 584 | /* |
560 | * The configuration for a particular BTS hardware implementation. | 585 | * The configuration for a particular BTS hardware implementation. |
@@ -1385,6 +1410,12 @@ static const struct user_regset x86_64_regsets[] = { | |||
1385 | .size = sizeof(long), .align = sizeof(long), | 1410 | .size = sizeof(long), .align = sizeof(long), |
1386 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set | 1411 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set |
1387 | }, | 1412 | }, |
1413 | [REGSET_IOPERM64] = { | ||
1414 | .core_note_type = NT_386_IOPERM, | ||
1415 | .n = IO_BITMAP_LONGS, | ||
1416 | .size = sizeof(long), .align = sizeof(long), | ||
1417 | .active = ioperm_active, .get = ioperm_get | ||
1418 | }, | ||
1388 | }; | 1419 | }; |
1389 | 1420 | ||
1390 | static const struct user_regset_view user_x86_64_view = { | 1421 | static const struct user_regset_view user_x86_64_view = { |
@@ -1431,6 +1462,12 @@ static const struct user_regset x86_32_regsets[] = { | |||
1431 | .active = regset_tls_active, | 1462 | .active = regset_tls_active, |
1432 | .get = regset_tls_get, .set = regset_tls_set | 1463 | .get = regset_tls_get, .set = regset_tls_set |
1433 | }, | 1464 | }, |
1465 | [REGSET_IOPERM32] = { | ||
1466 | .core_note_type = NT_386_IOPERM, | ||
1467 | .n = IO_BITMAP_BYTES / sizeof(u32), | ||
1468 | .size = sizeof(u32), .align = sizeof(u32), | ||
1469 | .active = ioperm_active, .get = ioperm_get | ||
1470 | }, | ||
1434 | }; | 1471 | }; |
1435 | 1472 | ||
1436 | static const struct user_regset_view user_x86_32_view = { | 1473 | static const struct user_regset_view user_x86_32_view = { |
@@ -1452,7 +1489,8 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
1452 | #endif | 1489 | #endif |
1453 | } | 1490 | } |
1454 | 1491 | ||
1455 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | 1492 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
1493 | int error_code, int si_code) | ||
1456 | { | 1494 | { |
1457 | struct siginfo info; | 1495 | struct siginfo info; |
1458 | 1496 | ||
@@ -1461,7 +1499,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code) | |||
1461 | 1499 | ||
1462 | memset(&info, 0, sizeof(info)); | 1500 | memset(&info, 0, sizeof(info)); |
1463 | info.si_signo = SIGTRAP; | 1501 | info.si_signo = SIGTRAP; |
1464 | info.si_code = TRAP_BRKPT; | 1502 | info.si_code = si_code; |
1465 | 1503 | ||
1466 | /* User-mode ip? */ | 1504 | /* User-mode ip? */ |
1467 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; | 1505 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; |
@@ -1548,5 +1586,5 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) | |||
1548 | */ | 1586 | */ |
1549 | if (test_thread_flag(TIF_SINGLESTEP) && | 1587 | if (test_thread_flag(TIF_SINGLESTEP) && |
1550 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) | 1588 | tracehook_consider_fatal_signal(current, SIGTRAP, SIG_DFL)) |
1551 | send_sigtrap(current, regs, 0); | 1589 | send_sigtrap(current, regs, 0, TRAP_BRKPT); |
1552 | } | 1590 | } |