Merge git://git.infradead.org/users/eparis/audit
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 May 2013 21:29:11 +0000 (14:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 May 2013 21:29:11 +0000 (14:29 -0700)
Pull audit changes from Eric Paris:
 "Al used to send pull requests every couple of years but he told me to
  just start pushing them to you directly.

  Our touching outside of core audit code is pretty straight forward.  A
  couple of interface changes which hit net/.  A simple argument bug
  calling audit functions in namei.c and the removal of some assembly
  branch prediction code on ppc"

* git://git.infradead.org/users/eparis/audit: (31 commits)
  audit: fix message spacing printing auid
  Revert "audit: move kaudit thread start from auditd registration to kaudit init"
  audit: vfs: fix audit_inode call in O_CREAT case of do_last
  audit: Make testing for a valid loginuid explicit.
  audit: fix event coverage of AUDIT_ANOM_LINK
  audit: use spin_lock in audit_receive_msg to process tty logging
  audit: do not needlessly take a lock in tty_audit_exit
  audit: do not needlessly take a spinlock in copy_signal
  audit: add an option to control logging of passwords with pam_tty_audit
  audit: use spin_lock_irqsave/restore in audit tty code
  helper for some session id stuff
  audit: use a consistent audit helper to log lsm information
  audit: push loginuid and sessionid processing down
  audit: stop pushing loginid, uid, sessionid as arguments
  audit: remove the old depricated kernel interface
  audit: make validity checking generic
  audit: allow checking the type of audit message in the user filter
  audit: fix build break when AUDIT_DEBUG == 2
  audit: remove duplicate export of audit_enabled
  Audit: do not print error when LSMs disabled
  ...

1  2 
arch/powerpc/kernel/entry_64.S
fs/namei.c
include/linux/sched.h
include/linux/tty.h
kernel/audit.c
kernel/audit.h
kernel/auditfilter.c
net/socket.c

index 3fe5259e2fea872be5da2e333427a935f8a012d0,c20d9bf4aa26504276f7ded80a31e4b11156e4c7..915fbb4fc2fe4e7534dbf78eb39317013b03b014
@@@ -62,9 -62,8 +62,9 @@@ system_call_common
        std     r12,_MSR(r1)
        std     r0,GPR0(r1)
        std     r10,GPR1(r1)
 +      beq     2f                      /* if from kernel mode */
        ACCOUNT_CPU_USER_ENTRY(r10, r11)
 -      std     r2,GPR2(r1)
 +2:    std     r2,GPR2(r1)
        std     r3,GPR3(r1)
        mfcr    r2
        std     r4,GPR4(r1)
@@@ -95,7 -94,7 +95,7 @@@
        addi    r9,r1,STACK_FRAME_OVERHEAD
        ld      r11,exception_marker@toc(r2)
        std     r11,-16(r9)             /* "regshere" marker */
 -#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)
 +#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC_SPLPAR)
  BEGIN_FW_FTR_SECTION
        beq     33f
        /* if from user, see if there are any DTL entries to process */
        addi    r9,r1,STACK_FRAME_OVERHEAD
  33:
  END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 -#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */
 +#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE && CONFIG_PPC_SPLPAR */
  
        /*
         * A syscall should always be called with interrupts enabled
        CURRENT_THREAD_INFO(r11, r1)
        ld      r10,TI_FLAGS(r11)
        andi.   r11,r10,_TIF_SYSCALL_T_OR_A
-       bne-    syscall_dotrace
+       bne     syscall_dotrace
  .Lsyscall_dotrace_cont:
        cmpldi  0,r0,NR_syscalls
        bge-    syscall_enosys
@@@ -227,7 -226,6 +227,7 @@@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHEC
  
        beq-    1f
        ACCOUNT_CPU_USER_EXIT(r11, r12)
 +      HMT_MEDIUM_LOW_HAS_PPR
        ld      r13,GPR13(r1)   /* only restore r13 if returning to usermode */
  1:    ld      r2,GPR2(r1)
        ld      r1,GPR1(r1)
@@@ -304,7 -302,6 +304,7 @@@ syscall_exit_work
        subi    r12,r12,TI_FLAGS
  
  4:    /* Anything else left to do? */
 +      SET_DEFAULT_THREAD_PPR(r3, r10)         /* Set thread.ppr = 3 */
        andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
        beq     .ret_from_except_lite
  
@@@ -448,27 -445,6 +448,27 @@@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR
        std     r23,_CCR(r1)
        std     r1,KSP(r3)      /* Set old stack pointer */
  
 +#ifdef CONFIG_PPC_BOOK3S_64
 +BEGIN_FTR_SECTION
 +      /*
 +       * Back up the TAR across context switches.  Note that the TAR is not
 +       * available for use in the kernel.  (To provide this, the TAR should
 +       * be backed up/restored on exception entry/exit instead, and be in
 +       * pt_regs.  FIXME, this should be in pt_regs anyway (for debug).)
 +       */
 +      mfspr   r0,SPRN_TAR
 +      std     r0,THREAD_TAR(r3)
 +
 +      /* Event based branch registers */
 +      mfspr   r0, SPRN_BESCR
 +      std     r0, THREAD_BESCR(r3)
 +      mfspr   r0, SPRN_EBBHR
 +      std     r0, THREAD_EBBHR(r3)
 +      mfspr   r0, SPRN_EBBRR
 +      std     r0, THREAD_EBBRR(r3)
 +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 +#endif
 +
  #ifdef CONFIG_SMP
        /* We need a sync somewhere here to make sure that if the
         * previous task gets rescheduled on another CPU, it sees all
@@@ -551,21 -527,6 +551,21 @@@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SE
        mr      r1,r8           /* start using new stack pointer */
        std     r7,PACAKSAVE(r13)
  
 +#ifdef CONFIG_PPC_BOOK3S_64
 +BEGIN_FTR_SECTION
 +      /* Event based branch registers */
 +      ld      r0, THREAD_BESCR(r4)
 +      mtspr   SPRN_BESCR, r0
 +      ld      r0, THREAD_EBBHR(r4)
 +      mtspr   SPRN_EBBHR, r0
 +      ld      r0, THREAD_EBBRR(r4)
 +      mtspr   SPRN_EBBRR, r0
 +
 +      ld      r0,THREAD_TAR(r4)
 +      mtspr   SPRN_TAR,r0
 +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 +#endif
 +
  #ifdef CONFIG_ALTIVEC
  BEGIN_FTR_SECTION
        ld      r0,THREAD_VRSAVE(r4)
@@@ -673,7 -634,7 +673,7 @@@ resume_kernel
        /* Clear _TIF_EMULATE_STACK_STORE flag */
        lis     r11,_TIF_EMULATE_STACK_STORE@h
        addi    r5,r9,TI_FLAGS
 -      ldarx   r4,0,r5
 +0:    ldarx   r4,0,r5
        andc    r4,r4,r11
        stdcx.  r4,0,r5
        bne-    0b
@@@ -801,10 -762,6 +801,10 @@@ fast_exception_return
        andc    r4,r4,r0         /* r0 contains MSR_RI here */
        mtmsrd  r4,1
  
 +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 +      /* TM debug */
 +      std     r3, PACATMSCRATCH(r13) /* Stash returned-to MSR */
 +#endif
        /*
         * r13 is our per cpu area, only restore it if we are returning to
         * userspace the value stored in the stack frame may belong to
        andi.   r0,r3,MSR_PR
        beq     1f
        ACCOUNT_CPU_USER_EXIT(r2, r4)
 +      RESTORE_PPR(r2, r4)
        REST_GPR(13, r1)
  1:
        mtspr   SPRN_SRR1,r3
@@@ -893,22 -849,13 +893,22 @@@ restore_check_irq_replay
        addi    r3,r1,STACK_FRAME_OVERHEAD;
        bl      .timer_interrupt
        b       .ret_from_except
 +#ifdef CONFIG_PPC_DOORBELL
 +1:
  #ifdef CONFIG_PPC_BOOK3E
 -1:    cmpwi   cr0,r3,0x280
 +      cmpwi   cr0,r3,0x280
 +#else
 +      BEGIN_FTR_SECTION
 +              cmpwi   cr0,r3,0xe80
 +      FTR_SECTION_ELSE
 +              cmpwi   cr0,r3,0xa00
 +      ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
 +#endif /* CONFIG_PPC_BOOK3E */
        bne     1f
        addi    r3,r1,STACK_FRAME_OVERHEAD;
        bl      .doorbell_exception
        b       .ret_from_except
 -#endif /* CONFIG_PPC_BOOK3E */
 +#endif /* CONFIG_PPC_DOORBELL */
  1:    b       .ret_from_except /* What else to do here ? */
   
  unrecov_restore:
diff --combined fs/namei.c
index 57ae9c8c66bfc6d98ae96643874710cdc3de321a,498ede374dc002a18546b77e4c67e48f06961942..85e40d1c0a8fd64b358447ee09b26f906102ee1d
@@@ -451,7 -451,7 +451,7 @@@ int inode_permission(struct inode *inod
   *
   * Given a path increment the reference count to the dentry and the vfsmount.
   */
 -void path_get(struct path *path)
 +void path_get(const struct path *path)
  {
        mntget(path->mnt);
        dget(path->dentry);
@@@ -464,7 -464,7 +464,7 @@@ EXPORT_SYMBOL(path_get)
   *
   * Given a path decrement the reference count to the dentry and the vfsmount.
   */
 -void path_put(struct path *path)
 +void path_put(const struct path *path)
  {
        dput(path->dentry);
        mntput(path->mnt);
@@@ -600,10 -600,14 +600,10 @@@ static int complete_walk(struct nameida
        if (likely(!(nd->flags & LOOKUP_JUMPED)))
                return 0;
  
 -      if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
 +      if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
                return 0;
  
 -      if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)))
 -              return 0;
 -
 -      /* Note: we do not d_invalidate() */
 -      status = d_revalidate(dentry, nd->flags);
 +      status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
        if (status > 0)
                return 0;
  
@@@ -689,6 -693,8 +689,6 @@@ void nd_jump_link(struct nameidata *nd
        nd->path = *path;
        nd->inode = nd->path.dentry->d_inode;
        nd->flags |= LOOKUP_JUMPED;
 -
 -      BUG_ON(nd->inode->i_op->follow_link);
  }
  
  static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
@@@ -1336,7 -1342,7 +1336,7 @@@ static struct dentry *__lookup_hash(str
   *  small and for now I'd prefer to have fast path as straight as possible.
   *  It _is_ time-critical.
   */
 -static int lookup_fast(struct nameidata *nd, struct qstr *name,
 +static int lookup_fast(struct nameidata *nd,
                       struct path *path, struct inode **inode)
  {
        struct vfsmount *mnt = nd->path.mnt;
         */
        if (nd->flags & LOOKUP_RCU) {
                unsigned seq;
 -              dentry = __d_lookup_rcu(parent, name, &seq, nd->inode);
 +              dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode);
                if (!dentry)
                        goto unlazy;
  
@@@ -1394,7 -1400,7 +1394,7 @@@ unlazy
                if (unlazy_walk(nd, dentry))
                        return -ECHILD;
        } else {
 -              dentry = __d_lookup(parent, name);
 +              dentry = __d_lookup(parent, &nd->last);
        }
  
        if (unlikely(!dentry))
@@@ -1430,7 -1436,8 +1430,7 @@@ need_lookup
  }
  
  /* Fast lookup failed, do it the slow way */
 -static int lookup_slow(struct nameidata *nd, struct qstr *name,
 -                     struct path *path)
 +static int lookup_slow(struct nameidata *nd, struct path *path)
  {
        struct dentry *dentry, *parent;
        int err;
        BUG_ON(nd->inode != parent->d_inode);
  
        mutex_lock(&parent->d_inode->i_mutex);
 -      dentry = __lookup_hash(name, parent, nd->flags);
 +      dentry = __lookup_hash(&nd->last, parent, nd->flags);
        mutex_unlock(&parent->d_inode->i_mutex);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
@@@ -1512,7 -1519,7 +1512,7 @@@ static inline int should_follow_link(st
  }
  
  static inline int walk_component(struct nameidata *nd, struct path *path,
 -              struct qstr *name, int type, int follow)
 +              int follow)
  {
        struct inode *inode;
        int err;
         * to be able to know about the current root directory and
         * parent relationships.
         */
 -      if (unlikely(type != LAST_NORM))
 -              return handle_dots(nd, type);
 -      err = lookup_fast(nd, name, path, &inode);
 +      if (unlikely(nd->last_type != LAST_NORM))
 +              return handle_dots(nd, nd->last_type);
 +      err = lookup_fast(nd, path, &inode);
        if (unlikely(err)) {
                if (err < 0)
                        goto out_err;
  
 -              err = lookup_slow(nd, name, path);
 +              err = lookup_slow(nd, path);
                if (err < 0)
                        goto out_err;
  
@@@ -1587,7 -1594,8 +1587,7 @@@ static inline int nested_symlink(struc
                res = follow_link(&link, nd, &cookie);
                if (res)
                        break;
 -              res = walk_component(nd, path, &nd->last,
 -                                   nd->last_type, LOOKUP_FOLLOW);
 +              res = walk_component(nd, path, LOOKUP_FOLLOW);
                put_link(nd, &link, cookie);
        } while (res > 0);
  
@@@ -1794,11 -1802,8 +1794,11 @@@ static int link_path_walk(const char *n
                        }
                }
  
 +              nd->last = this;
 +              nd->last_type = type;
 +
                if (!name[len])
 -                      goto last_component;
 +                      return 0;
                /*
                 * If it wasn't NUL, we know it was '/'. Skip that
                 * slash, and continue until no more slashes.
                        len++;
                } while (unlikely(name[len] == '/'));
                if (!name[len])
 -                      goto last_component;
 +                      return 0;
 +
                name += len;
  
 -              err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);
 +              err = walk_component(nd, &next, LOOKUP_FOLLOW);
                if (err < 0)
                        return err;
  
                        if (err)
                                return err;
                }
 -              if (can_lookup(nd->inode))
 -                      continue;
 -              err = -ENOTDIR; 
 -              break;
 -              /* here ends the main loop */
 -
 -last_component:
 -              nd->last = this;
 -              nd->last_type = type;
 -              return 0;
 +              if (!can_lookup(nd->inode)) {
 +                      err = -ENOTDIR; 
 +                      break;
 +              }
        }
        terminate_walk(nd);
        return err;
@@@ -1922,7 -1932,8 +1922,7 @@@ static inline int lookup_last(struct na
                nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
  
        nd->flags &= ~LOOKUP_PARENT;
 -      return walk_component(nd, path, &nd->last, nd->last_type,
 -                                      nd->flags & LOOKUP_FOLLOW);
 +      return walk_component(nd, path, nd->flags & LOOKUP_FOLLOW);
  }
  
  /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
@@@ -2721,7 -2732,7 +2721,7 @@@ static int do_last(struct nameidata *nd
                if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
                        symlink_ok = true;
                /* we _can_ be in RCU mode here */
 -              error = lookup_fast(nd, &nd->last, path, &inode);
 +              error = lookup_fast(nd, path, &inode);
                if (likely(!error))
                        goto finish_lookup;
  
                if (error)
                        return error;
  
-               audit_inode(name, dir, 0);
+               audit_inode(name, dir, LOOKUP_PARENT);
                error = -EISDIR;
                /* trailing slashes? */
                if (nd->last.name[nd->last.len])
@@@ -2767,7 -2778,7 +2767,7 @@@ retry_lookup
                        goto out;
  
                if ((*opened & FILE_CREATED) ||
 -                  !S_ISREG(file->f_path.dentry->d_inode->i_mode))
 +                  !S_ISREG(file_inode(file)->i_mode))
                        will_truncate = false;
  
                audit_inode(name, file->f_path.dentry, 0);
@@@ -2930,8 -2941,8 +2930,8 @@@ static struct file *path_openat(int dfd
        int error;
  
        file = get_empty_filp();
 -      if (!file)
 -              return ERR_PTR(-ENFILE);
 +      if (IS_ERR(file))
 +              return file;
  
        file->f_flags = op->open_flag;
  
diff --combined include/linux/sched.h
index caa8f4d0186b742c3effc99c296ac99724f2f4d1,c4689fe92864fc9fa5fbe55004bdb939eee41263..178a8d909f14a3dcdcbc0ce255572975c8b3b221
@@@ -51,7 -51,6 +51,7 @@@ struct sched_param 
  #include <linux/cred.h>
  #include <linux/llist.h>
  #include <linux/uidgid.h>
 +#include <linux/gfp.h>
  
  #include <asm/processor.h>
  
@@@ -99,6 -98,7 +99,6 @@@ extern int nr_threads
  DECLARE_PER_CPU(unsigned long, process_counts);
  extern int nr_processes(void);
  extern unsigned long nr_running(void);
 -extern unsigned long nr_uninterruptible(void);
  extern unsigned long nr_iowait(void);
  extern unsigned long nr_iowait_cpu(int cpu);
  extern unsigned long this_cpu_load(void);
@@@ -127,6 -127,18 +127,6 @@@ extern void proc_sched_show_task(struc
  extern void proc_sched_set_task(struct task_struct *p);
  extern void
  print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq);
 -#else
 -static inline void
 -proc_sched_show_task(struct task_struct *p, struct seq_file *m)
 -{
 -}
 -static inline void proc_sched_set_task(struct task_struct *p)
 -{
 -}
 -static inline void
 -print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
 -{
 -}
  #endif
  
  /*
  #define TASK_DEAD             64
  #define TASK_WAKEKILL         128
  #define TASK_WAKING           256
 -#define TASK_STATE_MAX                512
 +#define TASK_PARKED           512
 +#define TASK_STATE_MAX                1024
  
 -#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW"
 +#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
  
  extern char ___assert_task_state[1 - 2*!!(
                sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)];
@@@ -231,7 -242,7 +231,7 @@@ extern void init_idle_bootup_task(struc
  
  extern int runqueue_is_locked(int cpu);
  
 -#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
 +#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
  extern void nohz_balance_enter_idle(int cpu);
  extern void set_cpu_sd_state_idle(void);
  extern int get_nohz_timer_target(void);
@@@ -293,6 -304,19 +293,6 @@@ static inline void lockup_detector_init
  }
  #endif
  
 -#ifdef CONFIG_DETECT_HUNG_TASK
 -extern unsigned int  sysctl_hung_task_panic;
 -extern unsigned long sysctl_hung_task_check_count;
 -extern unsigned long sysctl_hung_task_timeout_secs;
 -extern unsigned long sysctl_hung_task_warnings;
 -extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
 -                                       void __user *buffer,
 -                                       size_t *lenp, loff_t *ppos);
 -#else
 -/* Avoid need for ifdefs elsewhere in the code */
 -enum { sysctl_hung_task_timeout_secs = 0 };
 -#endif
 -
  /* Attach to any functions which should be ignored in wchan output. */
  #define __sched               __attribute__((__section__(".sched.text")))
  
@@@ -309,10 -333,30 +309,10 @@@ extern signed long schedule_timeout_kil
  extern signed long schedule_timeout_uninterruptible(signed long timeout);
  asmlinkage void schedule(void);
  extern void schedule_preempt_disabled(void);
 -extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
  
  struct nsproxy;
  struct user_namespace;
  
 -/*
 - * Default maximum number of active map areas, this limits the number of vmas
 - * per mm struct. Users can overwrite this number by sysctl but there is a
 - * problem.
 - *
 - * When a program's coredump is generated as ELF format, a section is created
 - * per a vma. In ELF, the number of sections is represented in unsigned short.
 - * This means the number of sections should be smaller than 65535 at coredump.
 - * Because the kernel adds some informative sections to a image of program at
 - * generating coredump, we need some margin. The number of extra sections is
 - * 1-3 now and depends on arch. We use "5" as safe margin, here.
 - */
 -#define MAPCOUNT_ELF_CORE_MARGIN      (5)
 -#define DEFAULT_MAX_MAP_COUNT (USHRT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
 -
 -extern int sysctl_max_map_count;
 -
 -#include <linux/aio.h>
 -
  #ifdef CONFIG_MMU
  extern void arch_pick_mmap_layout(struct mm_struct *mm);
  extern unsigned long
@@@ -332,6 -376,11 +332,6 @@@ static inline void arch_pick_mmap_layou
  extern void set_dumpable(struct mm_struct *mm, int value);
  extern int get_dumpable(struct mm_struct *mm);
  
 -/* get/set_dumpable() values */
 -#define SUID_DUMPABLE_DISABLED        0
 -#define SUID_DUMPABLE_ENABLED 1
 -#define SUID_DUMPABLE_SAFE    2
 -
  /* mm flags */
  /* dumpable bits */
  #define MMF_DUMPABLE      0  /* core dump is permitted */
@@@ -512,8 -561,7 +512,8 @@@ struct signal_struct 
        unsigned int            has_child_subreaper:1;
  
        /* POSIX.1b Interval Timers */
 -      struct list_head posix_timers;
 +      int                     posix_timer_id;
 +      struct list_head        posix_timers;
  
        /* ITIMER_REAL timer for the process */
        struct hrtimer real_timer;
        cputime_t utime, stime, cutime, cstime;
        cputime_t gtime;
        cputime_t cgtime;
 -#ifndef CONFIG_VIRT_CPU_ACCOUNTING
 +#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        struct cputime prev_cputime;
  #endif
        unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
  #endif
  #ifdef CONFIG_AUDIT
        unsigned audit_tty;
+       unsigned audit_tty_log_passwd;
        struct tty_audit_buf *tty_audit_buf;
  #endif
  #ifdef CONFIG_CGROUPS
  #define SIGNAL_STOP_STOPPED   0x00000001 /* job control stop in effect */
  #define SIGNAL_STOP_CONTINUED 0x00000002 /* SIGCONT since WCONTINUED reap */
  #define SIGNAL_GROUP_EXIT     0x00000004 /* group exit in progress */
 +#define SIGNAL_GROUP_COREDUMP 0x00000008 /* coredump in progress */
  /*
   * Pending notifications to parent.
   */
@@@ -755,6 -803,31 +756,6 @@@ enum cpu_idle_type 
        CPU_MAX_IDLE_TYPES
  };
  
 -/*
 - * Increase resolution of nice-level calculations for 64-bit architectures.
 - * The extra resolution improves shares distribution and load balancing of
 - * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
 - * hierarchies, especially on larger systems. This is not a user-visible change
 - * and does not change the user-interface for setting shares/weights.
 - *
 - * We increase resolution only if we have enough bits to allow this increased
 - * resolution (i.e. BITS_PER_LONG > 32). The costs for increasing resolution
 - * when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the
 - * increased costs.
 - */
 -#if 0 /* BITS_PER_LONG > 32 -- currently broken: it increases power usage under light load  */
 -# define SCHED_LOAD_RESOLUTION        10
 -# define scale_load(w)                ((w) << SCHED_LOAD_RESOLUTION)
 -# define scale_load_down(w)   ((w) >> SCHED_LOAD_RESOLUTION)
 -#else
 -# define SCHED_LOAD_RESOLUTION        0
 -# define scale_load(w)                (w)
 -# define scale_load_down(w)   (w)
 -#endif
 -
 -#define SCHED_LOAD_SHIFT      (10 + SCHED_LOAD_RESOLUTION)
 -#define SCHED_LOAD_SCALE      (1L << SCHED_LOAD_SHIFT)
 -
  /*
   * Increase resolution of cpu_power calculations
   */
  
  extern int __weak arch_sd_sibiling_asym_packing(void);
  
 -struct sched_group_power {
 -      atomic_t ref;
 -      /*
 -       * CPU power of this group, SCHED_LOAD_SCALE being max power for a
 -       * single CPU.
 -       */
 -      unsigned int power, power_orig;
 -      unsigned long next_update;
 -      /*
 -       * Number of busy cpus in this group.
 -       */
 -      atomic_t nr_busy_cpus;
 -
 -      unsigned long cpumask[0]; /* iteration mask */
 -};
 -
 -struct sched_group {
 -      struct sched_group *next;       /* Must be a circular list */
 -      atomic_t ref;
 -
 -      unsigned int group_weight;
 -      struct sched_group_power *sgp;
 -
 -      /*
 -       * The CPUs this group covers.
 -       *
 -       * NOTE: this field is variable length. (Allocated dynamically
 -       * by attaching extra space to the end of the structure,
 -       * depending on how many CPUs the kernel has booted up with)
 -       */
 -      unsigned long cpumask[0];
 -};
 -
 -static inline struct cpumask *sched_group_cpus(struct sched_group *sg)
 -{
 -      return to_cpumask(sg->cpumask);
 -}
 -
 -/*
 - * cpumask masking which cpus in the group are allowed to iterate up the domain
 - * tree.
 - */
 -static inline struct cpumask *sched_group_mask(struct sched_group *sg)
 -{
 -      return to_cpumask(sg->sgp->cpumask);
 -}
 -
 -/**
 - * group_first_cpu - Returns the first cpu in the cpumask of a sched_group.
 - * @group: The group whose first cpu is to be returned.
 - */
 -static inline unsigned int group_first_cpu(struct sched_group *group)
 -{
 -      return cpumask_first(sched_group_cpus(group));
 -}
 -
  struct sched_domain_attr {
        int relax_domain_level;
  };
  
  extern int sched_domain_level_max;
  
 +struct sched_group;
 +
  struct sched_domain {
        /* These fields must be setup */
        struct sched_domain *parent;    /* top domain must be null terminated */
        unsigned int wake_idx;
        unsigned int forkexec_idx;
        unsigned int smt_gain;
 +
 +      int nohz_idle;                  /* NOHZ IDLE status */
        int flags;                      /* See SD_* */
        int level;
  
@@@ -882,6 -1007,18 +883,6 @@@ extern void partition_sched_domains(in
  cpumask_var_t *alloc_sched_domains(unsigned int ndoms);
  void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms);
  
 -/* Test a flag in parent sched domain */
 -static inline int test_sd_parent(struct sched_domain *sd, int flag)
 -{
 -      if (sd->parent && (sd->parent->flags & flag))
 -              return 1;
 -
 -      return 0;
 -}
 -
 -unsigned long default_scale_freq_power(struct sched_domain *sd, int cpu);
 -unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu);
 -
  bool cpus_share_cache(int this_cpu, int that_cpu);
  
  #else /* CONFIG_SMP */
@@@ -916,6 -1053,72 +917,6 @@@ struct mempolicy
  struct pipe_inode_info;
  struct uts_namespace;
  
 -struct rq;
 -struct sched_domain;
 -
 -/*
 - * wake flags
 - */
 -#define WF_SYNC               0x01            /* waker goes to sleep after wakup */
 -#define WF_FORK               0x02            /* child wakeup after fork */
 -#define WF_MIGRATED   0x04            /* internal use, task got migrated */
 -
 -#define ENQUEUE_WAKEUP                1
 -#define ENQUEUE_HEAD          2
 -#ifdef CONFIG_SMP
 -#define ENQUEUE_WAKING                4       /* sched_class::task_waking was called */
 -#else
 -#define ENQUEUE_WAKING                0
 -#endif
 -
 -#define DEQUEUE_SLEEP         1
 -
 -struct sched_class {
 -      const struct sched_class *next;
 -
 -      void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
 -      void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
 -      void (*yield_task) (struct rq *rq);
 -      bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt);
 -
 -      void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);
 -
 -      struct task_struct * (*pick_next_task) (struct rq *rq);
 -      void (*put_prev_task) (struct rq *rq, struct task_struct *p);
 -
 -#ifdef CONFIG_SMP
 -      int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
 -      void (*migrate_task_rq)(struct task_struct *p, int next_cpu);
 -
 -      void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
 -      void (*post_schedule) (struct rq *this_rq);
 -      void (*task_waking) (struct task_struct *task);
 -      void (*task_woken) (struct rq *this_rq, struct task_struct *task);
 -
 -      void (*set_cpus_allowed)(struct task_struct *p,
 -                               const struct cpumask *newmask);
 -
 -      void (*rq_online)(struct rq *rq);
 -      void (*rq_offline)(struct rq *rq);
 -#endif
 -
 -      void (*set_curr_task) (struct rq *rq);
 -      void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
 -      void (*task_fork) (struct task_struct *p);
 -
 -      void (*switched_from) (struct rq *this_rq, struct task_struct *task);
 -      void (*switched_to) (struct rq *this_rq, struct task_struct *task);
 -      void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
 -                           int oldprio);
 -
 -      unsigned int (*get_rr_interval) (struct rq *rq,
 -                                       struct task_struct *task);
 -
 -#ifdef CONFIG_FAIR_GROUP_SCHED
 -      void (*task_move_group) (struct task_struct *p, int on_rq);
 -#endif
 -};
 -
  struct load_weight {
        unsigned long weight, inv_weight;
  };
