x86/entry: Get rid of two-phase syscall entry work
authorAndy Lutomirski <luto@kernel.org>
Fri, 27 May 2016 20:08:59 +0000 (13:08 -0700)
committerKees Cook <keescook@chromium.org>
Tue, 14 Jun 2016 17:54:39 +0000 (10:54 -0700)
I added two-phase syscall entry work back when the entry slow path
was very slow.  Nowadays, the entry slow path is fast and two-phase
entry work serves no purpose.  Remove it.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
arch/x86/entry/common.c
arch/x86/include/asm/ptrace.h

index ec138e538c44f9acf7f829827d14a3991473763f..df56ca39487700c42b7a2bd6f62b8d6657de8c2a 100644 (file)
@@ -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)
index 6271281f947d82d5a463c849e17b0e60c8faf228..2b5d686ea9f37b3bd503d44e9481fd17682a2e6e 100644 (file)
@@ -83,12 +83,6 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
                         int error_code, int si_code);
 
 
-extern unsigned long syscall_trace_enter_phase1(struct pt_regs *, u32 arch);
-extern long syscall_trace_enter_phase2(struct pt_regs *, u32 arch,
-                                      unsigned long phase1_result);
-
-extern long syscall_trace_enter(struct pt_regs *);
-
 static inline unsigned long regs_return_value(struct pt_regs *regs)
 {
        return regs->ax;