|
@@ -64,20 +64,13 @@ static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * We can return 0 to resume the syscall or anything else to go to phase
|
|
|
- * 2. If we resume the syscall, we need to put something appropriate in
|
|
|
- * regs->orig_ax.
|
|
|
- *
|
|
|
- * NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax
|
|
|
- * are fully functional.
|
|
|
- *
|
|
|
- * For phase 2's benefit, our return value is:
|
|
|
- * 0: resume the syscall
|
|
|
- * 1: go to phase 2; no seccomp phase 2 needed
|
|
|
- * anything else: go to phase 2; pass return value to seccomp
|
|
|
+ * Returns the syscall nr to run (which should match regs->orig_ax) or -1
|
|
|
+ * to skip the syscall.
|
|
|
*/
|
|
|
-unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
|
|
|
+static long syscall_trace_enter(struct pt_regs *regs)
|
|
|
{
|
|
|
+ u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
|
|
|
+
|
|
|
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
|
|
unsigned long ret = 0;
|
|
|
u32 work;
|
|
@@ -118,59 +111,9 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
|
|
|
sd.args[5] = regs->bp;
|
|
|
}
|
|
|
|
|
|
- BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0);
|
|
|
- BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1);
|
|
|
-
|
|
|
- ret = seccomp_phase1(&sd);
|
|
|
- if (ret == SECCOMP_PHASE1_SKIP) {
|
|
|
- regs->orig_ax = -1;
|
|
|
- ret = 0;
|
|
|
- } else if (ret != SECCOMP_PHASE1_OK) {
|
|
|
- return ret; /* Go directly to phase 2 */
|
|
|
- }
|
|
|
-
|
|
|
- work &= ~_TIF_SECCOMP;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- /* Do our best to finish without phase 2. */
|
|
|
- if (work == 0)
|
|
|
- return ret; /* seccomp and/or nohz only (ret == 0 here) */
|
|
|
-
|
|
|
-#ifdef CONFIG_AUDITSYSCALL
|
|
|
- if (work == _TIF_SYSCALL_AUDIT) {
|
|
|
- /*
|
|
|
- * If there is no more work to be done except auditing,
|
|
|
- * then audit in phase 1. Phase 2 always audits, so, if
|
|
|
- * we audit here, then we can't go on to phase 2.
|
|
|
- */
|
|
|
- do_audit_syscall_entry(regs, arch);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- return 1; /* Something is enabled that we can't handle in phase 1 */
|
|
|
-}
|
|
|
-
|
|
|
-/* Returns the syscall nr to run (which should match regs->orig_ax). */
|
|
|
-long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
|
|
|
- unsigned long phase1_result)
|
|
|
-{
|
|
|
- struct thread_info *ti = pt_regs_to_thread_info(regs);
|
|
|
- long ret = 0;
|
|
|
- u32 work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
|
|
|
-
|
|
|
- if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
|
|
|
- BUG_ON(regs != task_pt_regs(current));
|
|
|
-
|
|
|
-#ifdef CONFIG_SECCOMP
|
|
|
- /*
|
|
|
- * Call seccomp_phase2 before running the other hooks so that
|
|
|
- * they can see any changes made by a seccomp tracer.
|
|
|
- */
|
|
|
- if (phase1_result > 1 && seccomp_phase2(phase1_result)) {
|
|
|
- /* seccomp failures shouldn't expose any additional code. */
|
|
|
- return -1;
|
|
|
+ ret = __secure_computing(&sd);
|
|
|
+ if (ret == -1)
|
|
|
+ return ret;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -189,17 +132,6 @@ long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
|
|
|
return ret ?: regs->orig_ax;
|
|
|
}
|
|
|
|
|
|
-long syscall_trace_enter(struct pt_regs *regs)
|
|
|
-{
|
|
|
- u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
|
|
|
- unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
|
|
|
-
|
|
|
- if (phase1_result == 0)
|
|
|
- return regs->orig_ax;
|
|
|
- else
|
|
|
- return syscall_trace_enter_phase2(regs, arch, phase1_result);
|
|
|
-}
|
|
|
-
|
|
|
#define EXIT_TO_USERMODE_LOOP_FLAGS \
|
|
|
(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
|
|
_TIF_NEED_RESCHED | _TIF_USER_RETURN_NOTIFY)
|