@@@ -992,7 -1195,6 +993,7 @@@ struct sched_entity 
        /* rq "owned" by this entity/group: */
        struct cfs_rq           *my_q;
  #endif
 +
  /*
   * Load-tracking only depends on SMP, FAIR_GROUP_SCHED dependency below may be
   * removed when useful for applications beyond shares distribution (e.g.
  struct sched_rt_entity {
        struct list_head run_list;
        unsigned long timeout;
 +      unsigned long watchdog_stamp;
        unsigned int time_slice;
  
        struct sched_rt_entity *back;
  #endif
  };
  
 -/*
 - * default timeslice is 100 msecs (used only for SCHED_RR tasks).
 - * Timeslices get refilled after they expire.
 - */
 -#define RR_TIMESLICE          (100 * HZ / 1000)
  
  struct rcu_node;
  
@@@ -1107,10 -1313,8 +1108,10 @@@ struct task_struct 
        int exit_code, exit_signal;
        int pdeath_signal;  /*  The signal sent when the parent dies  */
        unsigned int jobctl;    /* JOBCTL_*, siglock protected */
 -      /* ??? */
 +
 +      /* Used for emulating ABI behavior of previous Linux versions */
        unsigned int personality;
 +
        unsigned did_exec:1;
        unsigned in_execve:1;   /* Tell the LSMs that the process is doing an
                                 * execve */
  
        cputime_t utime, stime, utimescaled, stimescaled;
        cputime_t gtime;
 -#ifndef CONFIG_VIRT_CPU_ACCOUNTING
 +#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
        struct cputime prev_cputime;
 +#endif
 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 +      seqlock_t vtime_seqlock;
 +      unsigned long long vtime_snap;
 +      enum {
 +              VTIME_SLEEPING = 0,
 +              VTIME_USER,
 +              VTIME_SYS,
 +      } vtime_snap_whence;
  #endif
        unsigned long nvcsw, nivcsw; /* context switch counts */
        struct timespec start_time;             /* monotonic time */
  #ifdef CONFIG_UPROBES
        struct uprobe_task *utask;
  #endif
 +#if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE)
 +      unsigned int    sequential_io;
 +      unsigned int    sequential_io_avg;
 +#endif
  };
  
  /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@@ -1432,6 -1623,37 +1433,6 @@@ static inline void set_numabalancing_st
  }
  #endif
  
 -/*
 - * Priority of a process goes from 0..MAX_PRIO-1, valid RT
 - * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
 - * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
 - * values are inverted: lower p->prio value means higher priority.
 - *
 - * The MAX_USER_RT_PRIO value allows the actual maximum
 - * RT priority to be separate from the value exported to
 - * user-space.  This allows kernel threads to set their
 - * priority to a value higher than any user task. Note:
 - * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
 - */
 -
 -#define MAX_USER_RT_PRIO      100
 -#define MAX_RT_PRIO           MAX_USER_RT_PRIO
 -
 -#define MAX_PRIO              (MAX_RT_PRIO + 40)
 -#define DEFAULT_PRIO          (MAX_RT_PRIO + 20)
 -
 -static inline int rt_prio(int prio)
 -{
 -      if (unlikely(prio < MAX_RT_PRIO))
 -              return 1;
 -      return 0;
 -}
 -
 -static inline int rt_task(struct task_struct *p)
 -{
 -      return rt_prio(p->prio);
 -}
 -
  static inline struct pid *task_pid(struct task_struct *task)
  {
        return task->pids[PIDTYPE_PID].pid;
@@@ -1571,37 -1793,6 +1572,37 @@@ static inline void put_task_struct(stru
                __put_task_struct(t);
  }
  
 +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 +extern void task_cputime(struct task_struct *t,
 +                       cputime_t *utime, cputime_t *stime);
 +extern void task_cputime_scaled(struct task_struct *t,
 +                              cputime_t *utimescaled, cputime_t *stimescaled);
 +extern cputime_t task_gtime(struct task_struct *t);
 +#else
 +static inline void task_cputime(struct task_struct *t,
 +                              cputime_t *utime, cputime_t *stime)
 +{
 +      if (utime)
 +              *utime = t->utime;
 +      if (stime)
 +              *stime = t->stime;
 +}
 +
 +static inline void task_cputime_scaled(struct task_struct *t,
 +                                     cputime_t *utimescaled,
 +                                     cputime_t *stimescaled)
 +{
 +      if (utimescaled)
 +              *utimescaled = t->utimescaled;
 +      if (stimescaled)
 +              *stimescaled = t->stimescaled;
 +}
 +
 +static inline cputime_t task_gtime(struct task_struct *t)
 +{
 +      return t->gtime;
 +}
 +#endif
  extern void task_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st);
  extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime_t *st);
  
  #define PF_FROZEN     0x00010000      /* frozen for system suspend */
  #define PF_FSTRANS    0x00020000      /* inside a filesystem transaction */
  #define PF_KSWAPD     0x00040000      /* I am kswapd */
 +#define PF_MEMALLOC_NOIO 0x00080000   /* Allocating memory without IO involved */
  #define PF_LESS_THROTTLE 0x00100000   /* Throttle me less: I clean memory */
  #define PF_KTHREAD    0x00200000      /* I am a kernel thread */
  #define PF_RANDOMIZE  0x00400000      /* randomize virtual address space */
  #define PF_SWAPWRITE  0x00800000      /* Allowed to write to swap */
  #define PF_SPREAD_PAGE        0x01000000      /* Spread page cache over cpuset */
  #define PF_SPREAD_SLAB        0x02000000      /* Spread some slab caches over cpuset */
 -#define PF_THREAD_BOUND       0x04000000      /* Thread bound to specific cpu */
 +#define PF_NO_SETAFFINITY 0x04000000  /* Userland is not allowed to meddle with cpus_allowed */
  #define PF_MCE_EARLY    0x08000000      /* Early kill for mce process policy */
  #define PF_MEMPOLICY  0x10000000      /* Non-default NUMA mempolicy */
  #define PF_MUTEX_TESTER       0x20000000      /* Thread belongs to the rt mutex tester */
  #define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
  #define used_math() tsk_used_math(current)
  
 +/* __GFP_IO isn't allowed if PF_MEMALLOC_NOIO is set in current->flags */
 +static inline gfp_t memalloc_noio_flags(gfp_t flags)
 +{
 +      if (unlikely(current->flags & PF_MEMALLOC_NOIO))
 +              flags &= ~__GFP_IO;
 +      return flags;
 +}
 +
 +static inline unsigned int memalloc_noio_save(void)
 +{
 +      unsigned int flags = current->flags & PF_MEMALLOC_NOIO;
 +      current->flags |= PF_MEMALLOC_NOIO;
 +      return flags;
 +}
 +
 +static inline void memalloc_noio_restore(unsigned int flags)
 +{
 +      current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flags;
 +}
 +
  /*
   * task->jobctl flags
   */
