aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/ptrace.h5
-rw-r--r--arch/x86/kernel/ptrace.c157
2 files changed, 138 insertions, 24 deletions
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 6205f0c434db..86fc2bb82287 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -75,6 +75,11 @@ convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
75extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, 75extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
76 int error_code, int si_code); 76 int error_code, int si_code);
77 77
78
79extern unsigned long syscall_trace_enter_phase1(struct pt_regs *, u32 arch);
80extern long syscall_trace_enter_phase2(struct pt_regs *, u32 arch,
81 unsigned long phase1_result);
82
78extern long syscall_trace_enter(struct pt_regs *); 83extern long syscall_trace_enter(struct pt_regs *);
79extern void syscall_trace_leave(struct pt_regs *); 84extern void syscall_trace_leave(struct pt_regs *);
80 85
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index bbf338a04a5d..29576c244699 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1441,20 +1441,126 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
1441 force_sig_info(SIGTRAP, &info, tsk); 1441 force_sig_info(SIGTRAP, &info, tsk);
1442} 1442}
1443 1443
1444static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
1445{
1446#ifdef CONFIG_X86_64
1447 if (arch == AUDIT_ARCH_X86_64) {
1448 audit_syscall_entry(arch, regs->orig_ax, regs->di,
1449 regs->si, regs->dx, regs->r10);
1450 } else
1451#endif
1452 {
1453 audit_syscall_entry(arch, regs->orig_ax, regs->bx,
1454 regs->cx, regs->dx, regs->si);
1455 }
1456}
1457
1444/* 1458/*
1445 * We must return the syscall number to actually look up in the table. 1459 * We can return 0 to resume the syscall or anything else to go to phase
1446 * This can be -1L to skip running any syscall at all. 1460 * 2. If we resume the syscall, we need to put something appropriate in
1461 * regs->orig_ax.
1462 *
1463 * NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax
1464 * are fully functional.
1465 *
1466 * For phase 2's benefit, our return value is:
1467 * 0: resume the syscall
1468 * 1: go to phase 2; no seccomp phase 2 needed
1469 * anything else: go to phase 2; pass return value to seccomp
1447 */ 1470 */
1448long syscall_trace_enter(struct pt_regs *regs) 1471unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
1449{ 1472{
1450 long ret = 0; 1473 unsigned long ret = 0;
1474 u32 work;
1475
1476 BUG_ON(regs != task_pt_regs(current));
1477
1478 work = ACCESS_ONCE(current_thread_info()->flags) &
1479 _TIF_WORK_SYSCALL_ENTRY;
1451 1480
1452 /* 1481 /*
1453 * If TIF_NOHZ is set, we are required to call user_exit() before 1482 * If TIF_NOHZ is set, we are required to call user_exit() before
1454 * doing anything that could touch RCU. 1483 * doing anything that could touch RCU.
1455 */ 1484 */
1456 if (test_thread_flag(TIF_NOHZ)) 1485 if (work & _TIF_NOHZ) {
1457 user_exit(); 1486 user_exit();
1487 work &= ~TIF_NOHZ;
1488 }
1489
1490#ifdef CONFIG_SECCOMP
1491 /*
1492 * Do seccomp first -- it should minimize exposure of other
1493 * code, and keeping seccomp fast is probably more valuable
1494 * than the rest of this.
1495 */
1496 if (work & _TIF_SECCOMP) {
1497 struct seccomp_data sd;
1498
1499 sd.arch = arch;
1500 sd.nr = regs->orig_ax;
1501 sd.instruction_pointer = regs->ip;
1502#ifdef CONFIG_X86_64
1503 if (arch == AUDIT_ARCH_X86_64) {
1504 sd.args[0] = regs->di;
1505 sd.args[1] = regs->si;
1506 sd.args[2] = regs->dx;
1507 sd.args[3] = regs->r10;
1508 sd.args[4] = regs->r8;
1509 sd.args[5] = regs->r9;
1510 } else
1511#endif
1512 {
1513 sd.args[0] = regs->bx;
1514 sd.args[1] = regs->cx;
1515 sd.args[2] = regs->dx;
1516 sd.args[3] = regs->si;
1517 sd.args[4] = regs->di;
1518 sd.args[5] = regs->bp;
1519 }
1520
1521 BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0);
1522 BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1);
1523
1524 ret = seccomp_phase1(&sd);
1525 if (ret == SECCOMP_PHASE1_SKIP) {
1526 regs->orig_ax = -1;
1527 ret = 0;
1528 } else if (ret != SECCOMP_PHASE1_OK) {
1529 return ret; /* Go directly to phase 2 */
1530 }
1531
1532 work &= ~_TIF_SECCOMP;
1533 }
1534#endif
1535
1536 /* Do our best to finish without phase 2. */
1537 if (work == 0)
1538 return ret; /* seccomp and/or nohz only (ret == 0 here) */
1539
1540#ifdef CONFIG_AUDITSYSCALL
1541 if (work == _TIF_SYSCALL_AUDIT) {
1542 /*
1543 * If there is no more work to be done except auditing,
1544 * then audit in phase 1. Phase 2 always audits, so, if
1545 * we audit here, then we can't go on to phase 2.
1546 */
1547 do_audit_syscall_entry(regs, arch);
1548 return 0;
1549 }
1550#endif
1551
1552 return 1; /* Something is enabled that we can't handle in phase 1 */
1553}
1554
1555/* Returns the syscall nr to run (which should match regs->orig_ax). */
1556long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
1557 unsigned long phase1_result)
1558{
1559 long ret = 0;
1560 u32 work = ACCESS_ONCE(current_thread_info()->flags) &
1561 _TIF_WORK_SYSCALL_ENTRY;
1562
1563 BUG_ON(regs != task_pt_regs(current));
1458 1564
1459 /* 1565 /*
1460 * If we stepped into a sysenter/syscall insn, it trapped in 1566 * If we stepped into a sysenter/syscall insn, it trapped in
@@ -1463,17 +1569,21 @@ long syscall_trace_enter(struct pt_regs *regs)
1463 * do_debug() and we need to set it again to restore the user 1569 * do_debug() and we need to set it again to restore the user
1464 * state. If we entered on the slow path, TF was already set. 1570 * state. If we entered on the slow path, TF was already set.
1465 */ 1571 */
1466 if (test_thread_flag(TIF_SINGLESTEP)) 1572 if (work & _TIF_SINGLESTEP)
1467 regs->flags |= X86_EFLAGS_TF; 1573 regs->flags |= X86_EFLAGS_TF;
1468 1574
1469 /* do the secure computing check first */ 1575#ifdef CONFIG_SECCOMP
1470 if (secure_computing()) { 1576 /*
1577 * Call seccomp_phase2 before running the other hooks so that
1578 * they can see any changes made by a seccomp tracer.
1579 */
1580 if (phase1_result > 1 && seccomp_phase2(phase1_result)) {
1471 /* seccomp failures shouldn't expose any additional code. */ 1581 /* seccomp failures shouldn't expose any additional code. */
1472 ret = -1L; 1582 return -1;
1473 goto out;
1474 } 1583 }
1584#endif
1475 1585
1476 if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) 1586 if (unlikely(work & _TIF_SYSCALL_EMU))
1477 ret = -1L; 1587 ret = -1L;
1478 1588
1479 if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && 1589 if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
@@ -1483,23 +1593,22 @@ long syscall_trace_enter(struct pt_regs *regs)
1483 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1593 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1484 trace_sys_enter(regs, regs->orig_ax); 1594 trace_sys_enter(regs, regs->orig_ax);
1485 1595
1486 if (is_ia32_task()) 1596 do_audit_syscall_entry(regs, arch);
1487 audit_syscall_entry(AUDIT_ARCH_I386,
1488 regs->orig_ax,
1489 regs->bx, regs->cx,
1490 regs->dx, regs->si);
1491#ifdef CONFIG_X86_64
1492 else
1493 audit_syscall_entry(AUDIT_ARCH_X86_64,
1494 regs->orig_ax,
1495 regs->di, regs->si,
1496 regs->dx, regs->r10);
1497#endif
1498 1597
1499out:
1500 return ret ?: regs->orig_ax; 1598 return ret ?: regs->orig_ax;
1501} 1599}
1502 1600
1601long syscall_trace_enter(struct pt_regs *regs)
1602{
1603 u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
1604 unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
1605
1606 if (phase1_result == 0)
1607 return regs->orig_ax;
1608 else
1609 return syscall_trace_enter_phase2(regs, arch, phase1_result);
1610}
1611
1503void syscall_trace_leave(struct pt_regs *regs) 1612void syscall_trace_leave(struct pt_regs *regs)
1504{ 1613{
1505 bool step; 1614 bool step;