Hi all,

Today's linux-next merge of the tip tree got a conflict in
arch/x86/kernel/ptrace.c between commit 91397401bb50 ("ARCH: AUDIT:
audit_syscall_entry() should not require the arch") from the audit tree
and commit e0ffbaabc46d ("x86: Split syscall_trace_enter into two
phases") from the tip tree.

I fixed it up (see below - there is more cleanup possible since
do_audit_syscall_entry() no longer needs its "arch" argument) and can
carry the fix as necessary (no action is required).

-- 
Cheers,
Stephen Rothwell                    s...@canb.auug.org.au

diff --cc arch/x86/kernel/ptrace.c
index eb1c87f0b03b,29576c244699..000000000000
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@@ -1441,24 -1441,126 +1441,126 @@@ void send_sigtrap(struct task_struct *t
        force_sig_info(SIGTRAP, &info, tsk);
  }
  
- 
- #ifdef CONFIG_X86_32
- # define IS_IA32      1
- #elif defined CONFIG_IA32_EMULATION
- # define IS_IA32      is_compat_task()
- #else
- # define IS_IA32      0
+ static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
+ {
+ #ifdef CONFIG_X86_64
+       if (arch == AUDIT_ARCH_X86_64) {
 -              audit_syscall_entry(arch, regs->orig_ax, regs->di,
++              audit_syscall_entry(regs->orig_ax, regs->di,
+                                   regs->si, regs->dx, regs->r10);
+       } else
  #endif
+       {
 -              audit_syscall_entry(arch, regs->orig_ax, regs->bx,
++              audit_syscall_entry(regs->orig_ax, regs->bx,
+                                   regs->cx, regs->dx, regs->si);
+       }
+ }
  
  /*
-  * We must return the syscall number to actually look up in the table.
-  * This can be -1L to skip running any syscall at all.
+  * 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
   */
- long syscall_trace_enter(struct pt_regs *regs)
+ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
+ {
+       unsigned long ret = 0;
+       u32 work;
+ 
+       BUG_ON(regs != task_pt_regs(current));
+ 
+       work = ACCESS_ONCE(current_thread_info()->flags) &
+               _TIF_WORK_SYSCALL_ENTRY;
+ 
+       /*
+        * If TIF_NOHZ is set, we are required to call user_exit() before
+        * doing anything that could touch RCU.
+        */
+       if (work & _TIF_NOHZ) {
+               user_exit();
+               work &= ~TIF_NOHZ;
+       }
+ 
+ #ifdef CONFIG_SECCOMP
+       /*
+        * Do seccomp first -- it should minimize exposure of other
+        * code, and keeping seccomp fast is probably more valuable
+        * than the rest of this.
+        */
+       if (work & _TIF_SECCOMP) {
+               struct seccomp_data sd;
+ 
+               sd.arch = arch;
+               sd.nr = regs->orig_ax;
+               sd.instruction_pointer = regs->ip;
+ #ifdef CONFIG_X86_64
+               if (arch == AUDIT_ARCH_X86_64) {
+                       sd.args[0] = regs->di;
+                       sd.args[1] = regs->si;
+                       sd.args[2] = regs->dx;
+                       sd.args[3] = regs->r10;
+                       sd.args[4] = regs->r8;
+                       sd.args[5] = regs->r9;
+               } else
+ #endif
+               {
+                       sd.args[0] = regs->bx;
+                       sd.args[1] = regs->cx;
+                       sd.args[2] = regs->dx;
+                       sd.args[3] = regs->si;
+                       sd.args[4] = regs->di;
+                       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)
  {
        long ret = 0;
+       u32 work = ACCESS_ONCE(current_thread_info()->flags) &
+               _TIF_WORK_SYSCALL_ENTRY;
  
-       user_exit();
+       BUG_ON(regs != task_pt_regs(current));
  
        /*
         * If we stepped into a sysenter/syscall insn, it trapped in

Attachment: signature.asc
Description: PGP signature

Reply via email to