@@@ -1766,13 -1936,13 +1767,13 @@@ static inline int set_cpus_allowed_ptr(
  }
  #endif
  
 -#ifdef CONFIG_NO_HZ
 +#ifdef CONFIG_NO_HZ_COMMON
  void calc_load_enter_idle(void);
  void calc_load_exit_idle(void);
  #else
  static inline void calc_load_enter_idle(void) { }
  static inline void calc_load_exit_idle(void) { }
 -#endif /* CONFIG_NO_HZ */
 +#endif /* CONFIG_NO_HZ_COMMON */
  
  #ifndef CONFIG_CPUMASK_OFFSTACK
  static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
@@@ -1858,20 -2028,64 +1859,20 @@@ extern void idle_task_exit(void)
  static inline void idle_task_exit(void) {}
  #endif
  
 -#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
 -extern void wake_up_idle_cpu(int cpu);
 +#if defined(CONFIG_NO_HZ_COMMON) && defined(CONFIG_SMP)
 +extern void wake_up_nohz_cpu(int cpu);
  #else
 -static inline void wake_up_idle_cpu(int cpu) { }
 +static inline void wake_up_nohz_cpu(int cpu) { }
  #endif
  
 -extern unsigned int sysctl_sched_latency;
 -extern unsigned int sysctl_sched_min_granularity;
 -extern unsigned int sysctl_sched_wakeup_granularity;
 -extern unsigned int sysctl_sched_child_runs_first;
 -
 -enum sched_tunable_scaling {
 -      SCHED_TUNABLESCALING_NONE,
 -      SCHED_TUNABLESCALING_LOG,
 -      SCHED_TUNABLESCALING_LINEAR,
 -      SCHED_TUNABLESCALING_END,
 -};
 -extern enum sched_tunable_scaling sysctl_sched_tunable_scaling;
 -
 -extern unsigned int sysctl_numa_balancing_scan_delay;
 -extern unsigned int sysctl_numa_balancing_scan_period_min;
 -extern unsigned int sysctl_numa_balancing_scan_period_max;
 -extern unsigned int sysctl_numa_balancing_scan_period_reset;
 -extern unsigned int sysctl_numa_balancing_scan_size;
 -extern unsigned int sysctl_numa_balancing_settle_count;
 -
 -#ifdef CONFIG_SCHED_DEBUG
 -extern unsigned int sysctl_sched_migration_cost;
 -extern unsigned int sysctl_sched_nr_migrate;
 -extern unsigned int sysctl_sched_time_avg;
 -extern unsigned int sysctl_timer_migration;
 -extern unsigned int sysctl_sched_shares_window;
 -
 -int sched_proc_update_handler(struct ctl_table *table, int write,
 -              void __user *buffer, size_t *length,
 -              loff_t *ppos);
 -#endif
 -#ifdef CONFIG_SCHED_DEBUG
 -static inline unsigned int get_sysctl_timer_migration(void)
 -{
 -      return sysctl_timer_migration;
 -}
 +#ifdef CONFIG_NO_HZ_FULL
 +extern bool sched_can_stop_tick(void);
 +extern u64 scheduler_tick_max_deferment(void);
  #else
 -static inline unsigned int get_sysctl_timer_migration(void)
 -{
 -      return 1;
 -}
 +static inline bool sched_can_stop_tick(void) { return false; }
  #endif
 -extern unsigned int sysctl_sched_rt_period;
 -extern int sysctl_sched_rt_runtime;
 -
 -int sched_rt_handler(struct ctl_table *table, int write,
 -              void __user *buffer, size_t *lenp,
 -              loff_t *ppos);
  
  #ifdef CONFIG_SCHED_AUTOGROUP
 -extern unsigned int sysctl_sched_autogroup_enabled;
 -
  extern void sched_autogroup_create_attach(struct task_struct *p);
  extern void sched_autogroup_detach(struct task_struct *p);
  extern void sched_autogroup_fork(struct signal_struct *sig);
@@@ -1887,6 -2101,30 +1888,6 @@@ static inline void sched_autogroup_fork
  static inline void sched_autogroup_exit(struct signal_struct *sig) { }
  #endif
  
 -#ifdef CONFIG_CFS_BANDWIDTH
 -extern unsigned int sysctl_sched_cfs_bandwidth_slice;
 -#endif
 -
 -#ifdef CONFIG_RT_MUTEXES
 -extern int rt_mutex_getprio(struct task_struct *p);
 -extern void rt_mutex_setprio(struct task_struct *p, int prio);
 -extern void rt_mutex_adjust_pi(struct task_struct *p);
 -static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
 -{
 -      return tsk->pi_blocked_on != NULL;
 -}
 -#else
 -static inline int rt_mutex_getprio(struct task_struct *p)
 -{
 -      return p->normal_prio;
 -}
 -# define rt_mutex_adjust_pi(p)                do { } while (0)
 -static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
 -{
 -      return false;
 -}
 -#endif
 -
  extern bool yield_to(struct task_struct *p, bool preempt);
  extern void set_user_nice(struct task_struct *p, long nice);
  extern int task_prio(const struct task_struct *p);
