Merge git://git.infradead.org/users/eparis/audit
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 19 Oct 2014 23:25:56 +0000 (16:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 19 Oct 2014 23:25:56 +0000 (16:25 -0700)
Pull audit updates from Eric Paris:
 "So this change across a whole bunch of arches really solves one basic
  problem.  We want to audit when seccomp is killing a process.  seccomp
  hooks in before the audit syscall entry code.  audit_syscall_entry
  took as an argument the arch of the given syscall.  Since the arch is
  part of what makes a syscall number meaningful it's an important part
  of the record, but it isn't available when seccomp shoots the
  syscall...

  For most arch's we have a better way to get the arch (syscall_get_arch)
  So the solution was two fold: Implement syscall_get_arch() everywhere
  there is audit which didn't have it.  Use syscall_get_arch() in the
  seccomp audit code.  Having syscall_get_arch() everywhere meant it was
  a useless flag on the stack and we could get rid of it for the typical
  syscall entry.

  The other changes inside the audit system aren't grand, fixed some
  records that had invalid spaces.  Better locking around the task comm
  field.  Removing some dead functions and structs.  Make some things
  static.  Really minor stuff"

* git://git.infradead.org/users/eparis/audit: (31 commits)
  audit: rename audit_log_remove_rule to disambiguate for trees
  audit: cull redundancy in audit_rule_change
  audit: WARN if audit_rule_change called illegally
  audit: put rule existence check in canonical order
  next: openrisc: Fix build
  audit: get comm using lock to avoid race in string printing
  audit: remove open_arg() function that is never used
  audit: correct AUDIT_GET_FEATURE return message type
  audit: set nlmsg_len for multicast messages.
  audit: use union for audit_field values since they are mutually exclusive
  audit: invalid op= values for rules
  audit: use atomic_t to simplify audit_serial()
  kernel/audit.c: use ARRAY_SIZE instead of sizeof/sizeof[0]
  audit: reduce scope of audit_log_fcaps
  audit: reduce scope of audit_net_id
  audit: arm64: Remove the audit arch argument to audit_syscall_entry
  arm64: audit: Add audit hook in syscall_trace_enter/exit()
  audit: x86: drop arch from __audit_syscall_entry() interface
  sparc: implement is_32bit_task
  sparc: properly conditionalize use of TIF_32BIT
  ...

15 files changed:
1  2 
arch/arm/kernel/ptrace.c
arch/arm64/kernel/ptrace.c
arch/mips/include/asm/syscall.h
arch/mips/kernel/ptrace.c
arch/parisc/kernel/ptrace.c
arch/powerpc/kernel/ptrace.c
arch/s390/kernel/ptrace.c
arch/sparc/include/asm/thread_info_64.h
arch/x86/ia32/ia32entry.S
arch/x86/kernel/entry_32.S
arch/x86/kernel/ptrace.c
include/uapi/linux/audit.h
kernel/audit.c
kernel/auditfilter.c
kernel/auditsc.c

Simple merge
Simple merge
@@@ -129,14 -129,12 +129,14 @@@ extern const unsigned long sysn32_call_
  
  static inline int syscall_get_arch(void)
  {
-       int arch = EM_MIPS;
+       int arch = AUDIT_ARCH_MIPS;
  #ifdef CONFIG_64BIT
 -      if (!test_thread_flag(TIF_32BIT_REGS))
 +      if (!test_thread_flag(TIF_32BIT_REGS)) {
                arch |= __AUDIT_ARCH_64BIT;
 -      if (test_thread_flag(TIF_32BIT_ADDR))
 -              arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
 +              /* N32 sets only TIF_32BIT_ADDR */
 +              if (test_thread_flag(TIF_32BIT_ADDR))
 +                      arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
 +      }
  #endif
  #if defined(__LITTLE_ENDIAN)
        arch |=  __AUDIT_ARCH_LE;
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -194,16 -184,14 +194,16 @@@ sysexit_from_sys_call
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS_SYSEXIT32
  
 +      CFI_RESTORE_STATE
 +
  #ifdef CONFIG_AUDITSYSCALL
        .macro auditsys_entry_common
-       movl %esi,%r9d                  /* 6th arg: 4th syscall arg */
-       movl %edx,%r8d                  /* 5th arg: 3rd syscall arg */
-       /* (already in %ecx)               4th arg: 2nd syscall arg */
-       movl %ebx,%edx                  /* 3rd arg: 1st syscall arg */
-       movl %eax,%esi                  /* 2nd arg: syscall number */
-       movl $AUDIT_ARCH_I386,%edi      /* 1st arg: audit arch */
+       movl %esi,%r8d                  /* 5th arg: 4th syscall arg */
+       movl %ecx,%r9d                  /*swap with edx*/
+       movl %edx,%ecx                  /* 4th arg: 3rd syscall arg */
+       movl %r9d,%edx                  /* 3rd arg: 2nd syscall arg */
+       movl %ebx,%esi                  /* 2nd arg: 1st syscall arg */
+       movl %eax,%edi                  /* 1st arg: syscall number */
        call __audit_syscall_entry
        movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall number */
        cmpq $(IA32_NR_syscalls-1),%rax
Simple merge
@@@ -1441,126 -1441,24 +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
Simple merge
diff --cc kernel/audit.c
Simple merge
Simple merge
Simple merge