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

diff --combined arch/arm/kernel/ptrace.c
index 5e772a21ab9707916b82cb4d2a42d24fcb1bf878,6af95986fbf7926be0c2fee04e76d607c64fb557..ef9119f7462ea11550fc0e6edaa756d9edc39905
@@@ -933,13 -933,8 +933,13 @@@ asmlinkage int syscall_trace_enter(stru
        current_thread_info()->syscall = scno;
  
        /* Do the secure computing check first; failures should be fast. */
 -      if (secure_computing(scno) == -1)
 +#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
 +      if (secure_computing() == -1)
                return -1;
 +#else
 +      /* XXX: remove this once OABI gets fixed */
 +      secure_computing_strict(scno);
 +#endif
  
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, scno);
  
-       audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
-                           regs->ARM_r2, regs->ARM_r3);
+       audit_syscall_entry(scno, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
+                           regs->ARM_r3);
  
        return scno;
  }
index fe63ac5e9bf5582cb4e494262a9d714d4b6758a7,310842e3d4777be62f59cdc3aa149edcfd6fd59f..8a4ae8e73213a26add3da24f8a0ea2a8f17ff4ed
@@@ -87,8 -87,7 +87,8 @@@ static void ptrace_hbptriggered(struct 
                        break;
                }
        }
 -      for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) {
 +
 +      for (i = 0; i < ARM_MAX_WRP; ++i) {
                if (current->thread.debug.hbp_watch[i] == bp) {
                        info.si_errno = -((i << 1) + 1);
                        break;
@@@ -663,10 -662,8 +663,10 @@@ static int compat_gpr_get(struct task_s
                        kbuf += sizeof(reg);
                } else {
                        ret = copy_to_user(ubuf, &reg, sizeof(reg));
 -                      if (ret)
 +                      if (ret) {
 +                              ret = -EFAULT;
                                break;
 +                      }
  
                        ubuf += sizeof(reg);
                }
@@@ -704,10 -701,8 +704,10 @@@ static int compat_gpr_set(struct task_s
                        kbuf += sizeof(reg);
                } else {
                        ret = copy_from_user(&reg, ubuf, sizeof(reg));
 -                      if (ret)
 -                              return ret;
 +                      if (ret) {
 +                              ret = -EFAULT;
 +                              break;
 +                      }
  
                        ubuf += sizeof(reg);
                }
@@@ -1120,8 -1115,8 +1120,8 @@@ asmlinkage int syscall_trace_enter(stru
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, regs->syscallno);
  
-       audit_syscall_entry(syscall_get_arch(), regs->syscallno,
-               regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]);
+       audit_syscall_entry(regs->syscallno, regs->orig_x0, regs->regs[1],
+                           regs->regs[2], regs->regs[3]);
  
        return regs->syscallno;
  }
index cdf68b33bd65ac5826ac369a4d06aeedc3d1fd90,93b3b86c293c854538fb33f5b7b45e162e7b8471..bb7963753730d817117f209e6bac10f4943a0b56
@@@ -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;
index f7aac5b57b4b8e29470d0d2dd5ee37db4523398e,d8a76f97a053d8097593fad41c06ef8afc21fee6..9d1487d832932a0b3dcb4d2c694e773e753a8767
@@@ -24,6 -24,7 +24,6 @@@
  #include <linux/ptrace.h>
  #include <linux/regset.h>
  #include <linux/smp.h>
 -#include <linux/user.h>
  #include <linux/security.h>
  #include <linux/tracehook.h>
  #include <linux/audit.h>
@@@ -62,7 -63,7 +62,7 @@@ void ptrace_disable(struct task_struct 
   * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
   * Registers are sign extended to fill the available space.
   */
 -int ptrace_getregs(struct task_struct *child, __s64 __user *data)
 +int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
  {
        struct pt_regs *regs;
        int i;
        regs = task_pt_regs(child);
  
        for (i = 0; i < 32; i++)
 -              __put_user((long)regs->regs[i], data + i);
 -      __put_user((long)regs->lo, data + EF_LO - EF_R0);
 -      __put_user((long)regs->hi, data + EF_HI - EF_R0);
 -      __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
 -      __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
 -      __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
 -      __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
 +              __put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
 +      __put_user((long)regs->lo, (__s64 __user *)&data->lo);
 +      __put_user((long)regs->hi, (__s64 __user *)&data->hi);
 +      __put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
 +      __put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
 +      __put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
 +      __put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
  
        return 0;
  }
@@@ -89,7 -90,7 +89,7 @@@
   * the 64-bit format.  On a 32-bit kernel only the lower order half
   * (according to endianness) will be used.
   */
 -int ptrace_setregs(struct task_struct *child, __s64 __user *data)
 +int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
  {
        struct pt_regs *regs;
        int i;
        regs = task_pt_regs(child);
  
        for (i = 0; i < 32; i++)
 -              __get_user(regs->regs[i], data + i);
 -      __get_user(regs->lo, data + EF_LO - EF_R0);
 -      __get_user(regs->hi, data + EF_HI - EF_R0);
 -      __get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
 +              __get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
 +      __get_user(regs->lo, (__s64 __user *)&data->lo);
 +      __get_user(regs->hi, (__s64 __user *)&data->hi);
 +      __get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
  
        /* badvaddr, status, and cause may not be written.  */
  
@@@ -128,7 -129,7 +128,7 @@@ int ptrace_getfpregs(struct task_struc
        }
  
        __put_user(child->thread.fpu.fcr31, data + 64);
 -      __put_user(current_cpu_data.fpu_id, data + 65);
 +      __put_user(boot_cpu_data.fpu_id, data + 65);
  
        return 0;
  }
@@@ -150,7 -151,6 +150,7 @@@ int ptrace_setfpregs(struct task_struc
        }
  
        __get_user(child->thread.fpu.fcr31, data + 64);
 +      child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
  
        /* FIR may not be written.  */
  
@@@ -246,160 -246,36 +246,160 @@@ int ptrace_set_watch_regs(struct task_s
  
  /* regset get/set implementations */
  
 -static int gpr_get(struct task_struct *target,
 -                 const struct user_regset *regset,
 -                 unsigned int pos, unsigned int count,
 -                 void *kbuf, void __user *ubuf)
 +#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
 +
 +static int gpr32_get(struct task_struct *target,
 +                   const struct user_regset *regset,
 +                   unsigned int pos, unsigned int count,
 +                   void *kbuf, void __user *ubuf)
  {
        struct pt_regs *regs = task_pt_regs(target);
 +      u32 uregs[ELF_NGREG] = {};
 +      unsigned i;
 +
 +      for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
 +              /* k0/k1 are copied as zero. */
 +              if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
 +                      continue;
 +
 +              uregs[i] = regs->regs[i - MIPS32_EF_R0];
 +      }
  
 -      return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 -                                 regs, 0, sizeof(*regs));
 +      uregs[MIPS32_EF_LO] = regs->lo;
 +      uregs[MIPS32_EF_HI] = regs->hi;
 +      uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
 +      uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
 +      uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
 +      uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
 +
 +      return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
 +                                 sizeof(uregs));
  }
  
 -static int gpr_set(struct task_struct *target,
 -                 const struct user_regset *regset,
 -                 unsigned int pos, unsigned int count,
 -                 const void *kbuf, const void __user *ubuf)
 +static int gpr32_set(struct task_struct *target,
 +                   const struct user_regset *regset,
 +                   unsigned int pos, unsigned int count,
 +                   const void *kbuf, const void __user *ubuf)
  {
 -      struct pt_regs newregs;
 -      int ret;
 +      struct pt_regs *regs = task_pt_regs(target);
 +      u32 uregs[ELF_NGREG];
 +      unsigned start, num_regs, i;
 +      int err;
 +
 +      start = pos / sizeof(u32);
 +      num_regs = count / sizeof(u32);
 +
 +      if (start + num_regs > ELF_NGREG)
 +              return -EIO;
 +
 +      err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
 +                               sizeof(uregs));
 +      if (err)
 +              return err;
 +
 +      for (i = start; i < num_regs; i++) {
 +              /*
 +               * Cast all values to signed here so that if this is a 64-bit
 +               * kernel, the supplied 32-bit values will be sign extended.
 +               */
 +              switch (i) {
 +              case MIPS32_EF_R1 ... MIPS32_EF_R25:
 +                      /* k0/k1 are ignored. */
 +              case MIPS32_EF_R28 ... MIPS32_EF_R31:
 +                      regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
 +                      break;
 +              case MIPS32_EF_LO:
 +                      regs->lo = (s32)uregs[i];
 +                      break;
 +              case MIPS32_EF_HI:
 +                      regs->hi = (s32)uregs[i];
 +                      break;
 +              case MIPS32_EF_CP0_EPC:
 +                      regs->cp0_epc = (s32)uregs[i];
 +                      break;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
 +
 +#ifdef CONFIG_64BIT
 +
 +static int gpr64_get(struct task_struct *target,
 +                   const struct user_regset *regset,
 +                   unsigned int pos, unsigned int count,
 +                   void *kbuf, void __user *ubuf)
 +{
 +      struct pt_regs *regs = task_pt_regs(target);
 +      u64 uregs[ELF_NGREG] = {};
 +      unsigned i;
 +
 +      for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
 +              /* k0/k1 are copied as zero. */
 +              if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
 +                      continue;
 +
 +              uregs[i] = regs->regs[i - MIPS64_EF_R0];
 +      }
 +
 +      uregs[MIPS64_EF_LO] = regs->lo;
 +      uregs[MIPS64_EF_HI] = regs->hi;
 +      uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
 +      uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
 +      uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
 +      uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
 +
 +      return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
 +                                 sizeof(uregs));
 +}
  
 -      ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 -                               &newregs,
 -                               0, sizeof(newregs));
 -      if (ret)
 -              return ret;
 +static int gpr64_set(struct task_struct *target,
 +                   const struct user_regset *regset,
 +                   unsigned int pos, unsigned int count,
 +                   const void *kbuf, const void __user *ubuf)
 +{
 +      struct pt_regs *regs = task_pt_regs(target);
 +      u64 uregs[ELF_NGREG];
 +      unsigned start, num_regs, i;
 +      int err;
 +
 +      start = pos / sizeof(u64);
 +      num_regs = count / sizeof(u64);
  
 -      *task_pt_regs(target) = newregs;
 +      if (start + num_regs > ELF_NGREG)
 +              return -EIO;
 +
 +      err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
 +                               sizeof(uregs));
 +      if (err)
 +              return err;
 +
 +      for (i = start; i < num_regs; i++) {
 +              switch (i) {
 +              case MIPS64_EF_R1 ... MIPS64_EF_R25:
 +                      /* k0/k1 are ignored. */
 +              case MIPS64_EF_R28 ... MIPS64_EF_R31:
 +                      regs->regs[i - MIPS64_EF_R0] = uregs[i];
 +                      break;
 +              case MIPS64_EF_LO:
 +                      regs->lo = uregs[i];
 +                      break;
 +              case MIPS64_EF_HI:
 +                      regs->hi = uregs[i];
 +                      break;
 +              case MIPS64_EF_CP0_EPC:
 +                      regs->cp0_epc = uregs[i];
 +                      break;
 +              }
 +      }
  
        return 0;
  }
  
 +#endif /* CONFIG_64BIT */
 +
  static int fpr_get(struct task_struct *target,
                   const struct user_regset *regset,
                   unsigned int pos, unsigned int count,
@@@ -461,16 -337,14 +461,16 @@@ enum mips_regset 
        REGSET_FPR,
  };
  
 +#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
 +
  static const struct user_regset mips_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
                .n              = ELF_NGREG,
                .size           = sizeof(unsigned int),
                .align          = sizeof(unsigned int),
 -              .get            = gpr_get,
 -              .set            = gpr_set,
 +              .get            = gpr32_get,
 +              .set            = gpr32_set,
        },
        [REGSET_FPR] = {
                .core_note_type = NT_PRFPREG,
@@@ -490,18 -364,14 +490,18 @@@ static const struct user_regset_view us
        .n              = ARRAY_SIZE(mips_regsets),
  };
  
 +#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
 +
 +#ifdef CONFIG_64BIT
 +
  static const struct user_regset mips64_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
                .n              = ELF_NGREG,
                .size           = sizeof(unsigned long),
                .align          = sizeof(unsigned long),
 -              .get            = gpr_get,
 -              .set            = gpr_set,
 +              .get            = gpr64_get,
 +              .set            = gpr64_set,
        },
        [REGSET_FPR] = {
                .core_note_type = NT_PRFPREG,
  };
  
  static const struct user_regset_view user_mips64_view = {
 -      .name           = "mips",
 +      .name           = "mips64",
        .e_machine      = ELF_ARCH,
        .ei_osabi       = ELF_OSABI,
        .regsets        = mips64_regsets,
 -      .n              = ARRAY_SIZE(mips_regsets),
 +      .n              = ARRAY_SIZE(mips64_regsets),
  };
  
 +#endif /* CONFIG_64BIT */
 +
  const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  {
  #ifdef CONFIG_32BIT
        return &user_mips_view;
 -#endif
 -
 +#else
  #ifdef CONFIG_MIPS32_O32
 -              if (test_thread_flag(TIF_32BIT_REGS))
 -                      return &user_mips_view;
 +      if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
 +              return &user_mips_view;
  #endif
 -
        return &user_mips64_view;
 +#endif
  }
  
  long arch_ptrace(struct task_struct *child, long request,
                        break;
                case FPC_EIR:
                        /* implementation / version register */
 -                      tmp = current_cpu_data.fpu_id;
 +                      tmp = boot_cpu_data.fpu_id;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
                        break;
  #endif
                case FPC_CSR:
 -                      child->thread.fpu.fcr31 = data;
 +                      child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
@@@ -770,7 -639,7 +770,7 @@@ asmlinkage long syscall_trace_enter(str
        long ret = 0;
        user_exit();
  
 -      if (secure_computing(syscall) == -1)
 +      if (secure_computing() == -1)
                return -1;
  
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->regs[2]);
  
-       audit_syscall_entry(syscall_get_arch(),
-                           syscall,
-                           regs->regs[4], regs->regs[5],
+       audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
                            regs->regs[6], regs->regs[7]);
        return syscall;
  }