@@@ -2022,6 -2260,7 +2023,6 @@@ extern struct sigqueue *sigqueue_alloc(
  extern void sigqueue_free(struct sigqueue *);
  extern int send_sigqueue(struct sigqueue *,  struct task_struct *, int group);
  extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
 -extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
  
  static inline void restore_saved_sigmask(void)
  {
@@@ -2067,17 -2306,6 +2068,17 @@@ static inline int sas_ss_flags(unsigne
                : on_sig_stack(sp) ? SS_ONSTACK : 0);
  }
  
 +static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig)
 +{
 +      if (unlikely((ksig->ka.sa.sa_flags & SA_ONSTACK)) && ! sas_ss_flags(sp))
 +#ifdef CONFIG_STACK_GROWSUP
 +              return current->sas_ss_sp;
 +#else
 +              return current->sas_ss_sp + current->sas_ss_size;
 +#endif
 +      return sp;
 +}
 +
  /*
   * Routines for handling mm_structs
   */
@@@ -2258,18 -2486,27 +2259,18 @@@ static inline void threadgroup_change_e
   *
   * Lock the threadgroup @tsk belongs to.  No new task is allowed to enter
   * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or
 - * perform exec.  This is useful for cases where the threadgroup needs to
 - * stay stable across blockable operations.
 + * change ->group_leader/pid.  This is useful for cases where the threadgroup
 + * needs to stay stable across blockable operations.
   *
   * fork and exit paths explicitly call threadgroup_change_{begin|end}() for
   * synchronization.  While held, no new task will be added to threadgroup
   * and no existing live task will have its PF_EXITING set.
   *
 - * During exec, a task goes and puts its thread group through unusual
 - * changes.  After de-threading, exclusive access is assumed to resources
 - * which are usually shared by tasks in the same group - e.g. sighand may
 - * be replaced with a new one.  Also, the exec'ing task takes over group
 - * leader role including its pid.  Exclude these changes while locked by
 - * grabbing cred_guard_mutex which is used to synchronize exec path.
 + * de_thread() does threadgroup_change_{begin|end}() when a non-leader
 + * sub-thread becomes a new leader.
   */
  static inline void threadgroup_lock(struct task_struct *tsk)
  {
 -      /*
 -       * exec uses exit for de-threading nesting group_rwsem inside
 -       * cred_guard_mutex. Grab cred_guard_mutex first.
 -       */
 -      mutex_lock(&tsk->signal->cred_guard_mutex);
        down_write(&tsk->signal->group_rwsem);
  }
  
  static inline void threadgroup_unlock(struct task_struct *tsk)
  {
        up_write(&tsk->signal->group_rwsem);
 -      mutex_unlock(&tsk->signal->cred_guard_mutex);
  }
  #else
  static inline void threadgroup_change_begin(struct task_struct *tsk) {}
@@@ -2457,47 -2695,6 +2458,47 @@@ static inline int spin_needbreak(spinlo
  #endif
  }
  
 +/*
 + * Idle thread specific functions to determine the need_resched
 + * polling state. We have two versions, one based on TS_POLLING in
 + * thread_info.status and one based on TIF_POLLING_NRFLAG in
 + * thread_info.flags
 + */
 +#ifdef TS_POLLING
 +static inline int tsk_is_polling(struct task_struct *p)
 +{
 +      return task_thread_info(p)->status & TS_POLLING;
 +}
 +static inline void current_set_polling(void)
 +{
 +      current_thread_info()->status |= TS_POLLING;
 +}
 +
 +static inline void current_clr_polling(void)
 +{
 +      current_thread_info()->status &= ~TS_POLLING;
 +      smp_mb__after_clear_bit();
 +}
 +#elif defined(TIF_POLLING_NRFLAG)
 +static inline int tsk_is_polling(struct task_struct *p)
 +{
 +      return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG);
 +}
 +static inline void current_set_polling(void)
 +{
 +      set_thread_flag(TIF_POLLING_NRFLAG);
 +}
 +
 +static inline void current_clr_polling(void)
 +{
 +      clear_thread_flag(TIF_POLLING_NRFLAG);
 +}
 +#else
 +static inline int tsk_is_polling(struct task_struct *p) { return 0; }
 +static inline void current_set_polling(void) { }
 +static inline void current_clr_polling(void) { }
 +#endif
 +
  /*
   * Thread group CPU time accounting.
   */
@@@ -2557,8 -2754,28 +2558,8 @@@ static inline void set_task_cpu(struct 
  extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
  extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
  
 -extern void normalize_rt_tasks(void);
 -
  #ifdef CONFIG_CGROUP_SCHED
 -
  extern struct task_group root_task_group;
 -
 -extern struct task_group *sched_create_group(struct task_group *parent);
 -extern void sched_destroy_group(struct task_group *tg);
 -extern void sched_move_task(struct task_struct *tsk);
 -#ifdef CONFIG_FAIR_GROUP_SCHED
 -extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
 -extern unsigned long sched_group_shares(struct task_group *tg);
 -#endif
 -#ifdef CONFIG_RT_GROUP_SCHED
 -extern int sched_group_set_rt_runtime(struct task_group *tg,
 -                                    long rt_runtime_us);
 -extern long sched_group_rt_runtime(struct task_group *tg);
 -extern int sched_group_set_rt_period(struct task_group *tg,
 -                                    long rt_period_us);
 -extern long sched_group_rt_period(struct task_group *tg);
 -extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 -#endif
  #endif /* CONFIG_CGROUP_SCHED */
  
  extern int task_can_switch_user(struct user_struct *up,
diff --combined include/linux/tty.h
index 7e92bd86a808cfbdf31bf38f1165ab30fe93c2ff,96d640b32cd8bf380ea6f56e7ef16359f55e971f..8780bd2a272ab6672c8f6c32340b7d1ab2831acb
@@@ -202,8 -202,7 +202,8 @@@ struct tty_port 
        unsigned long           iflags;         /* TTYP_ internal flags */
  #define TTYP_FLUSHING                 1  /* Flushing to ldisc in progress */
  #define TTYP_FLUSHPENDING             2  /* Queued buffer flush pending */
 -      unsigned char           console:1;      /* port is a console */
 +      unsigned char           console:1,      /* port is a console */
 +                              low_latency:1;  /* direct buffer flush */
        struct mutex            mutex;          /* Locking */
        struct mutex            buf_mutex;      /* Buffer alloc lock */
        unsigned char           *xmit_buf;      /* Optional buffer */
@@@ -255,9 -254,9 +255,9 @@@ struct tty_struct 
        int count;
        struct winsize winsize;         /* termios mutex */
        unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
 -      unsigned char low_latency:1, warned:1;
        unsigned char ctrl_status;      /* ctrl_lock */
        unsigned int receive_room;      /* Bytes free for queue */
 +      int flow_change;
  
        struct tty_struct *link;
        struct fasync_struct *fasync;
@@@ -315,62 -314,14 +315,62 @@@ struct tty_file_private 
  #define TTY_NO_WRITE_SPLIT    17      /* Preserve write boundaries to driver */
  #define TTY_HUPPED            18      /* Post driver->hangup() */
  #define TTY_HUPPING           21      /* ->hangup() in progress */
 +#define TTY_LDISC_HALTED      22      /* Line discipline is halted */
  
  #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
  
 +/* Values for tty->flow_change */
 +#define TTY_THROTTLE_SAFE 1
 +#define TTY_UNTHROTTLE_SAFE 2
 +
 +static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
 +{
 +      tty->flow_change = val;
 +}
 +
 +static inline void tty_set_flow_change(struct tty_struct *tty, int val)
 +{
 +      tty->flow_change = val;
 +      smp_mb();
 +}
 +
 +#ifdef CONFIG_TTY
 +extern void console_init(void);
 +extern void tty_kref_put(struct tty_struct *tty);
 +extern struct pid *tty_get_pgrp(struct tty_struct *tty);
 +extern void tty_vhangup_self(void);
 +extern void disassociate_ctty(int priv);
 +extern dev_t tty_devnum(struct tty_struct *tty);
 +extern void proc_clear_tty(struct task_struct *p);
 +extern struct tty_struct *get_current_tty(void);
 +/* tty_io.c */
 +extern int __init tty_init(void);
 +#else
 +static inline void console_init(void)
 +{ }
 +static inline void tty_kref_put(struct tty_struct *tty)
 +{ }
 +static inline struct pid *tty_get_pgrp(struct tty_struct *tty)
 +{ return NULL; }
 +static inline void tty_vhangup_self(void)
 +{ }
 +static inline void disassociate_ctty(int priv)
 +{ }
 +static inline dev_t tty_devnum(struct tty_struct *tty)
 +{ return 0; }
 +static inline void proc_clear_tty(struct task_struct *p)
 +{ }
 +static inline struct tty_struct *get_current_tty(void)
 +{ return NULL; }
 +/* tty_io.c */
 +static inline int __init tty_init(void)
 +{ return 0; }
 +#endif
 +
  extern void tty_write_flush(struct tty_struct *);
  
  extern struct ktermios tty_std_termios;
  
 -extern void console_init(void);
  extern int vcs_init(void);
  
  extern struct class *tty_class;
@@@ -390,6 -341,7 +390,6 @@@ static inline struct tty_struct *tty_kr
                kref_get(&tty->kref);
        return tty;
  }
 -extern void tty_kref_put(struct tty_struct *tty);
  
  extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
                              const char *routine);
@@@ -416,49 -368,36 +416,49 @@@ extern int tty_write_room(struct tty_st
  extern void tty_driver_flush_buffer(struct tty_struct *tty);
  extern void tty_throttle(struct tty_struct *tty);
  extern void tty_unthrottle(struct tty_struct *tty);
 +extern int tty_throttle_safe(struct tty_struct *tty);
 +extern int tty_unthrottle_safe(struct tty_struct *tty);
  extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
  extern void tty_driver_remove_tty(struct tty_driver *driver,
                                  struct tty_struct *tty);
  extern void tty_free_termios(struct tty_struct *tty);
  extern int is_current_pgrp_orphaned(void);
 -extern struct pid *tty_get_pgrp(struct tty_struct *tty);
  extern int is_ignored(int sig);
  extern int tty_signal(int sig, struct tty_struct *tty);
  extern void tty_hangup(struct tty_struct *tty);
  extern void tty_vhangup(struct tty_struct *tty);
  extern void tty_vhangup_locked(struct tty_struct *tty);
 -extern void tty_vhangup_self(void);
  extern void tty_unhangup(struct file *filp);
  extern int tty_hung_up_p(struct file *filp);
  extern void do_SAK(struct tty_struct *tty);
  extern void __do_SAK(struct tty_struct *tty);
 -extern void disassociate_ctty(int priv);
  extern void no_tty(void);
 -extern void tty_flip_buffer_push(struct tty_struct *tty);
  extern void tty_flush_to_ldisc(struct tty_struct *tty);
  extern void tty_buffer_free_all(struct tty_port *port);
  extern void tty_buffer_flush(struct tty_struct *tty);
  extern void tty_buffer_init(struct tty_port *port);
 -extern speed_t tty_get_baud_rate(struct tty_struct *tty);
  extern speed_t tty_termios_baud_rate(struct ktermios *termios);
  extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
  extern void tty_termios_encode_baud_rate(struct ktermios *termios,
                                                speed_t ibaud, speed_t obaud);
  extern void tty_encode_baud_rate(struct tty_struct *tty,
                                                speed_t ibaud, speed_t obaud);
 +
 +/**
 + *    tty_get_baud_rate       -       get tty bit rates
 + *    @tty: tty to query
 + *
 + *    Returns the baud rate as an integer for this terminal. The
 + *    termios lock must be held by the caller and the terminal bit
 + *    flags may be updated.
 + *
 + *    Locking: none
 + */
 +static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
 +{
 +      return tty_termios_baud_rate(&tty->termios);
 +}
 +
  extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
  extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
  extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
@@@ -476,6 -415,9 +476,6 @@@ extern long tty_ioctl(struct file *file
  extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                        unsigned int cmd, unsigned long arg);
  extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
 -extern dev_t tty_devnum(struct tty_struct *tty);
 -extern void proc_clear_tty(struct task_struct *p);
 -extern struct tty_struct *get_current_tty(void);
  extern void tty_default_fops(struct file_operations *fops);
  extern struct tty_struct *alloc_tty_struct(void);
  extern int tty_alloc_file(struct file *file);
@@@ -535,8 -477,6 +535,8 @@@ extern int tty_port_carrier_raised(stru
  extern void tty_port_raise_dtr_rts(struct tty_port *port);
  extern void tty_port_lower_dtr_rts(struct tty_port *port);
  extern void tty_port_hangup(struct tty_port *port);
 +extern void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
 +extern void tty_port_tty_wakeup(struct tty_port *port);
  extern int tty_port_block_til_ready(struct tty_port *port,
                                struct tty_struct *tty, struct file *filp);
  extern int tty_port_close_start(struct tty_port *port,
@@@ -561,6 -501,8 +561,6 @@@ extern void tty_ldisc_release(struct tt
  extern void tty_ldisc_init(struct tty_struct *tty);
  extern void tty_ldisc_deinit(struct tty_struct *tty);
  extern void tty_ldisc_begin(void);
 -/* This last one is just for the tty layer internals and shouldn't be used elsewhere */
 -extern void tty_ldisc_enable(struct tty_struct *tty);
  
  
  /* n_tty.c */
@@@ -575,8 -517,7 +575,7 @@@ extern void tty_audit_exit(void)
  extern void tty_audit_fork(struct signal_struct *sig);
  extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
  extern void tty_audit_push(struct tty_struct *tty);
- extern int tty_audit_push_task(struct task_struct *tsk,
-                              kuid_t loginuid, u32 sessionid);
+ extern int tty_audit_push_current(void);
  #else
  static inline void tty_audit_add_data(struct tty_struct *tty,
                unsigned char *data, size_t size, unsigned icanon)
@@@ -594,13 -535,15 +593,12 @@@ static inline void tty_audit_fork(struc
  static inline void tty_audit_push(struct tty_struct *tty)
  {
  }
- static inline int tty_audit_push_task(struct task_struct *tsk,
-                                     kuid_t loginuid, u32 sessionid)
+ static inline int tty_audit_push_current(void)
  {
        return 0;
  }
  #endif
  
 -/* tty_io.c */
 -extern int __init tty_init(void);
 -
  /* tty_ioctl.c */
  extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                       unsigned int cmd, unsigned long arg);
@@@ -691,12 -634,5 +689,12 @@@ do {                                                                     
        finish_wait(&wq, &__wait);                                      \
  } while (0)
  
 +#ifdef CONFIG_PROC_FS
 +extern void proc_tty_register_driver(struct tty_driver *);
 +extern void proc_tty_unregister_driver(struct tty_driver *);
 +#else
 +static inline void proc_tty_register_driver(struct tty_driver *d) {}
 +static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
 +#endif
  
  #endif
diff --combined kernel/audit.c
index 0b084fa44b1f21f3cc73508676e79d58b08f1896,5c7e62ff4795f7fd2d4f12375d9bbf8301843ae3..21c7fa615bd3107b0c28a4da499ea3ee7361d695
@@@ -49,6 -49,8 +49,8 @@@
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/kthread.h>
+ #include <linux/kernel.h>
+ #include <linux/syscalls.h>
  
  #include <linux/audit.h>
  
@@@ -58,7 -60,7 +60,7 @@@
  #ifdef CONFIG_SECURITY
  #include <linux/security.h>
  #endif
 -#include <linux/netlink.h>
 +#include <net/netlink.h>
  #include <linux/freezer.h>
  #include <linux/tty.h>
  #include <linux/pid_namespace.h>
@@@ -265,7 -267,6 +267,6 @@@ void audit_log_lost(const char *message
  }
  
  static int audit_log_config_change(char *function_name, int new, int old,
-                                  kuid_t loginuid, u32 sessionid, u32 sid,
                                   int allow_changes)
  {
        struct audit_buffer *ab;
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (unlikely(!ab))
                return rc;
-       audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
-                        old, from_kuid(&init_user_ns, loginuid), sessionid);
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-               rc = security_secid_to_secctx(sid, &ctx, &len);
-               if (rc) {
-                       audit_log_format(ab, " sid=%u", sid);
-                       allow_changes = 0; /* Something weird, deny request */
-               } else {
-                       audit_log_format(ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
+       audit_log_format(ab, "%s=%d old=%d", function_name, new, old);
+       audit_log_session_info(ab);
+       rc = audit_log_task_context(ab);
+       if (rc)
+               allow_changes = 0; /* Something weird, deny request */
        audit_log_format(ab, " res=%d", allow_changes);
        audit_log_end(ab);
        return rc;
  }
  
- static int audit_do_config_change(char *function_name, int *to_change,
-                                 int new, kuid_t loginuid, u32 sessionid,
-                                 u32 sid)
+ static int audit_do_config_change(char *function_name, int *to_change, int new)
  {
        int allow_changes, rc = 0, old = *to_change;
  
                allow_changes = 1;
  
        if (audit_enabled != AUDIT_OFF) {
-               rc = audit_log_config_change(function_name, new, old, loginuid,
-                                            sessionid, sid, allow_changes);
+               rc = audit_log_config_change(function_name, new, old, allow_changes);
                if (rc)
                        allow_changes = 0;
        }
        return rc;
  }
  
- static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid,
-                               u32 sid)
+ static int audit_set_rate_limit(int limit)
  {
-       return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
-                                     limit, loginuid, sessionid, sid);
+       return audit_do_config_change("audit_rate_limit", &audit_rate_limit, limit);
  }
  
- static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid,
-                                  u32 sid)
+ static int audit_set_backlog_limit(int limit)
  {
-       return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
-                                     limit, loginuid, sessionid, sid);
+       return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit);
  }
  
- static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid)
+ static int audit_set_enabled(int state)
  {
        int rc;
        if (state < AUDIT_OFF || state > AUDIT_LOCKED)
                return -EINVAL;
  
-       rc =  audit_do_config_change("audit_enabled", &audit_enabled, state,
-                                    loginuid, sessionid, sid);
+       rc =  audit_do_config_change("audit_enabled", &audit_enabled, state);
        if (!rc)
                audit_ever_enabled |= !!state;
  
        return rc;
  }
  
- static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid)
+ static int audit_set_failure(int state)
  {
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PRINTK
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
  
-       return audit_do_config_change("audit_failure", &audit_failure, state,
-                                     loginuid, sessionid, sid);
+       return audit_do_config_change("audit_failure", &audit_failure, state);
  }
  
  /*
@@@ -417,34 -398,53 +398,53 @@@ static void kauditd_send_skb(struct sk_
                consume_skb(skb);
  }
  
- static int kauditd_thread(void *dummy)
+ /*
+  * flush_hold_queue - empty the hold queue if auditd appears
+  *
+  * If auditd just started, drain the queue of messages already
+  * sent to syslog/printk.  Remember loss here is ok.  We already
+  * called audit_log_lost() if it didn't go out normally.  so the
+  * race between the skb_dequeue and the next check for audit_pid
+  * doesn't matter.
+  *
+  * If you ever find kauditd to be too slow we can get a perf win
+  * by doing our own locking and keeping better track if there
+  * are messages in this queue.  I don't see the need now, but
+  * in 5 years when I want to play with this again I'll see this
+  * note and still have no friggin idea what i'm thinking today.
+  */
+ static void flush_hold_queue(void)
  {
        struct sk_buff *skb;
  
+       if (!audit_default || !audit_pid)
+               return;
+       skb = skb_dequeue(&audit_skb_hold_queue);
+       if (likely(!skb))
+               return;
+       while (skb && audit_pid) {
+               kauditd_send_skb(skb);
+               skb = skb_dequeue(&audit_skb_hold_queue);
+       }
+       /*
+        * if auditd just disappeared but we
+        * dequeued an skb we need to drop ref
+        */
+       if (skb)
+               consume_skb(skb);
+ }
+ static int kauditd_thread(void *dummy)
+ {
        set_freezable();
        while (!kthread_should_stop()) {
-               /*
-                * if auditd just started drain the queue of messages already
-                * sent to syslog/printk.  remember loss here is ok.  we already
-                * called audit_log_lost() if it didn't go out normally.  so the
-                * race between the skb_dequeue and the next check for audit_pid
-                * doesn't matter.
-                *
-                * if you ever find kauditd to be too slow we can get a perf win
-                * by doing our own locking and keeping better track if there
-                * are messages in this queue.  I don't see the need now, but
-                * in 5 years when I want to play with this again I'll see this
-                * note and still have no friggin idea what i'm thinking today.
-                */
-               if (audit_default && audit_pid) {
-                       skb = skb_dequeue(&audit_skb_hold_queue);
-                       if (unlikely(skb)) {
-                               while (skb && audit_pid) {
-                                       kauditd_send_skb(skb);
-                                       skb = skb_dequeue(&audit_skb_hold_queue);
-                               }
-                       }
-               }
+               struct sk_buff *skb;
+               DECLARE_WAITQUEUE(wait, current);
+               flush_hold_queue();
  
                skb = skb_dequeue(&audit_skb_queue);
                wake_up(&audit_backlog_wait);
                                kauditd_send_skb(skb);
                        else
                                audit_printk_skb(skb);
-               } else {
-                       DECLARE_WAITQUEUE(wait, current);
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       add_wait_queue(&kauditd_wait, &wait);
-                       if (!skb_queue_len(&audit_skb_queue)) {
-                               try_to_freeze();
-                               schedule();
-                       }
+                       continue;
+               }
+               set_current_state(TASK_INTERRUPTIBLE);
+               add_wait_queue(&kauditd_wait, &wait);
  
-                       __set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&kauditd_wait, &wait);
+               if (!skb_queue_len(&audit_skb_queue)) {
+                       try_to_freeze();
+                       schedule();
                }
+               __set_current_state(TASK_RUNNING);
+               remove_wait_queue(&kauditd_wait, &wait);
        }
        return 0;
  }
@@@ -579,13 -578,14 +578,14 @@@ static int audit_netlink_ok(struct sk_b
                return -EPERM;
  
        switch (msg_type) {
-       case AUDIT_GET:
        case AUDIT_LIST:
-       case AUDIT_LIST_RULES:
-       case AUDIT_SET:
        case AUDIT_ADD:
-       case AUDIT_ADD_RULE:
        case AUDIT_DEL:
+               return -EOPNOTSUPP;
+       case AUDIT_GET:
+       case AUDIT_SET:
+       case AUDIT_LIST_RULES:
+       case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
        case AUDIT_SIGNAL_INFO:
        case AUDIT_TTY_GET:
        return err;
  }
  
- static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
-                                    kuid_t auid, u32 ses, u32 sid)
+ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type)
  {
        int rc = 0;
-       char *ctx = NULL;
-       u32 len;
+       uid_t uid = from_kuid(&init_user_ns, current_uid());
  
        if (!audit_enabled) {
                *ab = NULL;
        *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
        if (unlikely(!*ab))
                return rc;
-       audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
-                        task_tgid_vnr(current),
-                        from_kuid(&init_user_ns, current_uid()),
-                        from_kuid(&init_user_ns, auid), ses);
-       if (sid) {
-               rc = security_secid_to_secctx(sid, &ctx, &len);
-               if (rc)
-                       audit_log_format(*ab, " ssid=%u", sid);
-               else {
-                       audit_log_format(*ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
+       audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid);
+       audit_log_session_info(*ab);
+       audit_log_task_context(*ab);
  
        return rc;
  }
  
  static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
-       u32                     seq, sid;
+       u32                     seq;
        void                    *data;
        struct audit_status     *status_get, status_set;
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
-       kuid_t                  loginuid; /* loginuid of sender */
-       u32                     sessionid;
        struct audit_sig_info   *sig_data;
        char                    *ctx = NULL;
        u32                     len;
  
        /* As soon as there's any sign of userspace auditd,
         * start kauditd to talk to it */
 -      if (!kauditd_task)
 +      if (!kauditd_task) {
                kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
 -      if (IS_ERR(kauditd_task)) {
 -              err = PTR_ERR(kauditd_task);
 -              kauditd_task = NULL;
 -              return err;
 +              if (IS_ERR(kauditd_task)) {
 +                      err = PTR_ERR(kauditd_task);
 +                      kauditd_task = NULL;
 +                      return err;
 +              }
        }
-       loginuid = audit_get_loginuid(current);
-       sessionid = audit_get_sessionid(current);
-       security_task_getsecid(current, &sid);
 -
        seq  = nlh->nlmsg_seq;
        data = nlmsg_data(nlh);
  
                        return -EINVAL;
                status_get   = (struct audit_status *)data;
                if (status_get->mask & AUDIT_STATUS_ENABLED) {
-                       err = audit_set_enabled(status_get->enabled,
-                                               loginuid, sessionid, sid);
+                       err = audit_set_enabled(status_get->enabled);
                        if (err < 0)
                                return err;
                }
                if (status_get->mask & AUDIT_STATUS_FAILURE) {
-                       err = audit_set_failure(status_get->failure,
-                                               loginuid, sessionid, sid);
+                       err = audit_set_failure(status_get->failure);
                        if (err < 0)
                                return err;
                }
                        int new_pid = status_get->pid;
  
                        if (audit_enabled != AUDIT_OFF)
-                               audit_log_config_change("audit_pid", new_pid,
-                                                       audit_pid, loginuid,
-                                                       sessionid, sid, 1);
+                               audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
                        audit_pid = new_pid;
                        audit_nlk_portid = NETLINK_CB(skb).portid;
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) {
-                       err = audit_set_rate_limit(status_get->rate_limit,
-                                                  loginuid, sessionid, sid);
+                       err = audit_set_rate_limit(status_get->rate_limit);
                        if (err < 0)
                                return err;
                }
                if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
-                       err = audit_set_backlog_limit(status_get->backlog_limit,
-                                                     loginuid, sessionid, sid);
+                       err = audit_set_backlog_limit(status_get->backlog_limit);
                break;
        case AUDIT_USER:
        case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
  
-               err = audit_filter_user();
+               err = audit_filter_user(msg_type);
                if (err == 1) {
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
-                               err = tty_audit_push_task(current, loginuid,
-                                                            sessionid);
+                               err = tty_audit_push_current();
                                if (err)
                                        break;
                        }
-                       audit_log_common_recv_msg(&ab, msg_type,
-                                                 loginuid, sessionid, sid);
+                       audit_log_common_recv_msg(&ab, msg_type);
                        if (msg_type != AUDIT_USER_TTY)
                                audit_log_format(ab, " msg='%.1024s'",
                                                 (char *)data);
                        else {
                                int size;
  
-                               audit_log_format(ab, " msg=");
+                               audit_log_format(ab, " data=");
                                size = nlmsg_len(nlh);
                                if (size > 0 &&
                                    ((unsigned char *)data)[size - 1] == '\0')
                        audit_log_end(ab);
                }
                break;
-       case AUDIT_ADD:
-       case AUDIT_DEL:
-               if (nlmsg_len(nlh) < sizeof(struct audit_rule))
-                       return -EINVAL;
-               if (audit_enabled == AUDIT_LOCKED) {
-                       audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                                 loginuid, sessionid, sid);
-                       audit_log_format(ab, " audit_enabled=%d res=0",
-                                        audit_enabled);
-                       audit_log_end(ab);
-                       return -EPERM;
-               }
-               /* fallthrough */
-       case AUDIT_LIST:
-               err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid,
-                                          seq, data, nlmsg_len(nlh),
-                                          loginuid, sessionid, sid);
-               break;
        case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
                if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