index 92438c21d4532e4c55d93adace8da60b081e88cf,74814577e4b8a18a9aaf117d63cdde384de6c557..9585c81f755fc667370ed850cba16ee1ff91024c
@@@ -17,7 -17,6 +17,7 @@@
  #include <linux/user.h>
  #include <linux/personality.h>
  #include <linux/security.h>
 +#include <linux/seccomp.h>
  #include <linux/compat.h>
  #include <linux/signal.h>
  #include <linux/audit.h>
@@@ -271,23 -270,17 +271,20 @@@ long do_syscall_trace_enter(struct pt_r
  {
        long ret = 0;
  
 +      /* Do the secure computing check first. */
 +      secure_computing_strict(regs->gr[20]);
 +
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
            tracehook_report_syscall_entry(regs))
                ret = -1L;
  
  #ifdef CONFIG_64BIT
        if (!is_compat_task())
-               audit_syscall_entry(AUDIT_ARCH_PARISC64,
-                       regs->gr[20],
-                       regs->gr[26], regs->gr[25],
-                       regs->gr[24], regs->gr[23]);
+               audit_syscall_entry(regs->gr[20], regs->gr[26], regs->gr[25],
+                                   regs->gr[24], regs->gr[23]);
        else
  #endif
-               audit_syscall_entry(AUDIT_ARCH_PARISC,
-                       regs->gr[20] & 0xffffffff,
+               audit_syscall_entry(regs->gr[20] & 0xffffffff,
                        regs->gr[26] & 0xffffffff,
                        regs->gr[25] & 0xffffffff,
                        regs->gr[24] & 0xffffffff,
index cdb404ea34688b581a788694ed1f8da43aed1f91,524a943a33bb24831deada106866f5313b7ce554..f21897b420576c63330eb5c62982ba0729229a85
@@@ -932,7 -932,7 +932,7 @@@ void ptrace_triggered(struct perf_even
  }
  #endif /* CONFIG_HAVE_HW_BREAKPOINT */
  
 -int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 +static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                               unsigned long data)
  {
  #ifdef CONFIG_HAVE_HW_BREAKPOINT
@@@ -1788,14 -1788,11 +1788,11 @@@ long do_syscall_trace_enter(struct pt_r
  
  #ifdef CONFIG_PPC64
        if (!is_32bit_task())
-               audit_syscall_entry(AUDIT_ARCH_PPC64,
-                                   regs->gpr[0],
-                                   regs->gpr[3], regs->gpr[4],
+               audit_syscall_entry(regs->gpr[0], regs->gpr[3], regs->gpr[4],
                                    regs->gpr[5], regs->gpr[6]);
        else
  #endif
-               audit_syscall_entry(AUDIT_ARCH_PPC,
-                                   regs->gpr[0],
+               audit_syscall_entry(regs->gpr[0],
                                    regs->gpr[3] & 0xffffffff,
                                    regs->gpr[4] & 0xffffffff,
                                    regs->gpr[5] & 0xffffffff,
index f537e937a9882f74f61a4830651bbd1abd4ddc66,910f253b22bcc97bc45421711bc8c49663c0ed8a..99a567b70d16f6e18a0028b0221f2bb2962f2718
  #define CREATE_TRACE_POINTS
  #include <trace/events/syscalls.h>
  
 -enum s390_regset {
 -      REGSET_GENERAL,
 -      REGSET_FP,
 -      REGSET_LAST_BREAK,
 -      REGSET_TDB,
 -      REGSET_SYSTEM_CALL,
 -      REGSET_GENERAL_EXTENDED,
 -};
 -
  void update_cr_regs(struct task_struct *task)
  {
        struct pt_regs *regs = task_pt_regs(task);
  
  #ifdef CONFIG_64BIT
        /* Take care of the enable/disable of transactional execution. */
 -      if (MACHINE_HAS_TE) {
 +      if (MACHINE_HAS_TE || MACHINE_HAS_VX) {
                unsigned long cr, cr_new;
  
                __ctl_store(cr, 0, 0);
 -              /* Set or clear transaction execution TXC bit 8. */
 -              cr_new = cr | (1UL << 55);
 -              if (task->thread.per_flags & PER_FLAG_NO_TE)
 -                      cr_new &= ~(1UL << 55);
 +              cr_new = cr;
 +              if (MACHINE_HAS_TE) {
 +                      /* Set or clear transaction execution TXC bit 8. */
 +                      cr_new |= (1UL << 55);
 +                      if (task->thread.per_flags & PER_FLAG_NO_TE)
 +                              cr_new &= ~(1UL << 55);
 +              }
 +              if (MACHINE_HAS_VX) {
 +                      /* Enable/disable of vector extension */
 +                      cr_new &= ~(1UL << 17);
 +                      if (task->thread.vxrs)
 +                              cr_new |= (1UL << 17);
 +              }
                if (cr_new != cr)
                        __ctl_load(cr_new, 0, 0);
 -              /* Set or clear transaction execution TDC bits 62 and 63. */
 -              __ctl_store(cr, 2, 2);
 -              cr_new = cr & ~3UL;
 -              if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
 -                      if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
 -                              cr_new |= 1UL;
 -                      else
 -                              cr_new |= 2UL;
 +              if (MACHINE_HAS_TE) {
 +                      /* Set/clear transaction execution TDC bits 62/63. */
 +                      __ctl_store(cr, 2, 2);
 +                      cr_new = cr & ~3UL;
 +                      if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
 +                              if (task->thread.per_flags &
 +                                  PER_FLAG_TE_ABORT_RAND_TEND)
 +                                      cr_new |= 1UL;
 +                              else
 +                                      cr_new |= 2UL;
 +                      }
 +                      if (cr_new != cr)
 +                              __ctl_load(cr_new, 2, 2);
                }
 -              if (cr_new != cr)
 -                      __ctl_load(cr_new, 2, 2);
        }
  #endif
        /* Copy user specified PER registers */
@@@ -87,8 -84,7 +87,8 @@@
        new.end = thread->per_user.end;
  
        /* merge TIF_SINGLE_STEP into user specified PER registers. */
 -      if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
 +      if (test_tsk_thread_flag(task, TIF_SINGLE_STEP) ||
 +          test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) {
                if (test_tsk_thread_flag(task, TIF_BLOCK_STEP))
                        new.control |= PER_EVENT_BRANCH;
                else
@@@ -97,8 -93,6 +97,8 @@@
                new.control |= PER_CONTROL_SUSPENSION;
                new.control |= PER_EVENT_TRANSACTION_END;
  #endif
 +              if (test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP))
 +                      new.control |= PER_EVENT_IFETCH;
                new.start = 0;
                new.end = PSW_ADDR_INSN;
        }
@@@ -809,7 -803,7 +809,7 @@@ asmlinkage long do_syscall_trace_enter(
        long ret = 0;
  
        /* Do the secure computing check first. */
 -      if (secure_computing(regs->gprs[2])) {
 +      if (secure_computing()) {
                /* seccomp failures shouldn't expose any additional code. */
                ret = -1;
                goto out;
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->gprs[2]);
  
-       audit_syscall_entry(is_compat_task() ?
-                               AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
-                           regs->gprs[2], regs->orig_gpr2,
+       audit_syscall_entry(regs->gprs[2], regs->orig_gpr2,
                            regs->gprs[3], regs->gprs[4],
                            regs->gprs[5]);
  out:
@@@ -929,15 -921,7 +927,15 @@@ static int s390_fpregs_get(struct task_
                save_fp_ctl(&target->thread.fp_regs.fpc);
                save_fp_regs(target->thread.fp_regs.fprs);
        }
 +#ifdef CONFIG_64BIT
 +      else if (target->thread.vxrs) {
 +              int i;
  
 +              for (i = 0; i < __NUM_VXRS_LOW; i++)
 +                      target->thread.fp_regs.fprs[i] =
 +                              *(freg_t *)(target->thread.vxrs + i);
 +      }
 +#endif
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
                                   &target->thread.fp_regs, 0, -1);
  }
@@@ -971,20 -955,9 +969,20 @@@ static int s390_fpregs_set(struct task_
                                        target->thread.fp_regs.fprs,
                                        offsetof(s390_fp_regs, fprs), -1);
  
 -      if (rc == 0 && target == current) {
 -              restore_fp_ctl(&target->thread.fp_regs.fpc);
 -              restore_fp_regs(target->thread.fp_regs.fprs);
 +      if (rc == 0) {
 +              if (target == current) {
 +                      restore_fp_ctl(&target->thread.fp_regs.fpc);
 +                      restore_fp_regs(target->thread.fp_regs.fprs);
 +              }
 +#ifdef CONFIG_64BIT
 +              else if (target->thread.vxrs) {
 +                      int i;
 +
 +                      for (i = 0; i < __NUM_VXRS_LOW; i++)
 +                              *(freg_t *)(target->thread.vxrs + i) =
 +                                      target->thread.fp_regs.fprs[i];
 +              }
 +#endif
        }
  
        return rc;
@@@ -1040,95 -1013,6 +1038,95 @@@ static int s390_tdb_set(struct task_str
        return 0;
  }
  
 +static int s390_vxrs_active(struct task_struct *target,
 +                            const struct user_regset *regset)
 +{
 +      return !!target->thread.vxrs;
 +}
 +
 +static int s390_vxrs_low_get(struct task_struct *target,
 +                           const struct user_regset *regset,
 +                           unsigned int pos, unsigned int count,
 +                           void *kbuf, void __user *ubuf)
 +{
 +      __u64 vxrs[__NUM_VXRS_LOW];
 +      int i;
 +
 +      if (target->thread.vxrs) {
 +              if (target == current)
 +                      save_vx_regs(target->thread.vxrs);
 +              for (i = 0; i < __NUM_VXRS_LOW; i++)
 +                      vxrs[i] = *((__u64 *)(target->thread.vxrs + i) + 1);
 +      } else
 +              memset(vxrs, 0, sizeof(vxrs));
 +      return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 +}
 +
 +static int s390_vxrs_low_set(struct task_struct *target,
 +                           const struct user_regset *regset,
 +                           unsigned int pos, unsigned int count,
 +                           const void *kbuf, const void __user *ubuf)
 +{
 +      __u64 vxrs[__NUM_VXRS_LOW];
 +      int i, rc;
 +
 +      if (!target->thread.vxrs) {
 +              rc = alloc_vector_registers(target);
 +              if (rc)
 +                      return rc;
 +      } else if (target == current)
 +              save_vx_regs(target->thread.vxrs);
 +
 +      rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 +      if (rc == 0) {
 +              for (i = 0; i < __NUM_VXRS_LOW; i++)
 +                      *((__u64 *)(target->thread.vxrs + i) + 1) = vxrs[i];
 +              if (target == current)
 +                      restore_vx_regs(target->thread.vxrs);
 +      }
 +
 +      return rc;
 +}
 +
 +static int s390_vxrs_high_get(struct task_struct *target,
 +                            const struct user_regset *regset,
 +                            unsigned int pos, unsigned int count,
 +                            void *kbuf, void __user *ubuf)
 +{
 +      __vector128 vxrs[__NUM_VXRS_HIGH];
 +
 +      if (target->thread.vxrs) {
 +              if (target == current)
 +                      save_vx_regs(target->thread.vxrs);
 +              memcpy(vxrs, target->thread.vxrs + __NUM_VXRS_LOW,
 +                     sizeof(vxrs));
 +      } else
 +              memset(vxrs, 0, sizeof(vxrs));
 +      return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 +}
 +
 +static int s390_vxrs_high_set(struct task_struct *target,
 +                            const struct user_regset *regset,
 +                            unsigned int pos, unsigned int count,
 +                            const void *kbuf, const void __user *ubuf)
 +{
 +      int rc;
 +
 +      if (!target->thread.vxrs) {
 +              rc = alloc_vector_registers(target);
 +              if (rc)
 +                      return rc;
 +      } else if (target == current)
 +              save_vx_regs(target->thread.vxrs);
 +
 +      rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 +                              target->thread.vxrs + __NUM_VXRS_LOW, 0, -1);
 +      if (rc == 0 && target == current)
 +              restore_vx_regs(target->thread.vxrs);
 +
 +      return rc;
 +}
 +
  #endif
  
  static int s390_system_call_get(struct task_struct *target,
@@@ -1152,7 -1036,7 +1150,7 @@@ static int s390_system_call_set(struct 
  }
  
  static const struct user_regset s390_regsets[] = {
 -      [REGSET_GENERAL] = {
 +      {
                .core_note_type = NT_PRSTATUS,
                .n = sizeof(s390_regs) / sizeof(long),
                .size = sizeof(long),
                .get = s390_regs_get,
                .set = s390_regs_set,
        },
 -      [REGSET_FP] = {
 +      {
                .core_note_type = NT_PRFPREG,
                .n = sizeof(s390_fp_regs) / sizeof(long),
                .size = sizeof(long),
                .get = s390_fpregs_get,
                .set = s390_fpregs_set,
        },
 +      {
 +              .core_note_type = NT_S390_SYSTEM_CALL,
 +              .n = 1,
 +              .size = sizeof(unsigned int),
 +              .align = sizeof(unsigned int),
 +              .get = s390_system_call_get,
 +              .set = s390_system_call_set,
 +      },
  #ifdef CONFIG_64BIT
 -      [REGSET_LAST_BREAK] = {
 +      {
                .core_note_type = NT_S390_LAST_BREAK,
                .n = 1,
                .size = sizeof(long),
                .get = s390_last_break_get,
                .set = s390_last_break_set,
        },
 -      [REGSET_TDB] = {
 +      {
                .core_note_type = NT_S390_TDB,
                .n = 1,
                .size = 256,
                .get = s390_tdb_get,
                .set = s390_tdb_set,
        },
 -#endif
 -      [REGSET_SYSTEM_CALL] = {
 -              .core_note_type = NT_S390_SYSTEM_CALL,
 -              .n = 1,
 -              .size = sizeof(unsigned int),
 -              .align = sizeof(unsigned int),
 -              .get = s390_system_call_get,
 -              .set = s390_system_call_set,
 +      {
 +              .core_note_type = NT_S390_VXRS_LOW,
 +              .n = __NUM_VXRS_LOW,
 +              .size = sizeof(__u64),
 +              .align = sizeof(__u64),
 +              .active = s390_vxrs_active,
 +              .get = s390_vxrs_low_get,
 +              .set = s390_vxrs_low_set,
        },
 +      {
 +              .core_note_type = NT_S390_VXRS_HIGH,
 +              .n = __NUM_VXRS_HIGH,
 +              .size = sizeof(__vector128),
 +              .align = sizeof(__vector128),
 +              .active = s390_vxrs_active,
 +              .get = s390_vxrs_high_get,
 +              .set = s390_vxrs_high_set,
 +      },
 +#endif
  };
  
  static const struct user_regset_view user_s390_view = {
@@@ -1376,7 -1242,7 +1374,7 @@@ static int s390_compat_last_break_set(s
  }
  
  static const struct user_regset s390_compat_regsets[] = {
 -      [REGSET_GENERAL] = {
 +      {
                .core_note_type = NT_PRSTATUS,
                .n = sizeof(s390_compat_regs) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
                .get = s390_compat_regs_get,
                .set = s390_compat_regs_set,
        },
 -      [REGSET_FP] = {
 +      {
                .core_note_type = NT_PRFPREG,
                .n = sizeof(s390_fp_regs) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
                .get = s390_fpregs_get,
                .set = s390_fpregs_set,
        },
 -      [REGSET_LAST_BREAK] = {
 +      {
 +              .core_note_type = NT_S390_SYSTEM_CALL,
 +              .n = 1,
 +              .size = sizeof(compat_uint_t),
 +              .align = sizeof(compat_uint_t),
 +              .get = s390_system_call_get,
 +              .set = s390_system_call_set,
 +      },
 +      {
                .core_note_type = NT_S390_LAST_BREAK,
                .n = 1,
                .size = sizeof(long),
                .get = s390_compat_last_break_get,
                .set = s390_compat_last_break_set,
        },
 -      [REGSET_TDB] = {
 +      {
                .core_note_type = NT_S390_TDB,
                .n = 1,
                .size = 256,
                .get = s390_tdb_get,
                .set = s390_tdb_set,
        },
 -      [REGSET_SYSTEM_CALL] = {
 -              .core_note_type = NT_S390_SYSTEM_CALL,
 -              .n = 1,
 -              .size = sizeof(compat_uint_t),
 -              .align = sizeof(compat_uint_t),
 -              .get = s390_system_call_get,
 -              .set = s390_system_call_set,
 +      {
 +              .core_note_type = NT_S390_VXRS_LOW,
 +              .n = __NUM_VXRS_LOW,
 +              .size = sizeof(__u64),
 +              .align = sizeof(__u64),
 +              .active = s390_vxrs_active,
 +              .get = s390_vxrs_low_get,
 +              .set = s390_vxrs_low_set,
 +      },
 +      {
 +              .core_note_type = NT_S390_VXRS_HIGH,
 +              .n = __NUM_VXRS_HIGH,
 +              .size = sizeof(__vector128),
 +              .align = sizeof(__vector128),
 +              .active = s390_vxrs_active,
 +              .get = s390_vxrs_high_get,
 +              .set = s390_vxrs_high_set,
        },
 -      [REGSET_GENERAL_EXTENDED] = {
 +      {
                .core_note_type = NT_S390_HIGH_GPRS,
                .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
                .size = sizeof(compat_long_t),
index cc6275c931a5782037678abebb9710fff392dad1,5a4f6600e62482e59cba6ef126be934c614491bc..798f0279a4b56a3ccd23b29c7b527bbd329b3061
@@@ -63,8 -63,7 +63,8 @@@ struct thread_info 
        struct pt_regs          *kern_una_regs;
        unsigned int            kern_una_insn;
  
 -      unsigned long           fpregs[0] __attribute__ ((aligned(64)));
 +      unsigned long           fpregs[(7 * 256) / sizeof(unsigned long)]
 +              __attribute__ ((aligned(64)));
  };
  
  #endif /* !(__ASSEMBLY__) */
  #define FAULT_CODE_ITLB               0x04    /* Miss happened in I-TLB          */
  #define FAULT_CODE_WINFIXUP   0x08    /* Miss happened during spill/fill */
  #define FAULT_CODE_BLKCOMMIT  0x10    /* Use blk-commit ASI in copy_page */
 +#define       FAULT_CODE_BAD_RA       0x20    /* Bad RA for sun4v                */
  
  #if PAGE_SHIFT == 13
  #define THREAD_SIZE (2*PAGE_SIZE)
@@@ -221,6 -219,8 +221,8 @@@ register struct thread_info *current_th
                                 _TIF_NEED_RESCHED)
  #define _TIF_DO_NOTIFY_RESUME_MASK    (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING)
  
+ #define is_32bit_task()       (test_thread_flag(TIF_32BIT))
  /*
   * Thread-synchronous status.
   *
index 711de084ab57114dc8410ea3de0fdbe436e0cf93,f5bdd288181564ee90cb5e123e5442eb14da4791..8ffba18395c8bb0a93c6a9dc65cfd8739a5937f3
@@@ -151,16 -151,6 +151,16 @@@ ENTRY(ia32_sysenter_target
  1:    movl    (%rbp),%ebp
        _ASM_EXTABLE(1b,ia32_badarg)
        ASM_CLAC
 +
 +      /*
 +       * Sysenter doesn't filter flags, so we need to clear NT
 +       * ourselves.  To save a few cycles, we can check whether
 +       * NT was set instead of doing an unconditional popfq.
 +       */
 +      testl $X86_EFLAGS_NT,EFLAGS(%rsp)       /* saved EFLAGS match cpu */
 +      jnz sysenter_fix_flags
 +sysenter_flags_fixed:
 +
        orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        CFI_REMEMBER_STATE
@@@ -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
        .endm
  
  sysenter_auditsys:
 -      CFI_RESTORE_STATE
        auditsys_entry_common
        movl %ebp,%r9d                  /* reload 6th syscall arg */
        jmp sysenter_dispatch
@@@ -246,11 -235,6 +246,11 @@@ sysexit_audit
        auditsys_exit sysexit_from_sys_call
  #endif
  
 +sysenter_fix_flags:
 +      pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED)
 +      popfq_cfi
 +      jmp sysenter_flags_fixed
 +
  sysenter_tracesys:
  #ifdef CONFIG_AUDITSYSCALL
        testl   $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
index 4b0e1dfa222627cd5a36fb7b8f51234508822536,f9e3fabc871623ce076603c867b6ea52010b5a12..b553ed89e5f5e97346ac460934ce6e016b45455f
@@@ -449,12 -449,11 +449,11 @@@ sysenter_audit
        jnz syscall_trace_entry
        addl $4,%esp
        CFI_ADJUST_CFA_OFFSET -4
-       /* %esi already in 8(%esp)         6th arg: 4th syscall arg */
-       /* %edx already in 4(%esp)         5th arg: 3rd syscall arg */
-       /* %ecx already in 0(%esp)         4th arg: 2nd syscall arg */
-       movl %ebx,%ecx                  /* 3rd arg: 1st syscall arg */
-       movl %eax,%edx                  /* 2nd arg: syscall number */
-       movl $AUDIT_ARCH_I386,%eax      /* 1st arg: audit arch */
+       movl %esi,4(%esp)               /* 5th arg: 4th syscall arg */
+       movl %edx,(%esp)                /* 4th arg: 3rd syscall arg */
+       /* %ecx already in %ecx            3rd arg: 2nd syscall arg */
+       movl %ebx,%edx                  /* 2nd arg: 1st syscall arg */
+       /* %eax already in %eax            1st arg: syscall number */
        call __audit_syscall_entry
        pushl_cfi %ebx
        movl PT_EAX(%esp),%eax          /* reload syscall number */
@@@ -683,7 -682,7 +682,7 @@@ END(syscall_badsys
  sysenter_badsys:
        movl $-ENOSYS,%eax
        jmp sysenter_after_call
 -END(syscall_badsys)
 +END(sysenter_badsys)
        CFI_ENDPROC
  
  .macro FIXUP_ESPFIX_STACK
@@@ -1059,6 -1058,9 +1058,6 @@@ ENTRY(mcount
  END(mcount)
  
  ENTRY(ftrace_caller)
 -      cmpl $0, function_trace_stop
 -      jne  ftrace_stub
 -
        pushl %eax
        pushl %ecx
        pushl %edx
@@@ -1090,6 -1092,8 +1089,6 @@@ END(ftrace_caller
  
  ENTRY(ftrace_regs_caller)
        pushf   /* push flags before compare (in cs location) */
 -      cmpl $0, function_trace_stop
 -      jne ftrace_restore_flags
  
        /*
         * i386 does not save SS and ESP when coming from kernel.
@@@ -1148,6 -1152,7 +1147,6 @@@ GLOBAL(ftrace_regs_call
        popf                    /* Pop flags at end (no addl to corrupt flags) */
        jmp ftrace_ret
  
 -ftrace_restore_flags:
        popf
        jmp  ftrace_stub
  #else /* ! CONFIG_DYNAMIC_FTRACE */
@@@ -1156,6 -1161,9 +1155,6 @@@ ENTRY(mcount
        cmpl $__PAGE_OFFSET, %esp
        jb ftrace_stub          /* Paging not enabled yet? */
  
 -      cmpl $0, function_trace_stop
 -      jne  ftrace_stub
 -
        cmpl $ftrace_stub, ftrace_trace_function
        jnz trace
  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --combined arch/x86/kernel/ptrace.c
index 29576c244699f0632e8d747ab8b8b8461bd4670c,eb1c87f0b03bcf6fa13f0c256404f40361e9df7d..749b0e423419fee7b97698e725dc6d665c1aa828
@@@ -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
         * do_debug() and we need to set it again to restore the user
         * state.  If we entered on the slow path, TF was already set.
         */
 -      if (test_thread_flag(TIF_SINGLESTEP))
 +      if (work & _TIF_SINGLESTEP)
                regs->flags |= X86_EFLAGS_TF;
  
 -      /* do the secure computing check first */
 -      if (secure_computing(regs->orig_ax)) {
 +#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. */
 -              ret = -1L;
 -              goto out;
 +              return -1;
        }
 +#endif
  
 -      if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
 +      if (unlikely(work & _TIF_SYSCALL_EMU))
                ret = -1L;
  
        if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
                trace_sys_enter(regs, regs->orig_ax);
  
 -      if (IS_IA32)
 -              audit_syscall_entry(regs->orig_ax, regs->bx, regs->cx,
 -                                  regs->dx, regs->si);
 -#ifdef CONFIG_X86_64
 -      else
 -              audit_syscall_entry(regs->orig_ax, regs->di, regs->si,
 -                                  regs->dx, regs->r10);
 -#endif
 +      do_audit_syscall_entry(regs, arch);
  
 -out:
        return ret ?: regs->orig_ax;
  }
  
 +long syscall_trace_enter(struct pt_regs *regs)
 +{
 +      u32 arch = is_ia32_task() ? 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);
 +}
 +
  void syscall_trace_leave(struct pt_regs *regs)
  {
        bool step;
index 3b9ff33e1768029c77a33ebe29d73362244156ac,4d100c841c80f2cdb7a436527380269b1f05c77e..d4dbef14d4dffa7d4eae071c59674e5a99b66091
@@@ -342,7 -342,6 +342,7 @@@ enum 
  #define __AUDIT_ARCH_64BIT 0x80000000
  #define __AUDIT_ARCH_LE          0x40000000
  
 +#define AUDIT_ARCH_AARCH64    (EM_AARCH64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
  #define AUDIT_ARCH_ALPHA      (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
  #define AUDIT_ARCH_ARM                (EM_ARM|__AUDIT_ARCH_LE)
  #define AUDIT_ARCH_ARMEB      (EM_ARM)
  #define AUDIT_ARCH_IA64               (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
  #define AUDIT_ARCH_M32R               (EM_M32R)
  #define AUDIT_ARCH_M68K               (EM_68K)
+ #define AUDIT_ARCH_MICROBLAZE (EM_MICROBLAZE)
  #define AUDIT_ARCH_MIPS               (EM_MIPS)
  #define AUDIT_ARCH_MIPSEL     (EM_MIPS|__AUDIT_ARCH_LE)
  #define AUDIT_ARCH_MIPS64     (EM_MIPS|__AUDIT_ARCH_64BIT)
@@@ -445,17 -445,4 +446,4 @@@ struct audit_rule_data 
        char            buf[0]; /* string fields buffer */
  };
  
- /* audit_rule is supported to maintain backward compatibility with
-  * userspace.  It supports integer fields only and corresponds to
-  * AUDIT_ADD, AUDIT_DEL and AUDIT_LIST requests.
-  */
- struct audit_rule {           /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
-       __u32           flags;  /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
-       __u32           action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
-       __u32           field_count;
-       __u32           mask[AUDIT_BITMASK_SIZE];
-       __u32           fields[AUDIT_MAX_FIELDS];
-       __u32           values[AUDIT_MAX_FIELDS];
- };
  #endif /* _UAPI_LINUX_AUDIT_H_ */
diff --combined kernel/audit.c
index ba2ff5a5c600daa49670502c2e2f8e9c72fe69e6,53bb39bf79e2aca9f2b83023a6102ebf072ac2c6..80983df92cd441f981090394252126fbde22cd64
@@@ -126,7 -126,7 +126,7 @@@ static atomic_t    audit_lost = ATOMIC_
  
  /* The netlink socket. */
  static struct sock *audit_sock;
- int audit_net_id;
static int audit_net_id;
  
  /* Hash for inode-based rules */
  struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
@@@ -724,7 -724,7 +724,7 @@@ static int audit_get_feature(struct sk_
  
        seq = nlmsg_hdr(skb)->nlmsg_seq;
  
-       audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &af, sizeof(af));
+       audit_send_reply(skb, seq, AUDIT_GET_FEATURE, 0, 0, &af, sizeof(af));
  
        return 0;
  }
@@@ -750,7 -750,7 +750,7 @@@ static int audit_set_feature(struct sk_
        struct audit_features *uaf;
        int i;
  
-       BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > sizeof(audit_feature_names)/sizeof(audit_feature_names[0]));
+       BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > ARRAY_SIZE(audit_feature_names));
        uaf = nlmsg_data(nlmsg_hdr(skb));
  
        /* if there is ever a version 2 we should handle that here */
@@@ -1301,19 -1301,9 +1301,9 @@@ err
   */
  unsigned int audit_serial(void)
  {
-       static DEFINE_SPINLOCK(serial_lock);
-       static unsigned int serial = 0;
+       static atomic_t serial = ATOMIC_INIT(0);
  
-       unsigned long flags;
-       unsigned int ret;
-       spin_lock_irqsave(&serial_lock, flags);
-       do {
-               ret = ++serial;
-       } while (unlikely(!ret));
-       spin_unlock_irqrestore(&serial_lock, flags);
-       return ret;
+       return atomic_add_return(1, &serial);
  }
  
  static inline void audit_get_stamp(struct audit_context *ctx,
@@@ -1677,11 -1667,11 +1667,11 @@@ void audit_log_cap(struct audit_buffer 
        audit_log_format(ab, " %s=", prefix);
        CAP_FOR_EACH_U32(i) {
                audit_log_format(ab, "%08x",
 -                               cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
 +                               cap->cap[CAP_LAST_U32 - i]);
        }
  }
  
- void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
  {
        kernel_cap_t *perm = &name->fcap.permitted;
        kernel_cap_t *inh = &name->fcap.inheritable;
@@@ -1860,7 -1850,7 +1850,7 @@@ EXPORT_SYMBOL(audit_log_task_context)
  void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
  {
        const struct cred *cred;
-       char name[sizeof(tsk->comm)];
+       char comm[sizeof(tsk->comm)];
        struct mm_struct *mm = tsk->mm;
        char *tty;
  
                         from_kgid(&init_user_ns, cred->fsgid),
                         tty, audit_get_sessionid(tsk));
  
-       get_task_comm(name, tsk);
        audit_log_format(ab, " comm=");
-       audit_log_untrustedstring(ab, name);
+       audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
  
        if (mm) {
                down_read(&mm->mmap_sem);
@@@ -1959,6 -1948,7 +1948,7 @@@ void audit_log_end(struct audit_buffer 
        } else {
                struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
  
+               nlh->nlmsg_len = ab->skb->len;
                kauditd_send_multicast_skb(ab->skb);
  
                /*
                 * protocol between the kaudit kernel subsystem and the auditd
                 * userspace code.
                 */
-               nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
+               nlh->nlmsg_len -= NLMSG_HDRLEN;
  
                if (audit_pid) {
                        skb_queue_tail(&audit_skb_queue, ab->skb);
diff --combined kernel/auditfilter.c
index c447cd9848d1bbce5f8e013c225b7fe9a26645fd,d214cd073a58001a6af0a99275b435552116928e..3598e13f2a655dbbcfb0df6b6c1bd1afcebd2b8f
@@@ -71,6 -71,24 +71,24 @@@ static struct list_head audit_rules_lis
  
  DEFINE_MUTEX(audit_filter_mutex);
  
+ static void audit_free_lsm_field(struct audit_field *f)
+ {
+       switch (f->type) {
+       case AUDIT_SUBJ_USER:
+       case AUDIT_SUBJ_ROLE:
+       case AUDIT_SUBJ_TYPE:
+       case AUDIT_SUBJ_SEN:
+       case AUDIT_SUBJ_CLR:
+       case AUDIT_OBJ_USER:
+       case AUDIT_OBJ_ROLE:
+       case AUDIT_OBJ_TYPE:
+       case AUDIT_OBJ_LEV_LOW:
+       case AUDIT_OBJ_LEV_HIGH:
+               kfree(f->lsm_str);
+               security_audit_rule_free(f->lsm_rule);
+       }
+ }
  static inline void audit_free_rule(struct audit_entry *e)
  {
        int i;
        if (erule->watch)
                audit_put_watch(erule->watch);
        if (erule->fields)
-               for (i = 0; i < erule->field_count; i++) {
-                       struct audit_field *f = &erule->fields[i];
-                       kfree(f->lsm_str);
-                       security_audit_rule_free(f->lsm_rule);
-               }
+               for (i = 0; i < erule->field_count; i++)
+                       audit_free_lsm_field(&erule->fields[i]);
        kfree(erule->fields);
        kfree(erule->filterkey);
        kfree(e);
@@@ -106,7 -121,7 +121,7 @@@ static inline struct audit_entry *audit
        if (unlikely(!entry))
                return NULL;
  
 -      fields = kzalloc(sizeof(*fields) * field_count, GFP_KERNEL);
 +      fields = kcalloc(field_count, sizeof(*fields), GFP_KERNEL);
        if (unlikely(!fields)) {
                kfree(entry);
                return NULL;
@@@ -148,7 -163,7 +163,7 @@@ static inline int audit_to_inode(struc
                                 struct audit_field *f)
  {
        if (krule->listnr != AUDIT_FILTER_EXIT ||
-           krule->watch || krule->inode_f || krule->tree ||
+           krule->inode_f || krule->watch || krule->tree ||
            (f->op != Audit_equal && f->op != Audit_not_equal))
                return -EINVAL;
  
@@@ -160,7 -175,7 +175,7 @@@ static __u32 *classes[AUDIT_SYSCALL_CLA
  
  int __init audit_register_class(int class, unsigned *list)
  {
 -      __u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL);
 +      __u32 *p = kcalloc(AUDIT_BITMASK_SIZE, sizeof(__u32), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
        while (*list != ~0U) {
@@@ -422,10 -437,6 +437,6 @@@ static struct audit_entry *audit_data_t
  
                f->type = data->fields[i];
                f->val = data->values[i];
-               f->uid = INVALID_UID;
-               f->gid = INVALID_GID;
-               f->lsm_str = NULL;
-               f->lsm_rule = NULL;
  
                /* Support legacy tests for a valid loginuid */
                if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
@@@ -1053,30 -1064,27 +1064,27 @@@ int audit_rule_change(int type, __u32 p
        int err = 0;
        struct audit_entry *entry;
  
+       entry = audit_data_to_entry(data, datasz);
+       if (IS_ERR(entry))
+               return PTR_ERR(entry);
        switch (type) {
        case AUDIT_ADD_RULE:
-               entry = audit_data_to_entry(data, datasz);
-               if (IS_ERR(entry))
-                       return PTR_ERR(entry);
                err = audit_add_rule(entry);
-               audit_log_rule_change("add rule", &entry->rule, !err);
-               if (err)
-                       audit_free_rule(entry);
+               audit_log_rule_change("add_rule", &entry->rule, !err);
                break;
        case AUDIT_DEL_RULE:
-               entry = audit_data_to_entry(data, datasz);
-               if (IS_ERR(entry))
-                       return PTR_ERR(entry);
                err = audit_del_rule(entry);
-               audit_log_rule_change("remove rule", &entry->rule, !err);
-               audit_free_rule(entry);
+               audit_log_rule_change("remove_rule", &entry->rule, !err);
                break;
        default:
-               return -EINVAL;
+               err = -EINVAL;
+               WARN_ON(1);
        }
  
+       if (err || type == AUDIT_DEL_RULE)
+               audit_free_rule(entry);
        return err;
  }
  
diff --combined kernel/auditsc.c
index 7208c1df248d645227c90bbbece7c249d6db6de6,89335723fb2a5f580a91627a8c868dbc31e6886e..e420a0c41b5f605b0f4ead982eac279e066ffee2
@@@ -67,6 -67,7 +67,7 @@@
  #include <linux/binfmts.h>
  #include <linux/highmem.h>
  #include <linux/syscalls.h>
+ #include <asm/syscall.h>
  #include <linux/capability.h>
  #include <linux/fs_struct.h>
  #include <linux/compat.h>
@@@ -125,14 -126,6 +126,6 @@@ struct audit_tree_refs 
        struct audit_chunk *c[31];
  };
  
- static inline int open_arg(int flags, int mask)
- {
-       int n = ACC_MODE(flags);
-       if (flags & (O_TRUNC | O_CREAT))
-               n |= AUDIT_PERM_WRITE;
-       return n & mask;
- }
  static int audit_match_perm(struct audit_context *ctx, int mask)
  {
        unsigned n;
@@@ -1505,7 -1498,6 +1498,6 @@@ void __audit_free(struct task_struct *t
  
  /**
   * audit_syscall_entry - fill in an audit record at syscall entry
-  * @arch: architecture type
   * @major: major syscall type (function)
   * @a1: additional syscall register 1
   * @a2: additional syscall register 2
   * will only be written if another part of the kernel requests that it
   * be written).
   */
- void __audit_syscall_entry(int arch, int major,
-                        unsigned long a1, unsigned long a2,
-                        unsigned long a3, unsigned long a4)
+ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
+                          unsigned long a3, unsigned long a4)
  {
        struct task_struct *tsk = current;
        struct audit_context *context = tsk->audit_context;
        if (!audit_enabled)
                return;
  
-       context->arch       = arch;
+       context->arch       = syscall_get_arch();
        context->major      = major;
        context->argv[0]    = a1;
        context->argv[1]    = a2;
@@@ -2406,7 -2397,7 +2397,7 @@@ int __audit_log_bprm_fcaps(struct linux
   * @new: the new credentials
   * @old: the old (current) credentials
   *
 - * Record the aguments userspace sent to sys_capset for later printing by the
 + * Record the arguments userspace sent to sys_capset for later printing by the
   * audit system if applicable
   */
  void __audit_log_capset(const struct cred *new, const struct cred *old)
@@@ -2433,6 -2424,7 +2424,7 @@@ static void audit_log_task(struct audit
        kgid_t gid;
        unsigned int sessionid;
        struct mm_struct *mm = current->mm;
+       char comm[sizeof(current->comm)];
  
        auid = audit_get_loginuid(current);
        sessionid = audit_get_sessionid(current);
                         sessionid);
        audit_log_task_context(ab);
        audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
-       audit_log_untrustedstring(ab, current->comm);
+       audit_log_untrustedstring(ab, get_task_comm(comm, current));
        if (mm) {
                down_read(&mm->mmap_sem);
                if (mm->exe_file)
@@@ -2488,11 -2480,9 +2480,9 @@@ void __audit_seccomp(unsigned long sysc
        if (unlikely(!ab))
                return;
        audit_log_task(ab);
-       audit_log_format(ab, " sig=%ld", signr);
-       audit_log_format(ab, " syscall=%ld", syscall);
-       audit_log_format(ab, " compat=%d", is_compat_task());
-       audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
-       audit_log_format(ab, " code=0x%x", code);
+       audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
+                        signr, syscall_get_arch(), syscall, is_compat_task(),
+                        KSTK_EIP(current), code);
        audit_log_end(ab);
  }