-                       audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                                 loginuid, sessionid, sid);
-                       audit_log_format(ab, " audit_enabled=%d res=0",
-                                        audit_enabled);
+                       audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
+                       audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled);
                        audit_log_end(ab);
                        return -EPERM;
                }
                /* fallthrough */
        case AUDIT_LIST_RULES:
                err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid,
-                                          seq, data, nlmsg_len(nlh),
-                                          loginuid, sessionid, sid);
+                                          seq, data, nlmsg_len(nlh));
                break;
        case AUDIT_TRIM:
                audit_trim_trees();
-               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                         loginuid, sessionid, sid);
+               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
                audit_log_format(ab, " op=trim res=1");
                audit_log_end(ab);
                break;
                /* OK, here comes... */
                err = audit_tag_tree(old, new);
  
-               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE,
-                                         loginuid, sessionid, sid);
+               audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
  
                audit_log_format(ab, " op=make_equiv old=");
                audit_log_untrustedstring(ab, old);
                struct audit_tty_status s;
                struct task_struct *tsk = current;
  
-               spin_lock_irq(&tsk->sighand->siglock);
+               spin_lock(&tsk->sighand->siglock);
                s.enabled = tsk->signal->audit_tty != 0;
-               spin_unlock_irq(&tsk->sighand->siglock);
+               s.log_passwd = tsk->signal->audit_tty_log_passwd;
+               spin_unlock(&tsk->sighand->siglock);
  
                audit_send_reply(NETLINK_CB(skb).portid, seq,
                                 AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
                break;
        }
        case AUDIT_TTY_SET: {
-               struct audit_tty_status *s;
+               struct audit_tty_status s;
                struct task_struct *tsk = current;
  
-               if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
-                       return -EINVAL;
-               s = data;
-               if (s->enabled != 0 && s->enabled != 1)
+               memset(&s, 0, sizeof(s));
+               /* guard against past and future API changes */
+               memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len));
+               if ((s.enabled != 0 && s.enabled != 1) ||
+                   (s.log_passwd != 0 && s.log_passwd != 1))
                        return -EINVAL;
  
-               spin_lock_irq(&tsk->sighand->siglock);
-               tsk->signal->audit_tty = s->enabled != 0;
-               spin_unlock_irq(&tsk->sighand->siglock);
+               spin_lock(&tsk->sighand->siglock);
+               tsk->signal->audit_tty = s.enabled;
+               tsk->signal->audit_tty_log_passwd = s.log_passwd;
+               spin_unlock(&tsk->sighand->siglock);
                break;
        }
        default:
@@@ -910,7 -859,7 +859,7 @@@ static void audit_receive_skb(struct sk
  {
        struct nlmsghdr *nlh;
        /*
 -       * len MUST be signed for NLMSG_NEXT to be able to dec it below 0
 +       * len MUST be signed for nlmsg_next to be able to dec it below 0
         * if the nlmsg_len was not aligned
         */
        int len;
        nlh = nlmsg_hdr(skb);
        len = skb->len;
  
 -      while (NLMSG_OK(nlh, len)) {
 +      while (nlmsg_ok(nlh, len)) {
                err = audit_receive_msg(skb, nlh);
                /* if err or if this message says it wants a response */
                if (err || (nlh->nlmsg_flags & NLM_F_ACK))
                        netlink_ack(skb, nlh, err);
  
 -              nlh = NLMSG_NEXT(nlh, len);
 +              nlh = nlmsg_next(nlh, &len);
        }
  }
  
@@@ -1434,6 -1383,14 +1383,14 @@@ void audit_log_d_path(struct audit_buff
        kfree(pathname);
  }
  
+ void audit_log_session_info(struct audit_buffer *ab)
+ {
+       u32 sessionid = audit_get_sessionid(current);
+       uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current));
+       audit_log_format(ab, " auid=%u ses=%u\n", auid, sessionid);
+ }
  void audit_log_key(struct audit_buffer *ab, char *key)
  {
        audit_log_format(ab, " key=");
                audit_log_format(ab, "(null)");
  }
  
+ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
+ {
+       int i;
+       audit_log_format(ab, " %s=", prefix);
+       CAP_FOR_EACH_U32(i) {
+               audit_log_format(ab, "%08x",
+                                cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
+       }
+ }
+ 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;
+       int log = 0;
+       if (!cap_isclear(*perm)) {
+               audit_log_cap(ab, "cap_fp", perm);
+               log = 1;
+       }
+       if (!cap_isclear(*inh)) {
+               audit_log_cap(ab, "cap_fi", inh);
+               log = 1;
+       }
+       if (log)
+               audit_log_format(ab, " cap_fe=%d cap_fver=%x",
+                                name->fcap.fE, name->fcap_ver);
+ }
+ static inline int audit_copy_fcaps(struct audit_names *name,
+                                  const struct dentry *dentry)
+ {
+       struct cpu_vfs_cap_data caps;
+       int rc;
+       if (!dentry)
+               return 0;
+       rc = get_vfs_caps_from_disk(dentry, &caps);
+       if (rc)
+               return rc;
+       name->fcap.permitted = caps.permitted;
+       name->fcap.inheritable = caps.inheritable;
+       name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
+       name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
+                               VFS_CAP_REVISION_SHIFT;
+       return 0;
+ }
+ /* Copy inode data into an audit_names. */
+ void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
+                     const struct inode *inode)
+ {
+       name->ino   = inode->i_ino;
+       name->dev   = inode->i_sb->s_dev;
+       name->mode  = inode->i_mode;
+       name->uid   = inode->i_uid;
+       name->gid   = inode->i_gid;
+       name->rdev  = inode->i_rdev;
+       security_inode_getsecid(inode, &name->osid);
+       audit_copy_fcaps(name, dentry);
+ }
+ /**
+  * audit_log_name - produce AUDIT_PATH record from struct audit_names
+  * @context: audit_context for the task
+  * @n: audit_names structure with reportable details
+  * @path: optional path to report instead of audit_names->name
+  * @record_num: record number to report when handling a list of names
+  * @call_panic: optional pointer to int that will be updated if secid fails
+  */
+ void audit_log_name(struct audit_context *context, struct audit_names *n,
+                   struct path *path, int record_num, int *call_panic)
+ {
+       struct audit_buffer *ab;
+       ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
+       if (!ab)
+               return;
+       audit_log_format(ab, "item=%d", record_num);
+       if (path)
+               audit_log_d_path(ab, " name=", path);
+       else if (n->name) {
+               switch (n->name_len) {
+               case AUDIT_NAME_FULL:
+                       /* log the full path */
+                       audit_log_format(ab, " name=");
+                       audit_log_untrustedstring(ab, n->name->name);
+                       break;
+               case 0:
+                       /* name was specified as a relative path and the
+                        * directory component is the cwd */
+                       audit_log_d_path(ab, " name=", &context->pwd);
+                       break;
+               default:
+                       /* log the name's directory component */
+                       audit_log_format(ab, " name=");
+                       audit_log_n_untrustedstring(ab, n->name->name,
+                                                   n->name_len);
+               }
+       } else
+               audit_log_format(ab, " name=(null)");
+       if (n->ino != (unsigned long)-1) {
+               audit_log_format(ab, " inode=%lu"
+                                " dev=%02x:%02x mode=%#ho"
+                                " ouid=%u ogid=%u rdev=%02x:%02x",
+                                n->ino,
+                                MAJOR(n->dev),
+                                MINOR(n->dev),
+                                n->mode,
+                                from_kuid(&init_user_ns, n->uid),
+                                from_kgid(&init_user_ns, n->gid),
+                                MAJOR(n->rdev),
+                                MINOR(n->rdev));
+       }
+       if (n->osid != 0) {
+               char *ctx = NULL;
+               u32 len;
+               if (security_secid_to_secctx(
+                       n->osid, &ctx, &len)) {
+                       audit_log_format(ab, " osid=%u", n->osid);
+                       if (call_panic)
+                               *call_panic = 2;
+               } else {
+                       audit_log_format(ab, " obj=%s", ctx);
+                       security_release_secctx(ctx, len);
+               }
+       }
+       audit_log_fcaps(ab, n);
+       audit_log_end(ab);
+ }
+ int audit_log_task_context(struct audit_buffer *ab)
+ {
+       char *ctx = NULL;
+       unsigned len;
+       int error;
+       u32 sid;
+       security_task_getsecid(current, &sid);
+       if (!sid)
+               return 0;
+       error = security_secid_to_secctx(sid, &ctx, &len);
+       if (error) {
+               if (error != -EINVAL)
+                       goto error_path;
+               return 0;
+       }
+       audit_log_format(ab, " subj=%s", ctx);
+       security_release_secctx(ctx, len);
+       return 0;
+ error_path:
+       audit_panic("error in audit_log_task_context");
+       return error;
+ }
+ 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)];
+       struct mm_struct *mm = tsk->mm;
+       char *tty;
+       if (!ab)
+               return;
+       /* tsk == current */
+       cred = current_cred();
+       spin_lock_irq(&tsk->sighand->siglock);
+       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+               tty = tsk->signal->tty->name;
+       else
+               tty = "(none)";
+       spin_unlock_irq(&tsk->sighand->siglock);
+       audit_log_format(ab,
+                        " ppid=%ld pid=%d auid=%u uid=%u gid=%u"
+                        " euid=%u suid=%u fsuid=%u"
+                        " egid=%u sgid=%u fsgid=%u ses=%u tty=%s",
+                        sys_getppid(),
+                        tsk->pid,
+                        from_kuid(&init_user_ns, audit_get_loginuid(tsk)),
+                        from_kuid(&init_user_ns, cred->uid),
+                        from_kgid(&init_user_ns, cred->gid),
+                        from_kuid(&init_user_ns, cred->euid),
+                        from_kuid(&init_user_ns, cred->suid),
+                        from_kuid(&init_user_ns, cred->fsuid),
+                        from_kgid(&init_user_ns, cred->egid),
+                        from_kgid(&init_user_ns, cred->sgid),
+                        from_kgid(&init_user_ns, cred->fsgid),
+                        audit_get_sessionid(tsk), tty);
+       get_task_comm(name, tsk);
+       audit_log_format(ab, " comm=");
+       audit_log_untrustedstring(ab, name);
+       if (mm) {
+               down_read(&mm->mmap_sem);
+               if (mm->exe_file)
+                       audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
+               up_read(&mm->mmap_sem);
+       }
+       audit_log_task_context(ab);
+ }
+ EXPORT_SYMBOL(audit_log_task_info);
  /**
   * audit_log_link_denied - report a link restriction denial
   * @operation: specific link opreation
  void audit_log_link_denied(const char *operation, struct path *link)
  {
        struct audit_buffer *ab;
+       struct audit_names *name;
+       name = kzalloc(sizeof(*name), GFP_NOFS);
+       if (!name)
+               return;
  
+       /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */
        ab = audit_log_start(current->audit_context, GFP_KERNEL,
                             AUDIT_ANOM_LINK);
        if (!ab)
-               return;
-       audit_log_format(ab, "op=%s action=denied", operation);
-       audit_log_format(ab, " pid=%d comm=", current->pid);
-       audit_log_untrustedstring(ab, current->comm);
-       audit_log_d_path(ab, " path=", link);
-       audit_log_format(ab, " dev=");
-       audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id);
-       audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino);
+               goto out;
+       audit_log_format(ab, "op=%s", operation);
+       audit_log_task_info(ab, current);
+       audit_log_format(ab, " res=0");
        audit_log_end(ab);
+       /* Generate AUDIT_PATH record with object. */
+       name->type = AUDIT_TYPE_NORMAL;
+       audit_copy_inode(name, link->dentry, link->dentry->d_inode);
+       audit_log_name(current->audit_context, name, link, 0, NULL);
+ out:
+       kfree(name);
  }
  
  /**
@@@ -1483,7 -1667,7 +1667,7 @@@ void audit_log_end(struct audit_buffer 
                audit_log_lost("rate limit exceeded");
        } else {
                struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
 -              nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
 +              nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
  
                if (audit_pid) {
                        skb_queue_tail(&audit_skb_queue, ab->skb);
diff --combined kernel/audit.h
index 11468d99dad00b9f168071701c35965cf49ae585,45c8325de5bb79fadd1225181bcdef110846fb4c..1c95131ef760c2f45d140efdccfd2d08636b76d7
@@@ -22,6 -22,7 +22,7 @@@
  #include <linux/fs.h>
  #include <linux/audit.h>
  #include <linux/skbuff.h>
+ #include <uapi/linux/mqueue.h>
  
  /* 0 = no checking
     1 = put_count checking
  */
  #define AUDIT_DEBUG 0
  
+ /* AUDIT_NAMES is the number of slots we reserve in the audit_context
+  * for saving names from getname().  If we get more names we will allocate
+  * a name dynamically and also add those to the list anchored by names_list. */
+ #define AUDIT_NAMES   5
  /* At task start time, the audit_state is set in the audit_context using
     a per-task filter.  At syscall entry, the audit_state is augmented by
     the syscall filter. */
@@@ -59,8 -65,161 +65,158 @@@ struct audit_entry 
        struct audit_krule      rule;
  };
  
 -#ifdef CONFIG_AUDIT
 -extern int audit_enabled;
+ struct audit_cap_data {
+       kernel_cap_t            permitted;
+       kernel_cap_t            inheritable;
+       union {
+               unsigned int    fE;             /* effective bit of file cap */
+               kernel_cap_t    effective;      /* effective set of process */
+       };
+ };
+ /* When fs/namei.c:getname() is called, we store the pointer in name and
+  * we don't let putname() free it (instead we free all of the saved
+  * pointers at syscall exit time).
+  *
+  * Further, in fs/namei.c:path_lookup() we store the inode and device.
+  */
+ struct audit_names {
+       struct list_head        list;           /* audit_context->names_list */
+       struct filename         *name;
+       int                     name_len;       /* number of chars to log */
+       bool                    name_put;       /* call __putname()? */
+       unsigned long           ino;
+       dev_t                   dev;
+       umode_t                 mode;
+       kuid_t                  uid;
+       kgid_t                  gid;
+       dev_t                   rdev;
+       u32                     osid;
+       struct audit_cap_data   fcap;
+       unsigned int            fcap_ver;
+       unsigned char           type;           /* record type */
+       /*
+        * This was an allocated audit_names and not from the array of
+        * names allocated in the task audit context.  Thus this name
+        * should be freed on syscall exit.
+        */
+       bool                    should_free;
+ };
+ /* The per-task audit context. */
+ struct audit_context {
+       int                 dummy;      /* must be the first element */
+       int                 in_syscall; /* 1 if task is in a syscall */
+       enum audit_state    state, current_state;
+       unsigned int        serial;     /* serial number for record */
+       int                 major;      /* syscall number */
+       struct timespec     ctime;      /* time of syscall entry */
+       unsigned long       argv[4];    /* syscall arguments */
+       long                return_code;/* syscall return code */
+       u64                 prio;
+       int                 return_valid; /* return code is valid */
+       /*
+        * The names_list is the list of all audit_names collected during this
+        * syscall.  The first AUDIT_NAMES entries in the names_list will
+        * actually be from the preallocated_names array for performance
+        * reasons.  Except during allocation they should never be referenced
+        * through the preallocated_names array and should only be found/used
+        * by running the names_list.
+        */
+       struct audit_names  preallocated_names[AUDIT_NAMES];
+       int                 name_count; /* total records in names_list */
+       struct list_head    names_list; /* struct audit_names->list anchor */
+       char                *filterkey; /* key for rule that triggered record */
+       struct path         pwd;
+       struct audit_aux_data *aux;
+       struct audit_aux_data *aux_pids;
+       struct sockaddr_storage *sockaddr;
+       size_t sockaddr_len;
+                               /* Save things to print about task_struct */
+       pid_t               pid, ppid;
+       kuid_t              uid, euid, suid, fsuid;
+       kgid_t              gid, egid, sgid, fsgid;
+       unsigned long       personality;
+       int                 arch;
+       pid_t               target_pid;
+       kuid_t              target_auid;
+       kuid_t              target_uid;
+       unsigned int        target_sessionid;
+       u32                 target_sid;
+       char                target_comm[TASK_COMM_LEN];
+       struct audit_tree_refs *trees, *first_trees;
+       struct list_head killed_trees;
+       int tree_count;
+       int type;
+       union {
+               struct {
+                       int nargs;
+                       long args[6];
+               } socketcall;
+               struct {
+                       kuid_t                  uid;
+                       kgid_t                  gid;
+                       umode_t                 mode;
+                       u32                     osid;
+                       int                     has_perm;
+                       uid_t                   perm_uid;
+                       gid_t                   perm_gid;
+                       umode_t                 perm_mode;
+                       unsigned long           qbytes;
+               } ipc;
+               struct {
+                       mqd_t                   mqdes;
+                       struct mq_attr          mqstat;
+               } mq_getsetattr;
+               struct {
+                       mqd_t                   mqdes;
+                       int                     sigev_signo;
+               } mq_notify;
+               struct {
+                       mqd_t                   mqdes;
+                       size_t                  msg_len;
+                       unsigned int            msg_prio;
+                       struct timespec         abs_timeout;
+               } mq_sendrecv;
+               struct {
+                       int                     oflag;
+                       umode_t                 mode;
+                       struct mq_attr          attr;
+               } mq_open;
+               struct {
+                       pid_t                   pid;
+                       struct audit_cap_data   cap;
+               } capset;
+               struct {
+                       int                     fd;
+                       int                     flags;
+               } mmap;
+       };
+       int fds[2];
+ #if AUDIT_DEBUG
+       int                 put_count;
+       int                 ino_count;
+ #endif
+ };
  extern int audit_ever_enabled;
  
 -#endif
+ extern void audit_copy_inode(struct audit_names *name,
+                            const struct dentry *dentry,
+                            const struct inode *inode);
+ extern void audit_log_cap(struct audit_buffer *ab, char *prefix,
+                         kernel_cap_t *cap);
+ extern void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name);
+ extern void audit_log_name(struct audit_context *context,
+                          struct audit_names *n, struct path *path,
+                          int record_num, int *call_panic);
  extern int audit_pid;
  
  #define AUDIT_INODE_BUCKETS   32
diff --combined kernel/auditfilter.c
index 267436826c3bc179678a57de72cf08220fa8faca,bc6595fe952e780faf43d6210d5ec9843e5cbe13..83a2970295d19ffdb1bd7417ed2b1b54a815cba1
@@@ -310,121 -310,83 +310,83 @@@ static u32 audit_to_op(u32 op
        return n;
  }
  
- /* Translate struct audit_rule to kernel's rule respresentation.
-  * Exists for backward compatibility with userspace. */
- static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
+ /* check if an audit field is valid */
+ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
  {
-       struct audit_entry *entry;
-       int err = 0;
-       int i;
-       entry = audit_to_entry_common(rule);
-       if (IS_ERR(entry))
-               goto exit_nofree;
-       for (i = 0; i < rule->field_count; i++) {
-               struct audit_field *f = &entry->rule.fields[i];
-               u32 n;
-               n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
-               /* Support for legacy operators where
-                * AUDIT_NEGATE bit signifies != and otherwise assumes == */
-               if (n & AUDIT_NEGATE)
-                       f->op = Audit_not_equal;
-               else if (!n)
-                       f->op = Audit_equal;
-               else
-                       f->op = audit_to_op(n);
-               entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1;
-               f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
-               f->val = rule->values[i];
-               f->uid = INVALID_UID;
-               f->gid = INVALID_GID;
-               err = -EINVAL;
-               if (f->op == Audit_bad)
-                       goto exit_free;
-               switch(f->type) {
-               default:
-                       goto exit_free;
-               case AUDIT_UID:
-               case AUDIT_EUID:
-               case AUDIT_SUID:
-               case AUDIT_FSUID:
-               case AUDIT_LOGINUID:
-                       /* bit ops not implemented for uid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-                       f->uid = make_kuid(current_user_ns(), f->val);
-                       if (!uid_valid(f->uid))
-                               goto exit_free;
-                       break;
-               case AUDIT_GID:
-               case AUDIT_EGID:
-               case AUDIT_SGID:
-               case AUDIT_FSGID:
-                       /* bit ops not implemented for gid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-                       f->gid = make_kgid(current_user_ns(), f->val);
-                       if (!gid_valid(f->gid))
-                               goto exit_free;
-                       break;
-               case AUDIT_PID:
-               case AUDIT_PERS:
-               case AUDIT_MSGTYPE:
-               case AUDIT_PPID:
-               case AUDIT_DEVMAJOR:
-               case AUDIT_DEVMINOR:
-               case AUDIT_EXIT:
-               case AUDIT_SUCCESS:
-                       /* bit ops are only useful on syscall args */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
-                       break;
-               case AUDIT_ARG0:
-               case AUDIT_ARG1:
-               case AUDIT_ARG2:
-               case AUDIT_ARG3:
-                       break;
-               /* arch is only allowed to be = or != */
-               case AUDIT_ARCH:
-                       if (f->op != Audit_not_equal && f->op != Audit_equal)
-                               goto exit_free;
-                       entry->rule.arch_f = f;
-                       break;
-               case AUDIT_PERM:
-                       if (f->val & ~15)
-                               goto exit_free;
-                       break;
-               case AUDIT_FILETYPE:
-                       if (f->val & ~S_IFMT)
-                               goto exit_free;
-                       break;
-               case AUDIT_INODE:
-                       err = audit_to_inode(&entry->rule, f);
-                       if (err)
-                               goto exit_free;
-                       break;
-               }
-       }
-       if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal)
-               entry->rule.inode_f = NULL;
- exit_nofree:
-       return entry;
+       switch(f->type) {
+       case AUDIT_MSGTYPE:
+               if (entry->rule.listnr != AUDIT_FILTER_TYPE &&
+                   entry->rule.listnr != AUDIT_FILTER_USER)
+                       return -EINVAL;
+               break;
+       };
  
- exit_free:
-       audit_free_rule(entry);
-       return ERR_PTR(err);
+       switch(f->type) {
+       default:
+               return -EINVAL;
+       case AUDIT_UID:
+       case AUDIT_EUID:
+       case AUDIT_SUID:
+       case AUDIT_FSUID:
+       case AUDIT_LOGINUID:
+       case AUDIT_OBJ_UID:
+       case AUDIT_GID:
+       case AUDIT_EGID:
+       case AUDIT_SGID:
+       case AUDIT_FSGID:
+       case AUDIT_OBJ_GID:
+       case AUDIT_PID:
+       case AUDIT_PERS:
+       case AUDIT_MSGTYPE:
+       case AUDIT_PPID:
+       case AUDIT_DEVMAJOR:
+       case AUDIT_DEVMINOR:
+       case AUDIT_EXIT:
+       case AUDIT_SUCCESS:
+               /* bit ops are only useful on syscall args */
+               if (f->op == Audit_bitmask || f->op == Audit_bittest)
+                       return -EINVAL;
+               break;
+       case AUDIT_ARG0:
+       case AUDIT_ARG1:
+       case AUDIT_ARG2:
+       case AUDIT_ARG3:
+       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:
+       case AUDIT_WATCH:
+       case AUDIT_DIR:
+       case AUDIT_FILTERKEY:
+               break;
+       case AUDIT_LOGINUID_SET:
+               if ((f->val != 0) && (f->val != 1))
+                       return -EINVAL;
+       /* FALL THROUGH */
+       case AUDIT_ARCH:
+               if (f->op != Audit_not_equal && f->op != Audit_equal)
+                       return -EINVAL;
+               break;
+       case AUDIT_PERM:
+               if (f->val & ~15)
+                       return -EINVAL;
+               break;
+       case AUDIT_FILETYPE:
+               if (f->val & ~S_IFMT)
+                       return -EINVAL;
+               break;
+       case AUDIT_FIELD_COMPARE:
+               if (f->val > AUDIT_MAX_FIELD_COMPARE)
+                       return -EINVAL;
+               break;
+       };
+       return 0;
  }
  
  /* Translate struct audit_rule_data to kernel's rule respresentation. */
@@@ -459,17 -421,25 +421,25 @@@ static struct audit_entry *audit_data_t
                f->gid = INVALID_GID;
                f->lsm_str = NULL;
                f->lsm_rule = NULL;
-               switch(f->type) {
+               /* Support legacy tests for a valid loginuid */
+               if ((f->type == AUDIT_LOGINUID) && (f->val == 4294967295)) {
+                       f->type = AUDIT_LOGINUID_SET;
+                       f->val = 0;
+               }
+               err = audit_field_valid(entry, f);
+               if (err)
+                       goto exit_free;
+               err = -EINVAL;
+               switch (f->type) {
+               case AUDIT_LOGINUID:
                case AUDIT_UID:
                case AUDIT_EUID:
                case AUDIT_SUID:
                case AUDIT_FSUID:
-               case AUDIT_LOGINUID:
                case AUDIT_OBJ_UID:
-                       /* bit ops not implemented for uid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
                        f->uid = make_kuid(current_user_ns(), f->val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
                case AUDIT_SGID:
                case AUDIT_FSGID:
                case AUDIT_OBJ_GID:
-                       /* bit ops not implemented for gid comparisons */
-                       if (f->op == Audit_bitmask || f->op == Audit_bittest)
-                               goto exit_free;
                        f->gid = make_kgid(current_user_ns(), f->val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
-               case AUDIT_PID:
-               case AUDIT_PERS:
-               case AUDIT_MSGTYPE:
-               case AUDIT_PPID:
-               case AUDIT_DEVMAJOR:
-               case AUDIT_DEVMINOR:
-               case AUDIT_EXIT:
-               case AUDIT_SUCCESS:
-               case AUDIT_ARG0:
-               case AUDIT_ARG1:
-               case AUDIT_ARG2:
-               case AUDIT_ARG3:
-                       break;
                case AUDIT_ARCH:
                        entry->rule.arch_f = f;
                        break;
                        entry->rule.buflen += f->val;
                        entry->rule.filterkey = str;
                        break;
-               case AUDIT_PERM:
-                       if (f->val & ~15)
-                               goto exit_free;
-                       break;
-               case AUDIT_FILETYPE:
-                       if (f->val & ~S_IFMT)
-                               goto exit_free;
-                       break;
-               case AUDIT_FIELD_COMPARE:
-                       if (f->val > AUDIT_MAX_FIELD_COMPARE)
-                               goto exit_free;
-                       break;
-               default:
-                       goto exit_free;
                }
        }
  
@@@ -594,10 -533,6 +533,10 @@@ exit_nofree
        return entry;
  
  exit_free:
 +      if (entry->rule.watch)
 +              audit_put_watch(entry->rule.watch); /* matches initial get */
 +      if (entry->rule.tree)
 +              audit_put_tree(entry->rule.tree); /* that's the temporary one */
        audit_free_rule(entry);
        return ERR_PTR(err);
  }
@@@ -613,36 -548,6 +552,6 @@@ static inline size_t audit_pack_string(
        return len;
  }
  
- /* Translate kernel rule respresentation to struct audit_rule.
-  * Exists for backward compatibility with userspace. */
- static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
- {
-       struct audit_rule *rule;
-       int i;
-       rule = kzalloc(sizeof(*rule), GFP_KERNEL);
-       if (unlikely(!rule))
-               return NULL;
-       rule->flags = krule->flags | krule->listnr;
-       rule->action = krule->action;
-       rule->field_count = krule->field_count;
-       for (i = 0; i < rule->field_count; i++) {
-               rule->values[i] = krule->fields[i].val;
-               rule->fields[i] = krule->fields[i].type;
-               if (krule->vers_ops == 1) {
-                       if (krule->fields[i].op == Audit_not_equal)
-                               rule->fields[i] |= AUDIT_NEGATE;
-               } else {
-                       rule->fields[i] |= audit_ops[krule->fields[i].op];
-               }
-       }
-       for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i];
-       return rule;
- }
  /* Translate kernel rule respresentation to struct audit_rule_data. */
  static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
  {
@@@ -1055,35 -960,6 +964,6 @@@ out
        return ret;
  }
  
- /* List rules using struct audit_rule.  Exists for backward
-  * compatibility with userspace. */
- static void audit_list(int pid, int seq, struct sk_buff_head *q)
- {
-       struct sk_buff *skb;
-       struct audit_krule *r;
-       int i;
-       /* This is a blocking read, so use audit_filter_mutex instead of rcu
-        * iterator to sync with list writers. */
-       for (i=0; i<AUDIT_NR_FILTERS; i++) {
-               list_for_each_entry(r, &audit_rules_list[i], list) {
-                       struct audit_rule *rule;
-                       rule = audit_krule_to_rule(r);
-                       if (unlikely(!rule))
-                               break;
-                       skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
-                                        rule, sizeof(*rule));
-                       if (skb)
-                               skb_queue_tail(q, skb);
-                       kfree(rule);
-               }
-       }
-       skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
-       if (skb)
-               skb_queue_tail(q, skb);
- }
  /* List rules using struct audit_rule_data. */
  static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
  {
  }
  
  /* Log rule additions and removals */
- static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid,
-                                 char *action, struct audit_krule *rule,
-                                 int res)
+ static void audit_log_rule_change(char *action, struct audit_krule *rule, int res)
  {
        struct audit_buffer *ab;
+       uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
+       u32 sessionid = audit_get_sessionid(current);
  
        if (!audit_enabled)
                return;
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (!ab)
                return;
-       audit_log_format(ab, "auid=%u ses=%u",
-                        from_kuid(&init_user_ns, loginuid), sessionid);
-       if (sid) {
-               char *ctx = NULL;
-               u32 len;
-               if (security_secid_to_secctx(sid, &ctx, &len))
-                       audit_log_format(ab, " ssid=%u", sid);
-               else {
-                       audit_log_format(ab, " subj=%s", ctx);
-                       security_release_secctx(ctx, len);
-               }
-       }
+       audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid);
+       audit_log_task_context(ab);
        audit_log_format(ab, " op=");
        audit_log_string(ab, action);
        audit_log_key(ab, rule->filterkey);
   * @sessionid: sessionid for netlink audit message
   * @sid: SE Linux Security ID of sender
   */
- int audit_receive_filter(int type, int pid, int seq, void *data,
-                        size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid)
+ int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz)
  {
        struct task_struct *tsk;
        struct audit_netlink_list *dest;
        struct audit_entry *entry;
  
        switch (type) {
-       case AUDIT_LIST:
        case AUDIT_LIST_RULES:
                /* We can't just spew out the rules here because we might fill
                 * the available socket buffer space and deadlock waiting for
                skb_queue_head_init(&dest->q);
  
                mutex_lock(&audit_filter_mutex);
-               if (type == AUDIT_LIST)
-                       audit_list(pid, seq, &dest->q);
-               else
-                       audit_list_rules(pid, seq, &dest->q);
+               audit_list_rules(pid, seq, &dest->q);
                mutex_unlock(&audit_filter_mutex);
  
                tsk = kthread_run(audit_send_list, dest, "audit_send_list");
                        err = PTR_ERR(tsk);
                }
                break;
-       case AUDIT_ADD:
        case AUDIT_ADD_RULE:
-               if (type == AUDIT_ADD)
-                       entry = audit_rule_to_entry(data);
-               else
-                       entry = audit_data_to_entry(data, datasz);
+               entry = audit_data_to_entry(data, datasz);
                if (IS_ERR(entry))
                        return PTR_ERR(entry);
  
                err = audit_add_rule(entry);
-               audit_log_rule_change(loginuid, sessionid, sid, "add rule",
-                                     &entry->rule, !err);
+               audit_log_rule_change("add rule", &entry->rule, !err);
                if (err)
                        audit_free_rule(entry);
                break;
-       case AUDIT_DEL:
        case AUDIT_DEL_RULE:
-               if (type == AUDIT_DEL)
-                       entry = audit_rule_to_entry(data);
-               else
-                       entry = audit_data_to_entry(data, datasz);
+               entry = audit_data_to_entry(data, datasz);
                if (IS_ERR(entry))
                        return PTR_ERR(entry);
  
                err = audit_del_rule(entry);
-               audit_log_rule_change(loginuid, sessionid, sid, "remove rule",
-                                     &entry->rule, !err);
+               audit_log_rule_change("remove rule", &entry->rule, !err);
                audit_free_rule(entry);
                break;
        default:
@@@ -1358,7 -1207,7 +1211,7 @@@ int audit_compare_dname_path(const cha
        return strncmp(p, dname, dlen);
  }
  
- static int audit_filter_user_rules(struct audit_krule *rule,
+ static int audit_filter_user_rules(struct audit_krule *rule, int type,
                                   enum audit_state *state)
  {
        int i;
                        result = audit_uid_comparator(audit_get_loginuid(current),
                                                  f->op, f->uid);
                        break;
+               case AUDIT_LOGINUID_SET:
+                       result = audit_comparator(audit_loginuid_set(current),
+                                                 f->op, f->val);
+                       break;
+               case AUDIT_MSGTYPE:
+                       result = audit_comparator(type, f->op, f->val);
+                       break;
                case AUDIT_SUBJ_USER:
                case AUDIT_SUBJ_ROLE:
                case AUDIT_SUBJ_TYPE:
        return 1;
  }
  
- int audit_filter_user(void)
+ int audit_filter_user(int type)
  {
        enum audit_state state = AUDIT_DISABLED;
        struct audit_entry *e;
  
        rcu_read_lock();
        list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
-               if (audit_filter_user_rules(&e->rule, &state)) {
+               if (audit_filter_user_rules(&e->rule, type, &state)) {
                        if (state == AUDIT_DISABLED)
                                ret = 0;
                        break;
diff --combined net/socket.c
index b416093997dafcf528204be9c99a9986dfe7965d,1bbc37b7a312ab768e3dd124eb50646cf52efa23..6b94633ca61d67e29faa58a7d42410e1ef678193
@@@ -69,6 -69,7 +69,6 @@@
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/mutex.h>
 -#include <linux/wanrouter.h>
  #include <linux/if_bridge.h>
  #include <linux/if_frad.h>
  #include <linux/if_vlan.h>
@@@ -369,15 -370,16 +369,15 @@@ struct file *sock_alloc_file(struct soc
  
        file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
                  &socket_file_ops);
 -      if (unlikely(!file)) {
 +      if (unlikely(IS_ERR(file))) {
                /* drop dentry, keep inode */
                ihold(path.dentry->d_inode);
                path_put(&path);
 -              return ERR_PTR(-ENFILE);
 +              return file;
        }
  
        sock->file = file;
        file->f_flags = O_RDWR | (flags & O_NONBLOCK);
 -      file->f_pos = 0;
        file->private_data = sock;
        return file;
  }
@@@ -600,7 -602,7 +600,7 @@@ void sock_release(struct socket *sock
  }
  EXPORT_SYMBOL(sock_release);
  
 -int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
 +void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
  {
        *tx_flags = 0;
        if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
                *tx_flags |= SKBTX_SW_TSTAMP;
        if (sock_flag(sk, SOCK_WIFI_STATUS))
                *tx_flags |= SKBTX_WIFI_STATUS;
 -      return 0;
  }
  EXPORT_SYMBOL(sock_tx_timestamp);
  
@@@ -681,6 -684,16 +681,6 @@@ int kernel_sendmsg(struct socket *sock
  }
  EXPORT_SYMBOL(kernel_sendmsg);
  
 -static int ktime2ts(ktime_t kt, struct timespec *ts)
 -{
 -      if (kt.tv64) {
 -              *ts = ktime_to_timespec(kt);
 -              return 1;
 -      } else {
 -              return 0;
 -      }
 -}
 -
  /*
   * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
   */
@@@ -713,15 -726,17 +713,15 @@@ void __sock_recv_timestamp(struct msghd
  
  
        memset(ts, 0, sizeof(ts));
 -      if (skb->tstamp.tv64 &&
 -          sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) {
 -              skb_get_timestampns(skb, ts + 0);
 +      if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) &&
 +          ktime_to_timespec_cond(skb->tstamp, ts + 0))
                empty = 0;
 -      }
        if (shhwtstamps) {
                if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) &&
 -                  ktime2ts(shhwtstamps->syststamp, ts + 1))
 +                  ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1))
                        empty = 0;
                if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) &&
 -                  ktime2ts(shhwtstamps->hwtstamp, ts + 2))
 +                  ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2))
                        empty = 0;
        }
        if (!empty)
@@@ -1160,6 -1175,15 +1160,6 @@@ static int sock_mmap(struct file *file
  
  static int sock_close(struct inode *inode, struct file *filp)
  {
 -      /*
 -       *      It was possible the inode is NULL we were
 -       *      closing an unfinished socket.
 -       */
 -
 -      if (!inode) {
 -              printk(KERN_DEBUG "sock_close: NULL inode\n");
 -              return 0;
 -      }
        sock_release(SOCKET_I(inode));
        return 0;
  }
@@@ -2412,7 -2436,7 +2412,7 @@@ static const unsigned char nargs[21] = 
  
  SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
  {
-       unsigned long a[6];
+       unsigned long a[AUDITSC_ARGS];
        unsigned long a0, a1;
        int err;
        unsigned int len;
        if (copy_from_user(a, args, len))
                return -EFAULT;
  
-       audit_socketcall(nargs[call] / sizeof(unsigned long), a);
+       err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
+       if (err)
+               return err;
  
        a0 = a[0];
        a1 = a[1];
@@@ -2814,7 -2840,7 +2816,7 @@@ static int ethtool_ioctl(struct net *ne
        }
  
        ifr = compat_alloc_user_space(buf_size);
 -      rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
 +      rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
  
        if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
                return -EFAULT;
                        offsetof(struct ethtool_rxnfc, fs.ring_cookie));
  
                if (copy_in_user(rxnfc, compat_rxnfc,
 -                               (void *)(&rxnfc->fs.m_ext + 1) -
 -                               (void *)rxnfc) ||
 +                               (void __user *)(&rxnfc->fs.m_ext + 1) -
 +                               (void __user *)rxnfc) ||
                    copy_in_user(&rxnfc->fs.ring_cookie,
                                 &compat_rxnfc->fs.ring_cookie,
 -                               (void *)(&rxnfc->fs.location + 1) -
 -                               (void *)&rxnfc->fs.ring_cookie) ||
 +                               (void __user *)(&rxnfc->fs.location + 1) -
 +                               (void __user *)&rxnfc->fs.ring_cookie) ||
                    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
                                 sizeof(rxnfc->rule_cnt)))
                        return -EFAULT;
  
        if (convert_out) {
                if (copy_in_user(compat_rxnfc, rxnfc,
 -                               (const void *)(&rxnfc->fs.m_ext + 1) -
 -                               (const void *)rxnfc) ||
 +                               (const void __user *)(&rxnfc->fs.m_ext + 1) -
 +                               (const void __user *)rxnfc) ||
                    copy_in_user(&compat_rxnfc->fs.ring_cookie,
                                 &rxnfc->fs.ring_cookie,
 -                               (const void *)(&rxnfc->fs.location + 1) -
 -                               (const void *)&rxnfc->fs.ring_cookie) ||
 +                               (const void __user *)(&rxnfc->fs.location + 1) -
 +                               (const void __user *)&rxnfc->fs.ring_cookie) ||
                    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
                                 sizeof(rxnfc->rule_cnt)))
                        return -EFAULT;