]> Git Repo - linux.git/commitdiff
Merge tag 'audit-pr-20190305' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
authorLinus Torvalds <[email protected]>
Thu, 7 Mar 2019 20:20:11 +0000 (12:20 -0800)
committerLinus Torvalds <[email protected]>
Thu, 7 Mar 2019 20:20:11 +0000 (12:20 -0800)
Pull audit updates from Paul Moore:
 "A lucky 13 audit patches for v5.1.

  Despite the rather large diffstat, most of the changes are from two
  bug fix patches that move code from one Kconfig option to another.

  Beyond that bit of churn, the remaining changes are largely cleanups
  and bug-fixes as we slowly march towards container auditing. It isn't
  all boring though, we do have a couple of new things: file
  capabilities v3 support, and expanded support for filtering on
  filesystems to solve problems with remote filesystems.

  All changes pass the audit-testsuite.  Please merge for v5.1"

* tag 'audit-pr-20190305' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: mark expected switch fall-through
  audit: hide auditsc_get_stamp and audit_serial prototypes
  audit: join tty records to their syscall
  audit: remove audit_context when CONFIG_ AUDIT and not AUDITSYSCALL
  audit: remove unused actx param from audit_rule_match
  audit: ignore fcaps on umount
  audit: clean up AUDITSYSCALL prototypes and stubs
  audit: more filter PATH records keyed on filesystem magic
  audit: add support for fcaps v3
  audit: move loginuid and sessionid from CONFIG_AUDITSYSCALL to CONFIG_AUDIT
  audit: add syscall information to CONFIG_CHANGE records
  audit: hand taken context to audit_kill_trees for syscall logging
  audit: give a clue what CONFIG_CHANGE op was involved

13 files changed:
1  2 
fs/namespace.c
fs/proc/base.c
include/linux/capability.h
include/linux/lsm_hooks.h
include/linux/sched.h
include/linux/security.h
init/init_task.c
security/commoncap.c
security/integrity/ima/ima_policy.c
security/security.c
security/selinux/include/audit.h
security/selinux/ss/services.c
security/smack/smack_lsm.c

diff --combined fs/namespace.c
index c4e83d94840cb296425fdc473aa0131c3e279179,e5de0e372df298218556cc626bbd80e4ee87f1d0..98a8c182af4f04e0752752751d731802b02172a9
@@@ -1640,6 -1640,8 +1640,8 @@@ int ksys_umount(char __user *name, int 
        if (!(flags & UMOUNT_NOFOLLOW))
                lookup_flags |= LOOKUP_FOLLOW;
  
+       lookup_flags |= LOOKUP_NO_EVAL;
        retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
        if (retval)
                goto out;
@@@ -2698,6 -2700,7 +2700,6 @@@ static long exact_copy_from_user(void *
        if (!access_ok(from, n))
                return n;
  
 -      current->kernel_uaccess_faults_ok++;
        while (n) {
                if (__get_user(c, f)) {
                        memset(t, 0, n);
                f++;
                n--;
        }
 -      current->kernel_uaccess_faults_ok--;
        return n;
  }
  
@@@ -2744,7 -2748,7 +2746,7 @@@ void *copy_mount_options(const void __u
  
  char *copy_mount_string(const void __user *data)
  {
 -      return data ? strndup_user(data, PAGE_SIZE) : NULL;
 +      return data ? strndup_user(data, PATH_MAX) : NULL;
  }
  
  /*
diff --combined fs/proc/base.c
index fca9fa5f23d85cd8975b06baade0fe395db23538,a23651ce69601b9dc7d31fd979cee362d17a3e7f..5ab1849971b460bb7d5539f5c7a01a1af1e016c4
@@@ -140,13 -140,9 +140,13 @@@ struct pid_entry 
  #define REG(NAME, MODE, fops)                         \
        NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})
  #define ONE(NAME, MODE, show)                         \
 -      NOD(NAME, (S_IFREG|(MODE)),                     \
 +      NOD(NAME, (S_IFREG|(MODE)),                     \
                NULL, &proc_single_file_operations,     \
                { .proc_show = show } )
 +#define ATTR(LSM, NAME, MODE)                         \
 +      NOD(NAME, (S_IFREG|(MODE)),                     \
 +              NULL, &proc_pid_attr_operations,        \
 +              { .lsm = LSM })
  
  /*
   * Count the number of hardlinks for the pid_entry table, excluding the .
@@@ -460,7 -456,7 +460,7 @@@ static int proc_pid_schedstat(struct se
                              struct pid *pid, struct task_struct *task)
  {
        if (unlikely(!sched_info_on()))
 -              seq_printf(m, "0 0 0\n");
 +              seq_puts(m, "0 0 0\n");
        else
                seq_printf(m, "%llu %llu %lu\n",
                   (unsigned long long)task->se.sum_exec_runtime,
@@@ -1090,6 -1086,10 +1090,6 @@@ static int __set_oom_adj(struct file *f
  
                        task_lock(p);
                        if (!p->vfork_done && process_shares_mm(p, mm)) {
 -                              pr_info("updating oom_score_adj for %d (%s) from %d to %d because it shares mm with %d (%s). Report if this is unexpected.\n",
 -                                              task_pid_nr(p), p->comm,
 -                                              p->signal->oom_score_adj, oom_adj,
 -                                              task_pid_nr(task), task->comm);
                                p->signal->oom_score_adj = oom_adj;
                                if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
                                        p->signal->oom_score_adj_min = (short)oom_adj;
@@@ -1210,7 -1210,7 +1210,7 @@@ static const struct file_operations pro
        .llseek         = default_llseek,
  };
  
- #ifdef CONFIG_AUDITSYSCALL
+ #ifdef CONFIG_AUDIT
  #define TMPBUFLEN 11
  static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
                                  size_t count, loff_t *ppos)
@@@ -2525,7 -2525,7 +2525,7 @@@ static ssize_t proc_pid_attr_read(struc
        if (!task)
                return -ESRCH;
  
 -      length = security_getprocattr(task,
 +      length = security_getprocattr(task, PROC_I(inode)->op.lsm,
                                      (char*)file->f_path.dentry->d_name.name,
                                      &p);
        put_task_struct(task);
@@@ -2574,9 -2574,7 +2574,9 @@@ static ssize_t proc_pid_attr_write(stru
        if (rv < 0)
                goto out_free;
  
 -      rv = security_setprocattr(file->f_path.dentry->d_name.name, page, count);
 +      rv = security_setprocattr(PROC_I(inode)->op.lsm,
 +                                file->f_path.dentry->d_name.name, page,
 +                                count);
        mutex_unlock(&current->signal->cred_guard_mutex);
  out_free:
        kfree(page);
@@@ -2590,53 -2588,13 +2590,53 @@@ static const struct file_operations pro
        .llseek         = generic_file_llseek,
  };
  
 +#define LSM_DIR_OPS(LSM) \
 +static int proc_##LSM##_attr_dir_iterate(struct file *filp, \
 +                           struct dir_context *ctx) \
 +{ \
 +      return proc_pident_readdir(filp, ctx, \
 +                                 LSM##_attr_dir_stuff, \
 +                                 ARRAY_SIZE(LSM##_attr_dir_stuff)); \
 +} \
 +\
 +static const struct file_operations proc_##LSM##_attr_dir_ops = { \
 +      .read           = generic_read_dir, \
 +      .iterate        = proc_##LSM##_attr_dir_iterate, \
 +      .llseek         = default_llseek, \
 +}; \
 +\
 +static struct dentry *proc_##LSM##_attr_dir_lookup(struct inode *dir, \
 +                              struct dentry *dentry, unsigned int flags) \
 +{ \
 +      return proc_pident_lookup(dir, dentry, \
 +                                LSM##_attr_dir_stuff, \
 +                                ARRAY_SIZE(LSM##_attr_dir_stuff)); \
 +} \
 +\
 +static const struct inode_operations proc_##LSM##_attr_dir_inode_ops = { \
 +      .lookup         = proc_##LSM##_attr_dir_lookup, \
 +      .getattr        = pid_getattr, \
 +      .setattr        = proc_setattr, \
 +}
 +
 +#ifdef CONFIG_SECURITY_SMACK
 +static const struct pid_entry smack_attr_dir_stuff[] = {
 +      ATTR("smack", "current",        0666),
 +};
 +LSM_DIR_OPS(smack);
 +#endif
 +
  static const struct pid_entry attr_dir_stuff[] = {
 -      REG("current",    S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 -      REG("prev",       S_IRUGO,         proc_pid_attr_operations),
 -      REG("exec",       S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 -      REG("fscreate",   S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 -      REG("keycreate",  S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 -      REG("sockcreate", S_IRUGO|S_IWUGO, proc_pid_attr_operations),
 +      ATTR(NULL, "current",           0666),
 +      ATTR(NULL, "prev",              0444),
 +      ATTR(NULL, "exec",              0666),
 +      ATTR(NULL, "fscreate",          0666),
 +      ATTR(NULL, "keycreate",         0666),
 +      ATTR(NULL, "sockcreate",        0666),
 +#ifdef CONFIG_SECURITY_SMACK
 +      DIR("smack",                    0555,
 +          proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
 +#endif
  };
  
  static int proc_attr_dir_readdir(struct file *file, struct dir_context *ctx)
@@@ -3044,7 -3002,7 +3044,7 @@@ static const struct pid_entry tgid_base
        ONE("oom_score",  S_IRUGO, proc_oom_score),
        REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
- #ifdef CONFIG_AUDITSYSCALL
+ #ifdef CONFIG_AUDIT
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
        REG("sessionid",  S_IRUGO, proc_sessionid_operations),
  #endif
@@@ -3207,7 -3165,7 +3207,7 @@@ static struct dentry *proc_pid_instanti
        return d_splice_alias(inode, dentry);
  }
  
 -struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 +struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags)
  {
        struct task_struct *task;
        unsigned tgid;
@@@ -3432,7 -3390,7 +3432,7 @@@ static const struct pid_entry tid_base_
        ONE("oom_score", S_IRUGO, proc_oom_score),
        REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
- #ifdef CONFIG_AUDITSYSCALL
+ #ifdef CONFIG_AUDIT
        REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
        REG("sessionid",  S_IRUGO, proc_sessionid_operations),
  #endif
index c3f9a4d558a04453e1d3747a7f4d2bbdfe6c0000,b769330e93807f17cf4eb43cbaa81f4cd2b0babf..ecce0f43c73acde0bfce88d459d838aa12398d9b
@@@ -14,7 -14,7 +14,7 @@@
  #define _LINUX_CAPABILITY_H
  
  #include <uapi/linux/capability.h>
+ #include <linux/uidgid.h>
  
  #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3
  #define _KERNEL_CAPABILITY_U32S    _LINUX_CAPABILITY_U32S_3
@@@ -25,11 -25,12 +25,12 @@@ typedef struct kernel_cap_struct 
        __u32 cap[_KERNEL_CAPABILITY_U32S];
  } kernel_cap_t;
  
- /* exact same as vfs_cap_data but in cpu endian and always filled completely */
+ /* same as vfs_ns_cap_data but in cpu endian and always filled completely */
  struct cpu_vfs_cap_data {
        __u32 magic_etc;
        kernel_cap_t permitted;
        kernel_cap_t inheritable;
+       kuid_t rootid;
  };
  
  #define _USER_CAP_HEADER_SIZE  (sizeof(struct __user_cap_header_struct))
@@@ -209,7 -210,6 +210,7 @@@ extern bool has_ns_capability_noaudit(s
  extern bool capable(int cap);
  extern bool ns_capable(struct user_namespace *ns, int cap);
  extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
 +extern bool ns_capable_setid(struct user_namespace *ns, int cap);
  #else
  static inline bool has_capability(struct task_struct *t, int cap)
  {
@@@ -241,10 -241,6 +242,10 @@@ static inline bool ns_capable_noaudit(s
  {
        return true;
  }
 +static inline bool ns_capable_setid(struct user_namespace *ns, int cap)
 +{
 +      return true;
 +}
  #endif /* CONFIG_MULTIUSER */
  extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
  extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
index 22fc786d723ae4cc36a0588d6e5f320a524b66f1,d0b5c7a0583270e2676d87d83dbb5d274618a1a7..85a301632cf14402d6ba2d331096700b5320f13a
   *    @cred contains the credentials to use.
   *    @ns contains the user namespace we want the capability in
   *    @cap contains the capability <include/linux/capability.h>.
 - *    @audit contains whether to write an audit message or not
 + *    @opts contains options for the capable check <include/linux/security.h>
   *    Return 0 if the capability is granted for @tsk.
   * @syslog:
   *    Check permission before accessing the kernel message ring or changing
   *    @field contains the field which relates to current LSM.
   *    @op contains the operator that will be used for matching.
   *    @rule points to the audit rule that will be checked against.
-  *    @actx points to the audit context associated with the check.
   *    Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
   *
   * @audit_rule_free:
@@@ -1446,10 -1445,8 +1445,10 @@@ union security_list_options 
                        const kernel_cap_t *effective,
                        const kernel_cap_t *inheritable,
                        const kernel_cap_t *permitted);
 -      int (*capable)(const struct cred *cred, struct user_namespace *ns,
 -                      int cap, int audit);
 +      int (*capable)(const struct cred *cred,
 +                      struct user_namespace *ns,
 +                      int cap,
 +                      unsigned int opts);
        int (*quotactl)(int cmds, int type, int id, struct super_block *sb);
        int (*quota_on)(struct dentry *dentry);
        int (*syslog)(int type);
        int (*audit_rule_init)(u32 field, u32 op, char *rulestr,
                                void **lsmrule);
        int (*audit_rule_known)(struct audit_krule *krule);
-       int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule,
-                               struct audit_context *actx);
+       int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule);
        void (*audit_rule_free)(void *lsmrule);
  #endif /* CONFIG_AUDIT */
  
@@@ -2029,18 -2025,6 +2027,18 @@@ struct security_hook_list 
        char                            *lsm;
  } __randomize_layout;
  
 +/*
 + * Security blob size or offset data.
 + */
 +struct lsm_blob_sizes {
 +      int     lbs_cred;
 +      int     lbs_file;
 +      int     lbs_inode;
 +      int     lbs_ipc;
 +      int     lbs_msg_msg;
 +      int     lbs_task;
 +};
 +
  /*
   * Initializing a security_hook_list structure takes
   * up a lot of space in a source file. This macro takes
@@@ -2056,21 -2040,9 +2054,21 @@@ extern char *lsm_names
  extern void security_add_hooks(struct security_hook_list *hooks, int count,
                                char *lsm);
  
 +#define LSM_FLAG_LEGACY_MAJOR BIT(0)
 +#define LSM_FLAG_EXCLUSIVE    BIT(1)
 +
 +enum lsm_order {
 +      LSM_ORDER_FIRST = -1,   /* This is only for capabilities. */
 +      LSM_ORDER_MUTABLE = 0,
 +};
 +
  struct lsm_info {
        const char *name;       /* Required. */
 +      enum lsm_order order;   /* Optional: default is LSM_ORDER_MUTABLE */
 +      unsigned long flags;    /* Optional: flags describing LSM */
 +      int *enabled;           /* Optional: controlled by CONFIG_LSM */
        int (*init)(void);      /* Required. */
 +      struct lsm_blob_sizes *blobs; /* Optional: for blob sharing. */
  };
  
  extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
@@@ -2110,6 -2082,17 +2108,6 @@@ static inline void security_delete_hook
  #define __lsm_ro_after_init   __ro_after_init
  #endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
  
 -extern int __init security_module_enable(const char *module);
 -extern void __init capability_add_hooks(void);
 -#ifdef CONFIG_SECURITY_YAMA
 -extern void __init yama_add_hooks(void);
 -#else
 -static inline void __init yama_add_hooks(void) { }
 -#endif
 -#ifdef CONFIG_SECURITY_LOADPIN
 -void __init loadpin_add_hooks(void);
 -#else
 -static inline void loadpin_add_hooks(void) { };
 -#endif
 +extern int lsm_inode_alloc(struct inode *inode);
  
  #endif /* ! __LINUX_LSM_HOOKS_H */
diff --combined include/linux/sched.h
index f073bd59df32c9214f70df5a9a2190bafdd064b8,765119df759aa19f50cc984854633ab55ad1bf7a..1549584a15388a21b6a3d02938da2cfa50c8ccce
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/seccomp.h>
  #include <linux/nodemask.h>
  #include <linux/rcupdate.h>
 +#include <linux/refcount.h>
  #include <linux/resource.h>
  #include <linux/latencytop.h>
  #include <linux/sched/prio.h>
@@@ -48,7 -47,6 +48,7 @@@ struct pid_namespace
  struct pipe_inode_info;
  struct rcu_node;
  struct reclaim_state;
 +struct capture_control;
  struct robust_list_head;
  struct sched_attr;
  struct sched_param;
@@@ -358,6 -356,12 +358,6 @@@ struct util_est 
   * For cfs_rq, it is the aggregated load_avg of all runnable and
   * blocked sched_entities.
   *
 - * load_avg may also take frequency scaling into account:
 - *
 - *   load_avg = runnable% * scale_load_down(load) * freq%
 - *
 - * where freq% is the CPU frequency normalized to the highest frequency.
 - *
   * [util_avg definition]
   *
   *   util_avg = running% * SCHED_CAPACITY_SCALE
   * a CPU. For cfs_rq, it is the aggregated util_avg of all runnable
   * and blocked sched_entities.
   *
 - * util_avg may also factor frequency scaling and CPU capacity scaling:
 - *
 - *   util_avg = running% * SCHED_CAPACITY_SCALE * freq% * capacity%
 + * load_avg and util_avg don't direcly factor frequency scaling and CPU
 + * capacity scaling. The scaling is done through the rq_clock_pelt that
 + * is used for computing those signals (see update_rq_clock_pelt())
   *
 - * where freq% is the same as above, and capacity% is the CPU capacity
 - * normalized to the greatest capacity (due to uarch differences, etc).
 - *
 - * N.B., the above ratios (runnable%, running%, freq%, and capacity%)
 - * themselves are in the range of [0, 1]. To do fixed point arithmetics,
 - * we therefore scale them to as large a range as necessary. This is for
 - * example reflected by util_avg's SCHED_CAPACITY_SCALE.
 + * N.B., the above ratios (runnable% and running%) themselves are in the
 + * range of [0, 1]. To do fixed point arithmetics, we therefore scale them
 + * to as large a range as necessary. This is for example reflected by
 + * util_avg's SCHED_CAPACITY_SCALE.
   *
   * [Overflow issue]
   *
@@@ -600,7 -607,7 +600,7 @@@ struct task_struct 
        randomized_struct_fields_start
  
        void                            *stack;
 -      atomic_t                        usage;
 +      refcount_t                      usage;
        /* Per task flags (PF_*), defined further below: */
        unsigned int                    flags;
        unsigned int                    ptrace;
        unsigned                        use_memdelay:1;
  #endif
  
 -      /*
 -       * May usercopy functions fault on kernel addresses?
 -       * This is not just a single bit because this can potentially nest.
 -       */
 -      unsigned int                    kernel_uaccess_faults_ok;
 -
        unsigned long                   atomic_flags; /* Flags requiring atomic access. */
  
        struct restart_block            restart_block;
  
        struct callback_head            *task_works;
  
-       struct audit_context            *audit_context;
+ #ifdef CONFIG_AUDIT
  #ifdef CONFIG_AUDITSYSCALL
+       struct audit_context            *audit_context;
+ #endif
        kuid_t                          loginuid;
        unsigned int                    sessionid;
  #endif
  
        struct io_context               *io_context;
  
 +#ifdef CONFIG_COMPACTION
 +      struct capture_control          *capture_control;
 +#endif
        /* Ptrace state: */
        unsigned long                   ptrace_message;
        kernel_siginfo_t                *last_siginfo;
        /* cg_list protected by css_set_lock and tsk->alloc_lock: */
        struct list_head                cg_list;
  #endif
 -#ifdef CONFIG_RESCTRL
 +#ifdef CONFIG_X86_CPU_RESCTRL
        u32                             closid;
        u32                             rmid;
  #endif
  #endif
  #ifdef CONFIG_THREAD_INFO_IN_TASK
        /* A live task holds one reference: */
 -      atomic_t                        stack_refcount;
 +      refcount_t                      stack_refcount;
  #endif
  #ifdef CONFIG_LIVEPATCH
        int patch_state;
@@@ -1396,10 -1408,9 +1398,10 @@@ extern struct pid *cad_pid
  #define PF_RANDOMIZE          0x00400000      /* Randomize virtual address space */
  #define PF_SWAPWRITE          0x00800000      /* Allowed to write to swap */
  #define PF_MEMSTALL           0x01000000      /* Stalled due to lack of memory */
 +#define PF_UMH                        0x02000000      /* I'm an Usermodehelper process */
  #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_MUTEX_TESTER               0x20000000      /* Thread belongs to the rt mutex tester */
 +#define PF_MEMALLOC_NOCMA     0x10000000      /* All allocation request will have _GFP_MOVABLE cleared */
  #define PF_FREEZER_SKIP               0x40000000      /* Freezer should not count it as freezable */
  #define PF_SUSPEND_TASK               0x80000000      /* This thread called freeze_processes() and should not be frozen */
  
@@@ -1449,7 -1460,6 +1451,7 @@@ static inline bool is_percpu_thread(voi
  #define PFA_SPEC_SSB_FORCE_DISABLE    4       /* Speculative Store Bypass force disabled*/
  #define PFA_SPEC_IB_DISABLE           5       /* Indirect branch speculation restricted */
  #define PFA_SPEC_IB_FORCE_DISABLE     6       /* Indirect branch speculation permanently restricted */
 +#define PFA_SPEC_SSB_NOEXEC           7       /* Speculative Store Bypass clear on execve() */
  
  #define TASK_PFA_TEST(name, func)                                     \
        static inline bool task_##func(struct task_struct *p)           \
@@@ -1478,10 -1488,6 +1480,10 @@@ TASK_PFA_TEST(SPEC_SSB_DISABLE, spec_ss
  TASK_PFA_SET(SPEC_SSB_DISABLE, spec_ssb_disable)
  TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable)
  
 +TASK_PFA_TEST(SPEC_SSB_NOEXEC, spec_ssb_noexec)
 +TASK_PFA_SET(SPEC_SSB_NOEXEC, spec_ssb_noexec)
 +TASK_PFA_CLEAR(SPEC_SSB_NOEXEC, spec_ssb_noexec)
 +
  TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
  TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
  
@@@ -1749,9 -1755,9 +1751,9 @@@ static __always_inline bool need_resche
  static inline unsigned int task_cpu(const struct task_struct *p)
  {
  #ifdef CONFIG_THREAD_INFO_IN_TASK
 -      return p->cpu;
 +      return READ_ONCE(p->cpu);
  #else
 -      return task_thread_info(p)->cpu;
 +      return READ_ONCE(task_thread_info(p)->cpu);
  #endif
  }
  
@@@ -1900,14 -1906,6 +1902,14 @@@ static inline void rseq_execve(struct t
  
  #endif
  
 +void __exit_umh(struct task_struct *tsk);
 +
 +static inline void exit_umh(struct task_struct *tsk)
 +{
 +      if (unlikely(tsk->flags & PF_UMH))
 +              __exit_umh(tsk);
 +}
 +
  #ifdef CONFIG_DEBUG_RSEQ
  
  void rseq_syscall(struct pt_regs *regs);
diff --combined include/linux/security.h
index 13537a49ae97258f46065f809443c7dc5f44e59f,e8febec62ffb2bd255847451989d1f39648acb95..2b35a43d11d63b1f8c917150216c51e7991390f3
@@@ -54,12 -54,9 +54,12 @@@ struct xattr
  struct xfrm_sec_ctx;
  struct mm_struct;
  
 +/* Default (no) options for the capable function */
 +#define CAP_OPT_NONE 0x0
  /* If capable should audit the security request */
 -#define SECURITY_CAP_NOAUDIT 0
 -#define SECURITY_CAP_AUDIT 1
 +#define CAP_OPT_NOAUDIT BIT(1)
 +/* If capable is being called by a setid function */
 +#define CAP_OPT_INSETID BIT(2)
  
  /* LSM Agnostic defines for sb_set_mnt_opts */
  #define SECURITY_LSM_NATIVE_LABELS    1
@@@ -75,7 -72,7 +75,7 @@@ enum lsm_event 
  
  /* These functions are in security/commoncap.c */
  extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
 -                     int cap, int audit);
 +                     int cap, unsigned int opts);
  extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz);
  extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
  extern int cap_ptrace_traceme(struct task_struct *parent);
@@@ -210,10 -207,10 +210,10 @@@ int security_capset(struct cred *new, c
                    const kernel_cap_t *effective,
                    const kernel_cap_t *inheritable,
                    const kernel_cap_t *permitted);
 -int security_capable(const struct cred *cred, struct user_namespace *ns,
 -                      int cap);
 -int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
 -                           int cap);
 +int security_capable(const struct cred *cred,
 +                     struct user_namespace *ns,
 +                     int cap,
 +                     unsigned int opts);
  int security_quotactl(int cmds, int type, int id, struct super_block *sb);
  int security_quota_on(struct dentry *dentry);
  int security_syslog(int type);
@@@ -369,10 -366,8 +369,10 @@@ int security_sem_semctl(struct kern_ipc
  int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
                        unsigned nsops, int alter);
  void security_d_instantiate(struct dentry *dentry, struct inode *inode);
 -int security_getprocattr(struct task_struct *p, char *name, char **value);
 -int security_setprocattr(const char *name, void *value, size_t size);
 +int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
 +                       char **value);
 +int security_setprocattr(const char *lsm, const char *name, void *value,
 +                       size_t size);
  int security_netlink_send(struct sock *sk, struct sk_buff *skb);
  int security_ismaclabel(const char *name);
  int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
@@@ -467,11 -462,14 +467,11 @@@ static inline int security_capset(struc
  }
  
  static inline int security_capable(const struct cred *cred,
 -                                 struct user_namespace *ns, int cap)
 +                                 struct user_namespace *ns,
 +                                 int cap,
 +                                 unsigned int opts)
  {
 -      return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT);
 -}
 -
 -static inline int security_capable_noaudit(const struct cred *cred,
 -                                         struct user_namespace *ns, int cap) {
 -      return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
 +      return cap_capable(cred, ns, cap, opts);
  }
  
  static inline int security_quotactl(int cmds, int type, int id,
@@@ -1114,18 -1112,15 +1114,18 @@@ static inline int security_sem_semop(st
        return 0;
  }
  
 -static inline void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 +static inline void security_d_instantiate(struct dentry *dentry,
 +                                        struct inode *inode)
  { }
  
 -static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
 +static inline int security_getprocattr(struct task_struct *p, const char *lsm,
 +                                     char *name, char **value)
  {
        return -EINVAL;
  }
  
 -static inline int security_setprocattr(char *name, void *value, size_t size)
 +static inline int security_setprocattr(const char *lsm, char *name,
 +                                     void *value, size_t size)
  {
        return -EINVAL;
  }
@@@ -1679,8 -1674,7 +1679,7 @@@ static inline int security_key_getsecur
  #ifdef CONFIG_SECURITY
  int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
  int security_audit_rule_known(struct audit_krule *krule);
- int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
-                             struct audit_context *actx);
+ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule);
  void security_audit_rule_free(void *lsmrule);
  
  #else
@@@ -1697,7 -1691,7 +1696,7 @@@ static inline int security_audit_rule_k
  }
  
  static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
-                                  void *lsmrule, struct audit_context *actx)
+                                           void *lsmrule)
  {
        return 0;
  }
diff --combined init/init_task.c
index df0257c5928c17f31823ebf9bf4eee7e287ff383,39c3109acc1aba93bff8436719421ba3571c24b6..c70ef656d0f40cf4fc603d0a7dbb70ba1820af73
@@@ -10,7 -10,6 +10,7 @@@
  #include <linux/fs.h>
  #include <linux/mm.h>
  #include <linux/audit.h>
 +#include <linux/numa.h>
  
  #include <asm/pgtable.h>
  #include <linux/uaccess.h>
@@@ -45,7 -44,7 +45,7 @@@ static struct signal_struct init_signal
  };
  
  static struct sighand_struct init_sighand = {
 -      .count          = ATOMIC_INIT(1),
 +      .count          = REFCOUNT_INIT(1),
        .action         = { { { .sa_handler = SIG_DFL, } }, },
        .siglock        = __SPIN_LOCK_UNLOCKED(init_sighand.siglock),
        .signalfd_wqh   = __WAIT_QUEUE_HEAD_INITIALIZER(init_sighand.signalfd_wqh),
@@@ -62,11 -61,11 +62,11 @@@ struct task_struct init_tas
  = {
  #ifdef CONFIG_THREAD_INFO_IN_TASK
        .thread_info    = INIT_THREAD_INFO(init_task),
 -      .stack_refcount = ATOMIC_INIT(1),
 +      .stack_refcount = REFCOUNT_INIT(1),
  #endif
        .state          = 0,
        .stack          = init_stack,
 -      .usage          = ATOMIC_INIT(2),
 +      .usage          = REFCOUNT_INIT(2),
        .flags          = PF_KTHREAD,
        .prio           = MAX_PRIO - 20,
        .static_prio    = MAX_PRIO - 20,
        .thread_pid     = &init_struct_pid,
        .thread_group   = LIST_HEAD_INIT(init_task.thread_group),
        .thread_node    = LIST_HEAD_INIT(init_signals.thread_head),
- #ifdef CONFIG_AUDITSYSCALL
+ #ifdef CONFIG_AUDIT
        .loginuid       = INVALID_UID,
        .sessionid      = AUDIT_SID_UNSET,
  #endif
        .vtime.state    = VTIME_SYS,
  #endif
  #ifdef CONFIG_NUMA_BALANCING
 -      .numa_preferred_nid = -1,
 +      .numa_preferred_nid = NUMA_NO_NODE,
        .numa_group     = NULL,
        .numa_faults    = NULL,
  #endif
diff --combined security/commoncap.c
index f1d117c3d8ae634eee3d31344eb8bc5e87c95f5f,c097f3568001040e441e9ad12af920c27922b71c..c477fb673701a11b3cb2577be4138ab579d11de3
@@@ -57,7 -57,7 +57,7 @@@ static void warn_setuid_and_fcaps_mixed
   * @cred: The credentials to use
   * @ns:  The user namespace in which we need the capability
   * @cap: The capability to check for
 - * @audit: Whether to write an audit message or not
 + * @opts: Bitmask of options defined in include/linux/security.h
   *
   * Determine whether the nominated task has the specified capability amongst
   * its effective set, returning 0 if it does, -ve if it does not.
@@@ -68,7 -68,7 +68,7 @@@
   * kernel's capable() and has_capability() returns 1 for this case.
   */
  int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
 -              int cap, int audit)
 +              int cap, unsigned int opts)
  {
        struct user_namespace *ns = targ_ns;
  
@@@ -222,11 -222,12 +222,11 @@@ int cap_capget(struct task_struct *targ
   */
  static inline int cap_inh_is_capped(void)
  {
 -
        /* they are so limited unless the current task has the CAP_SETPCAP
         * capability
         */
        if (cap_capable(current_cred(), current_cred()->user_ns,
 -                      CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
 +                      CAP_SETPCAP, CAP_OPT_NONE) == 0)
                return 0;
        return 1;
  }
@@@ -642,6 -643,8 +642,8 @@@ int get_vfs_caps_from_disk(const struc
        cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
        cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK;
  
+       cpu_caps->rootid = rootkuid;
        return 0;
  }
  
@@@ -1207,9 -1210,8 +1209,9 @@@ int cap_task_prctl(int option, unsigne
                    || ((old->securebits & SECURE_ALL_LOCKS & ~arg2))   /*[2]*/
                    || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS))   /*[3]*/
                    || (cap_capable(current_cred(),
 -                                  current_cred()->user_ns, CAP_SETPCAP,
 -                                  SECURITY_CAP_AUDIT) != 0)           /*[4]*/
 +                                  current_cred()->user_ns,
 +                                  CAP_SETPCAP,
 +                                  CAP_OPT_NONE) != 0)                 /*[4]*/
                        /*
                         * [1] no changing of bits that are locked
                         * [2] no unlocking of locks
@@@ -1304,10 -1306,9 +1306,10 @@@ int cap_vm_enough_memory(struct mm_stru
  {
        int cap_sys_admin = 0;
  
 -      if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
 -                      SECURITY_CAP_NOAUDIT) == 0)
 +      if (cap_capable(current_cred(), &init_user_ns,
 +                              CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0)
                cap_sys_admin = 1;
 +
        return cap_sys_admin;
  }
  
@@@ -1326,7 -1327,7 +1328,7 @@@ int cap_mmap_addr(unsigned long addr
  
        if (addr < dac_mmap_min_addr) {
                ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
 -                                SECURITY_CAP_AUDIT);
 +                                CAP_OPT_NONE);
                /* set PF_SUPERPRIV if it turns out we allow the low mmap */
                if (ret == 0)
                        current->flags |= PF_SUPERPRIV;
@@@ -1363,17 -1364,10 +1365,17 @@@ struct security_hook_list capability_ho
        LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
  };
  
 -void __init capability_add_hooks(void)
 +static int __init capability_init(void)
  {
        security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
                                "capability");
 +      return 0;
  }
  
 +DEFINE_LSM(capability) = {
 +      .name = "capability",
 +      .order = LSM_ORDER_FIRST,
 +      .init = capability_init,
 +};
 +
  #endif /* CONFIG_SECURITY */
index 122797023bdb842774a8f23319ad87cae8ef2cf1,26fa9d9723f64e532699558cd298b1a858389fd8..e0cc323f948f465bc2343c3da7a113c0138f045a
@@@ -340,8 -340,7 +340,7 @@@ retry
                        rc = security_filter_rule_match(osid,
                                                        rule->lsm[i].type,
                                                        Audit_equal,
-                                                       rule->lsm[i].rule,
-                                                       NULL);
+                                                       rule->lsm[i].rule);
                        break;
                case LSM_SUBJ_USER:
                case LSM_SUBJ_ROLE:
                        rc = security_filter_rule_match(secid,
                                                        rule->lsm[i].type,
                                                        Audit_equal,
-                                                       rule->lsm[i].rule,
-                                                       NULL);
+                                                       rule->lsm[i].rule);
                default:
                        break;
                }
@@@ -938,12 -936,10 +936,12 @@@ static int ima_parse_rule(char *rule, s
                case Opt_uid_gt:
                case Opt_euid_gt:
                        entry->uid_op = &uid_gt;
 +                      /* fall through */
                case Opt_uid_lt:
                case Opt_euid_lt:
                        if ((token == Opt_uid_lt) || (token == Opt_euid_lt))
                                entry->uid_op = &uid_lt;
 +                      /* fall through */
                case Opt_uid_eq:
                case Opt_euid_eq:
                        uid_token = (token == Opt_uid_eq) ||
                        break;
                case Opt_fowner_gt:
                        entry->fowner_op = &uid_gt;
 +                      /* fall through */
                case Opt_fowner_lt:
                        if (token == Opt_fowner_lt)
                                entry->fowner_op = &uid_lt;
 +                      /* fall through */
                case Opt_fowner_eq:
                        ima_log_string_op(ab, "fowner", args[0].from,
                                          entry->fowner_op);
diff --combined security/security.c
index ed9b8cbf21cf735b43208e945d96b1f065bbd4e9,5f954b179a8e31a605832ba5dd02dc5225d374fe..301b141b9a32b6380df7cae74281910b50cae0f4
  #include <linux/personality.h>
  #include <linux/backing-dev.h>
  #include <linux/string.h>
 +#include <linux/msg.h>
  #include <net/flow.h>
  
  #define MAX_LSM_EVM_XATTR     2
  
 -/* Maximum number of letters for an LSM name string */
 -#define SECURITY_NAME_MAX     10
 +/* How many LSMs were built into the kernel? */
 +#define LSM_COUNT (__end_lsm_info - __start_lsm_info)
  
  struct security_hook_heads security_hook_heads __lsm_ro_after_init;
  static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
  
 +static struct kmem_cache *lsm_file_cache;
 +static struct kmem_cache *lsm_inode_cache;
 +
  char *lsm_names;
 +static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
 +
  /* Boot-time LSM user choice */
 -static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
 -      CONFIG_DEFAULT_SECURITY;
 +static __initdata const char *chosen_lsm_order;
 +static __initdata const char *chosen_major_lsm;
 +
 +static __initconst const char * const builtin_lsm_order = CONFIG_LSM;
 +
 +/* Ordered list of LSMs to initialize. */
 +static __initdata struct lsm_info **ordered_lsms;
 +static __initdata struct lsm_info *exclusive;
  
  static __initdata bool debug;
  #define init_debug(...)                                               \
                        pr_info(__VA_ARGS__);                   \
        } while (0)
  
 -static void __init major_lsm_init(void)
 +static bool __init is_enabled(struct lsm_info *lsm)
  {
 -      struct lsm_info *lsm;
 -      int ret;
 +      if (!lsm->enabled)
 +              return false;
 +
 +      return *lsm->enabled;
 +}
 +
 +/* Mark an LSM's enabled flag. */
 +static int lsm_enabled_true __initdata = 1;
 +static int lsm_enabled_false __initdata = 0;
 +static void __init set_enabled(struct lsm_info *lsm, bool enabled)
 +{
 +      /*
 +       * When an LSM hasn't configured an enable variable, we can use
 +       * a hard-coded location for storing the default enabled state.
 +       */
 +      if (!lsm->enabled) {
 +              if (enabled)
 +                      lsm->enabled = &lsm_enabled_true;
 +              else
 +                      lsm->enabled = &lsm_enabled_false;
 +      } else if (lsm->enabled == &lsm_enabled_true) {
 +              if (!enabled)
 +                      lsm->enabled = &lsm_enabled_false;
 +      } else if (lsm->enabled == &lsm_enabled_false) {
 +              if (enabled)
 +                      lsm->enabled = &lsm_enabled_true;
 +      } else {
 +              *lsm->enabled = enabled;
 +      }
 +}
 +
 +/* Is an LSM already listed in the ordered LSMs list? */
 +static bool __init exists_ordered_lsm(struct lsm_info *lsm)
 +{
 +      struct lsm_info **check;
 +
 +      for (check = ordered_lsms; *check; check++)
 +              if (*check == lsm)
 +                      return true;
 +
 +      return false;
 +}
 +
 +/* Append an LSM to the list of ordered LSMs to initialize. */
 +static int last_lsm __initdata;
 +static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
 +{
 +      /* Ignore duplicate selections. */
 +      if (exists_ordered_lsm(lsm))
 +              return;
 +
 +      if (WARN(last_lsm == LSM_COUNT, "%s: out of LSM slots!?\n", from))
 +              return;
 +
 +      /* Enable this LSM, if it is not already set. */
 +      if (!lsm->enabled)
 +              lsm->enabled = &lsm_enabled_true;
 +      ordered_lsms[last_lsm++] = lsm;
 +
 +      init_debug("%s ordering: %s (%sabled)\n", from, lsm->name,
 +                 is_enabled(lsm) ? "en" : "dis");
 +}
 +
 +/* Is an LSM allowed to be initialized? */
 +static bool __init lsm_allowed(struct lsm_info *lsm)
 +{
 +      /* Skip if the LSM is disabled. */
 +      if (!is_enabled(lsm))
 +              return false;
 +
 +      /* Not allowed if another exclusive LSM already initialized. */
 +      if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) {
 +              init_debug("exclusive disabled: %s\n", lsm->name);
 +              return false;
 +      }
 +
 +      return true;
 +}
 +
 +static void __init lsm_set_blob_size(int *need, int *lbs)
 +{
 +      int offset;
 +
 +      if (*need > 0) {
 +              offset = *lbs;
 +              *lbs += *need;
 +              *need = offset;
 +      }
 +}
 +
 +static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
 +{
 +      if (!needed)
 +              return;
 +
 +      lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
 +      lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file);
 +      /*
 +       * The inode blob gets an rcu_head in addition to
 +       * what the modules might need.
 +       */
 +      if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
 +              blob_sizes.lbs_inode = sizeof(struct rcu_head);
 +      lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
 +      lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
 +      lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
 +      lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
 +}
 +
 +/* Prepare LSM for initialization. */
 +static void __init prepare_lsm(struct lsm_info *lsm)
 +{
 +      int enabled = lsm_allowed(lsm);
 +
 +      /* Record enablement (to handle any following exclusive LSMs). */
 +      set_enabled(lsm, enabled);
 +
 +      /* If enabled, do pre-initialization work. */
 +      if (enabled) {
 +              if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) {
 +                      exclusive = lsm;
 +                      init_debug("exclusive chosen: %s\n", lsm->name);
 +              }
 +
 +              lsm_set_blob_sizes(lsm->blobs);
 +      }
 +}
 +
 +/* Initialize a given LSM, if it is enabled. */
 +static void __init initialize_lsm(struct lsm_info *lsm)
 +{
 +      if (is_enabled(lsm)) {
 +              int ret;
  
 -      for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
                init_debug("initializing %s\n", lsm->name);
                ret = lsm->init();
                WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
        }
  }
  
 +/* Populate ordered LSMs list from comma-separated LSM name list. */
 +static void __init ordered_lsm_parse(const char *order, const char *origin)
 +{
 +      struct lsm_info *lsm;
 +      char *sep, *name, *next;
 +
 +      /* LSM_ORDER_FIRST is always first. */
 +      for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
 +              if (lsm->order == LSM_ORDER_FIRST)
 +                      append_ordered_lsm(lsm, "first");
 +      }
 +
 +      /* Process "security=", if given. */
 +      if (chosen_major_lsm) {
 +              struct lsm_info *major;
 +
 +              /*
 +               * To match the original "security=" behavior, this
 +               * explicitly does NOT fallback to another Legacy Major
 +               * if the selected one was separately disabled: disable
 +               * all non-matching Legacy Major LSMs.
 +               */
 +              for (major = __start_lsm_info; major < __end_lsm_info;
 +                   major++) {
 +                      if ((major->flags & LSM_FLAG_LEGACY_MAJOR) &&
 +                          strcmp(major->name, chosen_major_lsm) != 0) {
 +                              set_enabled(major, false);
 +                              init_debug("security=%s disabled: %s\n",
 +                                         chosen_major_lsm, major->name);
 +                      }
 +              }
 +      }
 +
 +      sep = kstrdup(order, GFP_KERNEL);
 +      next = sep;
 +      /* Walk the list, looking for matching LSMs. */
 +      while ((name = strsep(&next, ",")) != NULL) {
 +              bool found = false;
 +
 +              for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
 +                      if (lsm->order == LSM_ORDER_MUTABLE &&
 +                          strcmp(lsm->name, name) == 0) {
 +                              append_ordered_lsm(lsm, origin);
 +                              found = true;
 +                      }
 +              }
 +
 +              if (!found)
 +                      init_debug("%s ignored: %s\n", origin, name);
 +      }
 +
 +      /* Process "security=", if given. */
 +      if (chosen_major_lsm) {
 +              for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
 +                      if (exists_ordered_lsm(lsm))
 +                              continue;
 +                      if (strcmp(lsm->name, chosen_major_lsm) == 0)
 +                              append_ordered_lsm(lsm, "security=");
 +              }
 +      }
 +
 +      /* Disable all LSMs not in the ordered list. */
 +      for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
 +              if (exists_ordered_lsm(lsm))
 +                      continue;
 +              set_enabled(lsm, false);
 +              init_debug("%s disabled: %s\n", origin, lsm->name);
 +      }
 +
 +      kfree(sep);
 +}
 +
 +static void __init lsm_early_cred(struct cred *cred);
 +static void __init lsm_early_task(struct task_struct *task);
 +
 +static void __init ordered_lsm_init(void)
 +{
 +      struct lsm_info **lsm;
 +
 +      ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),
 +                              GFP_KERNEL);
 +
 +      if (chosen_lsm_order) {
 +              if (chosen_major_lsm) {
 +                      pr_info("security= is ignored because it is superseded by lsm=\n");
 +                      chosen_major_lsm = NULL;
 +              }
 +              ordered_lsm_parse(chosen_lsm_order, "cmdline");
 +      } else
 +              ordered_lsm_parse(builtin_lsm_order, "builtin");
 +
 +      for (lsm = ordered_lsms; *lsm; lsm++)
 +              prepare_lsm(*lsm);
 +
 +      init_debug("cred blob size     = %d\n", blob_sizes.lbs_cred);
 +      init_debug("file blob size     = %d\n", blob_sizes.lbs_file);
 +      init_debug("inode blob size    = %d\n", blob_sizes.lbs_inode);
 +      init_debug("ipc blob size      = %d\n", blob_sizes.lbs_ipc);
 +      init_debug("msg_msg blob size  = %d\n", blob_sizes.lbs_msg_msg);
 +      init_debug("task blob size     = %d\n", blob_sizes.lbs_task);
 +
 +      /*
 +       * Create any kmem_caches needed for blobs
 +       */
 +      if (blob_sizes.lbs_file)
 +              lsm_file_cache = kmem_cache_create("lsm_file_cache",
 +                                                 blob_sizes.lbs_file, 0,
 +                                                 SLAB_PANIC, NULL);
 +      if (blob_sizes.lbs_inode)
 +              lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
 +                                                  blob_sizes.lbs_inode, 0,
 +                                                  SLAB_PANIC, NULL);
 +
 +      lsm_early_cred((struct cred *) current->cred);
 +      lsm_early_task(current);
 +      for (lsm = ordered_lsms; *lsm; lsm++)
 +              initialize_lsm(*lsm);
 +
 +      kfree(ordered_lsms);
 +}
 +
  /**
   * security_init - initializes the security framework
   *
@@@ -343,27 -80,28 +343,27 @@@ int __init security_init(void
             i++)
                INIT_HLIST_HEAD(&list[i]);
  
 -      /*
 -       * Load minor LSMs, with the capability module always first.
 -       */
 -      capability_add_hooks();
 -      yama_add_hooks();
 -      loadpin_add_hooks();
 -
 -      /*
 -       * Load all the remaining security modules.
 -       */
 -      major_lsm_init();
 +      /* Load LSMs in specified order. */
 +      ordered_lsm_init();
  
        return 0;
  }
  
  /* Save user chosen LSM */
 -static int __init choose_lsm(char *str)
 +static int __init choose_major_lsm(char *str)
  {
 -      strncpy(chosen_lsm, str, SECURITY_NAME_MAX);
 +      chosen_major_lsm = str;
        return 1;
  }
 -__setup("security=", choose_lsm);
 +__setup("security=", choose_major_lsm);
 +
 +/* Explicitly choose LSM initialization order. */
 +static int __init choose_lsm_order(char *str)
 +{
 +      chosen_lsm_order = str;
 +      return 1;
 +}
 +__setup("lsm=", choose_lsm_order);
  
  /* Enable LSM order debugging. */
  static int __init enable_debug(char *str)
@@@ -409,6 -147,29 +409,6 @@@ static int lsm_append(char *new, char *
        return 0;
  }
  
 -/**
 - * security_module_enable - Load given security module on boot ?
 - * @module: the name of the module
 - *
 - * Each LSM must pass this method before registering its own operations
 - * to avoid security registration races. This method may also be used
 - * to check if your LSM is currently loaded during kernel initialization.
 - *
 - * Returns:
 - *
 - * true if:
 - *
 - * - The passed LSM is the one chosen by user at boot time,
 - * - or the passed LSM is configured as the default and the user did not
 - *   choose an alternate LSM at boot time.
 - *
 - * Otherwise, return false.
 - */
 -int __init security_module_enable(const char *module)
 -{
 -      return !strcmp(module, chosen_lsm);
 -}
 -
  /**
   * security_add_hooks - Add a modules hooks to the hook lists.
   * @hooks: the hooks to add
@@@ -448,161 -209,6 +448,161 @@@ int unregister_lsm_notifier(struct noti
  }
  EXPORT_SYMBOL(unregister_lsm_notifier);
  
 +/**
 + * lsm_cred_alloc - allocate a composite cred blob
 + * @cred: the cred that needs a blob
 + * @gfp: allocation type
 + *
 + * Allocate the cred blob for all the modules
 + *
 + * Returns 0, or -ENOMEM if memory can't be allocated.
 + */
 +static int lsm_cred_alloc(struct cred *cred, gfp_t gfp)
 +{
 +      if (blob_sizes.lbs_cred == 0) {
 +              cred->security = NULL;
 +              return 0;
 +      }
 +
 +      cred->security = kzalloc(blob_sizes.lbs_cred, gfp);
 +      if (cred->security == NULL)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +/**
 + * lsm_early_cred - during initialization allocate a composite cred blob
 + * @cred: the cred that needs a blob
 + *
 + * Allocate the cred blob for all the modules
 + */
 +static void __init lsm_early_cred(struct cred *cred)
 +{
 +      int rc = lsm_cred_alloc(cred, GFP_KERNEL);
 +
 +      if (rc)
 +              panic("%s: Early cred alloc failed.\n", __func__);
 +}
 +
 +/**
 + * lsm_file_alloc - allocate a composite file blob
 + * @file: the file that needs a blob
 + *
 + * Allocate the file blob for all the modules
 + *
 + * Returns 0, or -ENOMEM if memory can't be allocated.
 + */
 +static int lsm_file_alloc(struct file *file)
 +{
 +      if (!lsm_file_cache) {
 +              file->f_security = NULL;
 +              return 0;
 +      }
 +
 +      file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL);
 +      if (file->f_security == NULL)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +/**
 + * lsm_inode_alloc - allocate a composite inode blob
 + * @inode: the inode that needs a blob
 + *
 + * Allocate the inode blob for all the modules
 + *
 + * Returns 0, or -ENOMEM if memory can't be allocated.
 + */
 +int lsm_inode_alloc(struct inode *inode)
 +{
 +      if (!lsm_inode_cache) {
 +              inode->i_security = NULL;
 +              return 0;
 +      }
 +
 +      inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS);
 +      if (inode->i_security == NULL)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +/**
 + * lsm_task_alloc - allocate a composite task blob
 + * @task: the task that needs a blob
 + *
 + * Allocate the task blob for all the modules
 + *
 + * Returns 0, or -ENOMEM if memory can't be allocated.
 + */
 +static int lsm_task_alloc(struct task_struct *task)
 +{
 +      if (blob_sizes.lbs_task == 0) {
 +              task->security = NULL;
 +              return 0;
 +      }
 +
 +      task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
 +      if (task->security == NULL)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +/**
 + * lsm_ipc_alloc - allocate a composite ipc blob
 + * @kip: the ipc that needs a blob
 + *
 + * Allocate the ipc blob for all the modules
 + *
 + * Returns 0, or -ENOMEM if memory can't be allocated.
 + */
 +static int lsm_ipc_alloc(struct kern_ipc_perm *kip)
 +{
 +      if (blob_sizes.lbs_ipc == 0) {
 +              kip->security = NULL;
 +              return 0;
 +      }
 +
 +      kip->security = kzalloc(blob_sizes.lbs_ipc, GFP_KERNEL);
 +      if (kip->security == NULL)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +/**
 + * lsm_msg_msg_alloc - allocate a composite msg_msg blob
 + * @mp: the msg_msg that needs a blob
 + *
 + * Allocate the ipc blob for all the modules
 + *
 + * Returns 0, or -ENOMEM if memory can't be allocated.
 + */
 +static int lsm_msg_msg_alloc(struct msg_msg *mp)
 +{
 +      if (blob_sizes.lbs_msg_msg == 0) {
 +              mp->security = NULL;
 +              return 0;
 +      }
 +
 +      mp->security = kzalloc(blob_sizes.lbs_msg_msg, GFP_KERNEL);
 +      if (mp->security == NULL)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +/**
 + * lsm_early_task - during initialization allocate a composite task blob
 + * @task: the task that needs a blob
 + *
 + * Allocate the task blob for all the modules
 + */
 +static void __init lsm_early_task(struct task_struct *task)
 +{
 +      int rc = lsm_task_alloc(task);
 +
 +      if (rc)
 +              panic("%s: Early task alloc failed.\n", __func__);
 +}
 +
  /*
   * Hook list operation macros.
   *
@@@ -688,12 -294,16 +688,12 @@@ int security_capset(struct cred *new, c
                                effective, inheritable, permitted);
  }
  
 -int security_capable(const struct cred *cred, struct user_namespace *ns,
 -                   int cap)
 -{
 -      return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT);
 -}
 -
 -int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
 -                           int cap)
 +int security_capable(const struct cred *cred,
 +                   struct user_namespace *ns,
 +                   int cap,
 +                   unsigned int opts)
  {
 -      return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT);
 +      return call_int_hook(capable, 0, cred, ns, cap, opts);
  }
  
  int security_quotactl(int cmds, int type, int id, struct super_block *sb)
@@@ -858,40 -468,14 +858,40 @@@ EXPORT_SYMBOL(security_add_mnt_opt)
  
  int security_inode_alloc(struct inode *inode)
  {
 -      inode->i_security = NULL;
 -      return call_int_hook(inode_alloc_security, 0, inode);
 +      int rc = lsm_inode_alloc(inode);
 +
 +      if (unlikely(rc))
 +              return rc;
 +      rc = call_int_hook(inode_alloc_security, 0, inode);
 +      if (unlikely(rc))
 +              security_inode_free(inode);
 +      return rc;
 +}
 +
 +static void inode_free_by_rcu(struct rcu_head *head)
 +{
 +      /*
 +       * The rcu head is at the start of the inode blob
 +       */
 +      kmem_cache_free(lsm_inode_cache, head);
  }
  
  void security_inode_free(struct inode *inode)
  {
        integrity_inode_free(inode);
        call_void_hook(inode_free_security, inode);
 +      /*
 +       * The inode may still be referenced in a path walk and
 +       * a call to security_inode_permission() can be made
 +       * after inode_free_security() is called. Ideally, the VFS
 +       * wouldn't do this, but fixing that is a much harder
 +       * job. For now, simply free the i_security via RCU, and
 +       * leave the current inode->i_security pointer intact.
 +       * The inode will be freed after the RCU grace period too.
 +       */
 +      if (inode->i_security)
 +              call_rcu((struct rcu_head *)inode->i_security,
 +                              inode_free_by_rcu);
  }
  
  int security_dentry_init_security(struct dentry *dentry, int mode,
@@@ -1321,27 -905,12 +1321,27 @@@ int security_file_permission(struct fil
  
  int security_file_alloc(struct file *file)
  {
 -      return call_int_hook(file_alloc_security, 0, file);
 +      int rc = lsm_file_alloc(file);
 +
 +      if (rc)
 +              return rc;
 +      rc = call_int_hook(file_alloc_security, 0, file);
 +      if (unlikely(rc))
 +              security_file_free(file);
 +      return rc;
  }
  
  void security_file_free(struct file *file)
  {
 +      void *blob;
 +
        call_void_hook(file_free_security, file);
 +
 +      blob = file->f_security;
 +      if (blob) {
 +              file->f_security = NULL;
 +              kmem_cache_free(lsm_file_cache, blob);
 +      }
  }
  
  int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@@ -1443,63 -1012,27 +1443,63 @@@ int security_file_open(struct file *fil
  
  int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
  {
 -      return call_int_hook(task_alloc, 0, task, clone_flags);
 +      int rc = lsm_task_alloc(task);
 +
 +      if (rc)
 +              return rc;
 +      rc = call_int_hook(task_alloc, 0, task, clone_flags);
 +      if (unlikely(rc))
 +              security_task_free(task);
 +      return rc;
  }
  
  void security_task_free(struct task_struct *task)
  {
        call_void_hook(task_free, task);
 +
 +      kfree(task->security);
 +      task->security = NULL;
  }
  
  int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
  {
 -      return call_int_hook(cred_alloc_blank, 0, cred, gfp);
 +      int rc = lsm_cred_alloc(cred, gfp);
 +
 +      if (rc)
 +              return rc;
 +
 +      rc = call_int_hook(cred_alloc_blank, 0, cred, gfp);
 +      if (unlikely(rc))
 +              security_cred_free(cred);
 +      return rc;
  }
  
  void security_cred_free(struct cred *cred)
  {
 +      /*
 +       * There is a failure case in prepare_creds() that
 +       * may result in a call here with ->security being NULL.
 +       */
 +      if (unlikely(cred->security == NULL))
 +              return;
 +
        call_void_hook(cred_free, cred);
 +
 +      kfree(cred->security);
 +      cred->security = NULL;
  }
  
  int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
  {
 -      return call_int_hook(cred_prepare, 0, new, old, gfp);
 +      int rc = lsm_cred_alloc(new, gfp);
 +
 +      if (rc)
 +              return rc;
 +
 +      rc = call_int_hook(cred_prepare, 0, new, old, gfp);
 +      if (unlikely(rc))
 +              security_cred_free(new);
 +      return rc;
  }
  
  void security_transfer_creds(struct cred *new, const struct cred *old)
@@@ -1680,40 -1213,22 +1680,40 @@@ void security_ipc_getsecid(struct kern_
  
  int security_msg_msg_alloc(struct msg_msg *msg)
  {
 -      return call_int_hook(msg_msg_alloc_security, 0, msg);
 +      int rc = lsm_msg_msg_alloc(msg);
 +
 +      if (unlikely(rc))
 +              return rc;
 +      rc = call_int_hook(msg_msg_alloc_security, 0, msg);
 +      if (unlikely(rc))
 +              security_msg_msg_free(msg);
 +      return rc;
  }
  
  void security_msg_msg_free(struct msg_msg *msg)
  {
        call_void_hook(msg_msg_free_security, msg);
 +      kfree(msg->security);
 +      msg->security = NULL;
  }
  
  int security_msg_queue_alloc(struct kern_ipc_perm *msq)
  {
 -      return call_int_hook(msg_queue_alloc_security, 0, msq);
 +      int rc = lsm_ipc_alloc(msq);
 +
 +      if (unlikely(rc))
 +              return rc;
 +      rc = call_int_hook(msg_queue_alloc_security, 0, msq);
 +      if (unlikely(rc))
 +              security_msg_queue_free(msq);
 +      return rc;
  }
  
  void security_msg_queue_free(struct kern_ipc_perm *msq)
  {
        call_void_hook(msg_queue_free_security, msq);
 +      kfree(msq->security);
 +      msq->security = NULL;
  }
  
  int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
@@@ -1740,21 -1255,12 +1740,21 @@@ int security_msg_queue_msgrcv(struct ke
  
  int security_shm_alloc(struct kern_ipc_perm *shp)
  {
 -      return call_int_hook(shm_alloc_security, 0, shp);
 +      int rc = lsm_ipc_alloc(shp);
 +
 +      if (unlikely(rc))
 +              return rc;
 +      rc = call_int_hook(shm_alloc_security, 0, shp);
 +      if (unlikely(rc))
 +              security_shm_free(shp);
 +      return rc;
  }
  
  void security_shm_free(struct kern_ipc_perm *shp)
  {
        call_void_hook(shm_free_security, shp);
 +      kfree(shp->security);
 +      shp->security = NULL;
  }
  
  int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
@@@ -1774,21 -1280,12 +1774,21 @@@ int security_shm_shmat(struct kern_ipc_
  
  int security_sem_alloc(struct kern_ipc_perm *sma)
  {
 -      return call_int_hook(sem_alloc_security, 0, sma);
 +      int rc = lsm_ipc_alloc(sma);
 +
 +      if (unlikely(rc))
 +              return rc;
 +      rc = call_int_hook(sem_alloc_security, 0, sma);
 +      if (unlikely(rc))
 +              security_sem_free(sma);
 +      return rc;
  }
  
  void security_sem_free(struct kern_ipc_perm *sma)
  {
        call_void_hook(sem_free_security, sma);
 +      kfree(sma->security);
 +      sma->security = NULL;
  }
  
  int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
@@@ -1815,30 -1312,14 +1815,30 @@@ void security_d_instantiate(struct dent
  }
  EXPORT_SYMBOL(security_d_instantiate);
  
 -int security_getprocattr(struct task_struct *p, char *name, char **value)
 +int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
 +                              char **value)
  {
 -      return call_int_hook(getprocattr, -EINVAL, p, name, value);
 +      struct security_hook_list *hp;
 +
 +      hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
 +              if (lsm != NULL && strcmp(lsm, hp->lsm))
 +                      continue;
 +              return hp->hook.getprocattr(p, name, value);
 +      }
 +      return -EINVAL;
  }
  
 -int security_setprocattr(const char *name, void *value, size_t size)
 +int security_setprocattr(const char *lsm, const char *name, void *value,
 +                       size_t size)
  {
 -      return call_int_hook(setprocattr, -EINVAL, name, value, size);
 +      struct security_hook_list *hp;
 +
 +      hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
 +              if (lsm != NULL && strcmp(lsm, hp->lsm))
 +                      continue;
 +              return hp->hook.setprocattr(name, value, size);
 +      }
 +      return -EINVAL;
  }
  
  int security_netlink_send(struct sock *sk, struct sk_buff *skb)
@@@ -2302,11 -1783,9 +2302,9 @@@ void security_audit_rule_free(void *lsm
        call_void_hook(audit_rule_free, lsmrule);
  }
  
- int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
-                             struct audit_context *actx)
+ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
  {
-       return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule,
-                               actx);
+       return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
  }
  #endif /* CONFIG_AUDIT */
  
index 36e1d44c0209421e4eefc98c956a5888a322a380,e51a81ffb8c915eabf35404c62eb53d03c76bb09..682e2b5de2a49cb350aff8d56361cb46c4e429fc
@@@ -1,6 -1,9 +1,6 @@@
  /*
   * SELinux support for the Audit LSM hooks
   *
 - * Most of below header was moved from include/linux/selinux.h which
 - * is released under below copyrights:
 - *
   * Author: James Morris <[email protected]>
   *
   * Copyright (C) 2005 Red Hat, Inc., James Morris <[email protected]>
@@@ -43,13 -46,11 +43,11 @@@ void selinux_audit_rule_free(void *rule
   *    @field: the field this rule refers to
   *    @op: the operater the rule uses
   *    @rule: pointer to the audit rule to check against
-  *    @actx: the audit context (can be NULL) associated with the check
   *
   *    Returns 1 if the context id matches the rule, 0 if it does not, and
   *    -errno on failure.
   */
- int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
-                            struct audit_context *actx);
+ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule);
  
  /**
   *    selinux_audit_rule_known - check to see if rule contains selinux fields.
index a0a2aa964111c4e446d29fc3422e9e6c9af5a13c,0b7e33f6aa59e7e946f28e961bde6cde63006475..1269e2be3c2d9ff1b03f21376c7354e2cb354b0c
@@@ -49,6 -49,7 +49,6 @@@
  #include <linux/sched.h>
  #include <linux/audit.h>
  #include <linux/mutex.h>
 -#include <linux/selinux.h>
  #include <linux/flex_array.h>
  #include <linux/vmalloc.h>
  #include <net/netlabel.h>
@@@ -1280,8 -1281,7 +1280,8 @@@ const char *security_get_initial_sid_co
  
  static int security_sid_to_context_core(struct selinux_state *state,
                                        u32 sid, char **scontext,
 -                                      u32 *scontext_len, int force)
 +                                      u32 *scontext_len, int force,
 +                                      int only_invalid)
  {
        struct policydb *policydb;
        struct sidtab *sidtab;
                rc = -EINVAL;
                goto out_unlock;
        }
 -      rc = context_struct_to_string(policydb, context, scontext,
 -                                    scontext_len);
 +      if (only_invalid && !context->len) {
 +              scontext = NULL;
 +              scontext_len = 0;
 +              rc = 0;
 +      } else {
 +              rc = context_struct_to_string(policydb, context, scontext,
 +                                            scontext_len);
 +      }
  out_unlock:
        read_unlock(&state->ss->policy_rwlock);
  out:
@@@ -1355,34 -1349,14 +1355,34 @@@ int security_sid_to_context(struct seli
                            u32 sid, char **scontext, u32 *scontext_len)
  {
        return security_sid_to_context_core(state, sid, scontext,
 -                                          scontext_len, 0);
 +                                          scontext_len, 0, 0);
  }
  
  int security_sid_to_context_force(struct selinux_state *state, u32 sid,
                                  char **scontext, u32 *scontext_len)
  {
        return security_sid_to_context_core(state, sid, scontext,
 -                                          scontext_len, 1);
 +                                          scontext_len, 1, 0);
 +}
 +
 +/**
 + * security_sid_to_context_inval - Obtain a context for a given SID if it
 + *                                 is invalid.
 + * @sid: security identifier, SID
 + * @scontext: security context
 + * @scontext_len: length in bytes
 + *
 + * Write the string representation of the context associated with @sid
 + * into a dynamically allocated string of the correct size, but only if the
 + * context is invalid in the current policy.  Set @scontext to point to
 + * this string (or NULL if the context is valid) and set @scontext_len to
 + * the length of the string (or 0 if the context is valid).
 + */
 +int security_sid_to_context_inval(struct selinux_state *state, u32 sid,
 +                                char **scontext, u32 *scontext_len)
 +{
 +      return security_sid_to_context_core(state, sid, scontext,
 +                                          scontext_len, 1, 1);
  }
  
  /*
@@@ -3402,8 -3376,7 +3402,7 @@@ int selinux_audit_rule_known(struct aud
        return 0;
  }
  
- int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
-                            struct audit_context *actx)
+ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
  {
        struct selinux_state *state = &selinux_state;
        struct context *ctxt;
index 2309c696c6c800e7ebafe6c0e1c5ee95b59e5484,403513df42fcc26f521c21641cb647c0e407713e..424bce4ef21df19718587e544863de168b9a0057
@@@ -139,7 -139,7 +139,7 @@@ static int smk_bu_note(char *note, stru
  static int smk_bu_current(char *note, struct smack_known *oskp,
                          int mode, int rc)
  {
 -      struct task_smack *tsp = current_security();
 +      struct task_smack *tsp = smack_cred(current_cred());
        char acc[SMK_NUM_ACCESS_TYPE + 1];
  
        if (rc <= 0)
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  static int smk_bu_task(struct task_struct *otp, int mode, int rc)
  {
 -      struct task_smack *tsp = current_security();
 +      struct task_smack *tsp = smack_cred(current_cred());
        struct smack_known *smk_task = smk_of_task_struct(otp);
        char acc[SMK_NUM_ACCESS_TYPE + 1];
  
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  static int smk_bu_inode(struct inode *inode, int mode, int rc)
  {
 -      struct task_smack *tsp = current_security();
 -      struct inode_smack *isp = inode->i_security;
 +      struct task_smack *tsp = smack_cred(current_cred());
 +      struct inode_smack *isp = smack_inode(inode);
        char acc[SMK_NUM_ACCESS_TYPE + 1];
  
        if (isp->smk_flags & SMK_INODE_IMPURE)
  #ifdef CONFIG_SECURITY_SMACK_BRINGUP
  static int smk_bu_file(struct file *file, int mode, int rc)
  {
 -      struct task_smack *tsp = current_security();
 +      struct task_smack *tsp = smack_cred(current_cred());
        struct smack_known *sskp = tsp->smk_task;
        struct inode *inode = file_inode(file);
 -      struct inode_smack *isp = inode->i_security;
 +      struct inode_smack *isp = smack_inode(inode);
        char acc[SMK_NUM_ACCESS_TYPE + 1];
  
        if (isp->smk_flags & SMK_INODE_IMPURE)
  static int smk_bu_credfile(const struct cred *cred, struct file *file,
                                int mode, int rc)
  {
 -      struct task_smack *tsp = cred->security;
 +      struct task_smack *tsp = smack_cred(cred);
        struct smack_known *sskp = tsp->smk_task;
        struct inode *inode = file_inode(file);
 -      struct inode_smack *isp = inode->i_security;
 +      struct inode_smack *isp = smack_inode(inode);
        char acc[SMK_NUM_ACCESS_TYPE + 1];
  
        if (isp->smk_flags & SMK_INODE_IMPURE)
@@@ -305,35 -305,50 +305,35 @@@ static struct smack_known *smk_fetch(co
  }
  
  /**
 - * new_inode_smack - allocate an inode security blob
 + * init_inode_smack - initialize an inode security blob
 + * @isp: the blob to initialize
   * @skp: a pointer to the Smack label entry to use in the blob
   *
 - * Returns the new blob or NULL if there's no memory available
   */
 -static struct inode_smack *new_inode_smack(struct smack_known *skp)
 +static void init_inode_smack(struct inode *inode, struct smack_known *skp)
  {
 -      struct inode_smack *isp;
 -
 -      isp = kmem_cache_zalloc(smack_inode_cache, GFP_NOFS);
 -      if (isp == NULL)
 -              return NULL;
 +      struct inode_smack *isp = smack_inode(inode);
  
        isp->smk_inode = skp;
        isp->smk_flags = 0;
        mutex_init(&isp->smk_lock);
 -
 -      return isp;
  }
  
  /**
 - * new_task_smack - allocate a task security blob
 + * init_task_smack - initialize a task security blob
 + * @tsp: blob to initialize
   * @task: a pointer to the Smack label for the running task
   * @forked: a pointer to the Smack label for the forked task
 - * @gfp: type of the memory for the allocation
   *
 - * Returns the new blob or NULL if there's no memory available
   */
 -static struct task_smack *new_task_smack(struct smack_known *task,
 -                                      struct smack_known *forked, gfp_t gfp)
 +static void init_task_smack(struct task_smack *tsp, struct smack_known *task,
 +                                      struct smack_known *forked)
  {
 -      struct task_smack *tsp;
 -
 -      tsp = kzalloc(sizeof(struct task_smack), gfp);
 -      if (tsp == NULL)
 -              return NULL;
 -
        tsp->smk_task = task;
        tsp->smk_forked = forked;
        INIT_LIST_HEAD(&tsp->smk_rules);
        INIT_LIST_HEAD(&tsp->smk_relabel);
        mutex_init(&tsp->smk_rules_lock);
 -
 -      return tsp;
  }
  
  /**
@@@ -433,7 -448,7 +433,7 @@@ static int smk_ptrace_rule_check(struc
  
        rcu_read_lock();
        tracercred = __task_cred(tracer);
 -      tsp = tracercred->security;
 +      tsp = smack_cred(tracercred);
        tracer_known = smk_of_task(tsp);
  
        if ((mode & PTRACE_MODE_ATTACH) &&
@@@ -500,7 -515,7 +500,7 @@@ static int smack_ptrace_traceme(struct 
        int rc;
        struct smack_known *skp;
  
 -      skp = smk_of_task(current_security());
 +      skp = smk_of_task(smack_cred(current_cred()));
  
        rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
        return rc;
@@@ -703,13 -718,6 +703,13 @@@ static int smack_set_mnt_opts(struct su
        if (sp->smk_flags & SMK_SB_INITIALIZED)
                return 0;
  
 +      if (inode->i_security == NULL) {
 +              int rc = lsm_inode_alloc(inode);
 +
 +              if (rc)
 +                      return rc;
 +      }
 +
        if (!smack_privileged(CAP_MAC_ADMIN)) {
                /*
                 * Unprivileged mounts don't get to specify Smack values.
        /*
         * Initialize the root inode.
         */
 -      isp = inode->i_security;
 -      if (isp == NULL) {
 -              isp = new_inode_smack(sp->smk_root);
 -              if (isp == NULL)
 -                      return -ENOMEM;
 -              inode->i_security = isp;
 -      } else
 -              isp->smk_inode = sp->smk_root;
 +      init_inode_smack(inode, sp->smk_root);
  
 -      if (transmute)
 +      if (transmute) {
 +              isp = smack_inode(inode);
                isp->smk_flags |= SMK_INODE_TRANSMUTE;
 +      }
  
        return 0;
  }
@@@ -818,7 -831,7 +818,7 @@@ static int smack_sb_statfs(struct dentr
  static int smack_bprm_set_creds(struct linux_binprm *bprm)
  {
        struct inode *inode = file_inode(bprm->file);
 -      struct task_smack *bsp = bprm->cred->security;
 +      struct task_smack *bsp = smack_cred(bprm->cred);
        struct inode_smack *isp;
        struct superblock_smack *sbsp;
        int rc;
        if (bprm->called_set_creds)
                return 0;
  
 -      isp = inode->i_security;
 +      isp = smack_inode(inode);
        if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
                return 0;
  
@@@ -877,10 -890,48 +877,10 @@@ static int smack_inode_alloc_security(s
  {
        struct smack_known *skp = smk_of_current();
  
 -      inode->i_security = new_inode_smack(skp);
 -      if (inode->i_security == NULL)
 -              return -ENOMEM;
 +      init_inode_smack(inode, skp);
        return 0;
  }
  
 -/**
 - * smack_inode_free_rcu - Free inode_smack blob from cache
 - * @head: the rcu_head for getting inode_smack pointer
 - *
 - *  Call back function called from call_rcu() to free
 - *  the i_security blob pointer in inode
 - */
 -static void smack_inode_free_rcu(struct rcu_head *head)
 -{
 -      struct inode_smack *issp;
 -
 -      issp = container_of(head, struct inode_smack, smk_rcu);
 -      kmem_cache_free(smack_inode_cache, issp);
 -}
 -
 -/**
 - * smack_inode_free_security - free an inode blob using call_rcu()
 - * @inode: the inode with a blob
 - *
 - * Clears the blob pointer in inode using RCU
 - */
 -static void smack_inode_free_security(struct inode *inode)
 -{
 -      struct inode_smack *issp = inode->i_security;
 -
 -      /*
 -       * The inode may still be referenced in a path walk and
 -       * a call to smack_inode_permission() can be made
 -       * after smack_inode_free_security() is called.
 -       * To avoid race condition free the i_security via RCU
 -       * and leave the current inode->i_security pointer intact.
 -       * The inode will be freed after the RCU grace period too.
 -       */
 -      call_rcu(&issp->smk_rcu, smack_inode_free_rcu);
 -}
 -
  /**
   * smack_inode_init_security - copy out the smack from an inode
   * @inode: the newly created inode
@@@ -896,7 -947,7 +896,7 @@@ static int smack_inode_init_security(st
                                     const struct qstr *qstr, const char **name,
                                     void **value, size_t *len)
  {
 -      struct inode_smack *issp = inode->i_security;
 +      struct inode_smack *issp = smack_inode(inode);
        struct smack_known *skp = smk_of_current();
        struct smack_known *isp = smk_of_inode(inode);
        struct smack_known *dsp = smk_of_inode(dir);
@@@ -1234,7 -1285,7 +1234,7 @@@ static void smack_inode_post_setxattr(s
                                      const void *value, size_t size, int flags)
  {
        struct smack_known *skp;
 -      struct inode_smack *isp = d_backing_inode(dentry)->i_security;
 +      struct inode_smack *isp = smack_inode(d_backing_inode(dentry));
  
        if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
                isp->smk_flags |= SMK_INODE_TRANSMUTE;
@@@ -1315,7 -1366,7 +1315,7 @@@ static int smack_inode_removexattr(stru
        if (rc != 0)
                return rc;
  
 -      isp = d_backing_inode(dentry)->i_security;
 +      isp = smack_inode(d_backing_inode(dentry));
        /*
         * Don't do anything special for these.
         *      XATTR_NAME_SMACKIPIN
@@@ -1447,12 -1498,24 +1447,12 @@@ static void smack_inode_getsecid(struc
   */
  static int smack_file_alloc_security(struct file *file)
  {
 -      struct smack_known *skp = smk_of_current();
 +      struct smack_known **blob = smack_file(file);
  
 -      file->f_security = skp;
 +      *blob = smk_of_current();
        return 0;
  }
  
 -/**
 - * smack_file_free_security - clear a file security blob
 - * @file: the object
 - *
 - * The security blob for a file is a pointer to the master
 - * label list, so no memory is freed.
 - */
 -static void smack_file_free_security(struct file *file)
 -{
 -      file->f_security = NULL;
 -}
 -
  /**
   * smack_file_ioctl - Smack check on ioctls
   * @file: the object
@@@ -1590,7 -1653,7 +1590,7 @@@ static int smack_mmap_file(struct file 
        if (unlikely(IS_PRIVATE(file_inode(file))))
                return 0;
  
 -      isp = file_inode(file)->i_security;
 +      isp = smack_inode(file_inode(file));
        if (isp->smk_mmap == NULL)
                return 0;
        sbsp = file_inode(file)->i_sb->s_security;
                return -EACCES;
        mkp = isp->smk_mmap;
  
 -      tsp = current_security();
 +      tsp = smack_cred(current_cred());
        skp = smk_of_current();
        rc = 0;
  
   */
  static void smack_file_set_fowner(struct file *file)
  {
 -      file->f_security = smk_of_current();
 +      struct smack_known **blob = smack_file(file);
 +
 +      *blob = smk_of_current();
  }
  
  /**
  static int smack_file_send_sigiotask(struct task_struct *tsk,
                                     struct fown_struct *fown, int signum)
  {
 +      struct smack_known **blob;
        struct smack_known *skp;
 -      struct smack_known *tkp = smk_of_task(tsk->cred->security);
 +      struct smack_known *tkp = smk_of_task(smack_cred(tsk->cred));
        const struct cred *tcred;
        struct file *file;
        int rc;
        file = container_of(fown, struct file, f_owner);
  
        /* we don't log here as rc can be overriden */
 -      skp = file->f_security;
 +      blob = smack_file(file);
 +      skp = *blob;
        rc = smk_access(skp, tkp, MAY_DELIVER, NULL);
        rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc);
  
@@@ -1752,7 -1811,7 +1752,7 @@@ static int smack_file_receive(struct fi
        if (inode->i_sb->s_magic == SOCKFS_MAGIC) {
                sock = SOCKET_I(inode);
                ssp = sock->sk->sk_security;
 -              tsp = current_security();
 +              tsp = smack_cred(current_cred());
                /*
                 * If the receiving process can't write to the
                 * passed socket or if the passed socket can't
   */
  static int smack_file_open(struct file *file)
  {
 -      struct task_smack *tsp = file->f_cred->security;
 +      struct task_smack *tsp = smack_cred(file->f_cred);
        struct inode *inode = file_inode(file);
        struct smk_audit_info ad;
        int rc;
   */
  static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
  {
 -      struct task_smack *tsp;
 -
 -      tsp = new_task_smack(NULL, NULL, gfp);
 -      if (tsp == NULL)
 -              return -ENOMEM;
 -
 -      cred->security = tsp;
 -
 +      init_task_smack(smack_cred(cred), NULL, NULL);
        return 0;
  }
  
   */
  static void smack_cred_free(struct cred *cred)
  {
 -      struct task_smack *tsp = cred->security;
 +      struct task_smack *tsp = smack_cred(cred);
        struct smack_rule *rp;
        struct list_head *l;
        struct list_head *n;
  
 -      if (tsp == NULL)
 -              return;
 -      cred->security = NULL;
 -
        smk_destroy_label_list(&tsp->smk_relabel);
  
        list_for_each_safe(l, n, &tsp->smk_rules) {
                list_del(&rp->list);
                kfree(rp);
        }
 -      kfree(tsp);
  }
  
  /**
  static int smack_cred_prepare(struct cred *new, const struct cred *old,
                              gfp_t gfp)
  {
 -      struct task_smack *old_tsp = old->security;
 -      struct task_smack *new_tsp;
 +      struct task_smack *old_tsp = smack_cred(old);
 +      struct task_smack *new_tsp = smack_cred(new);
        int rc;
  
 -      new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp);
 -      if (new_tsp == NULL)
 -              return -ENOMEM;
 -
 -      new->security = new_tsp;
 +      init_task_smack(new_tsp, old_tsp->smk_task, old_tsp->smk_task);
  
        rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp);
        if (rc != 0)
  
        rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel,
                                gfp);
 -      if (rc != 0)
 -              return rc;
 -
 -      return 0;
 +      return rc;
  }
  
  /**
   */
  static void smack_cred_transfer(struct cred *new, const struct cred *old)
  {
 -      struct task_smack *old_tsp = old->security;
 -      struct task_smack *new_tsp = new->security;
 +      struct task_smack *old_tsp = smack_cred(old);
 +      struct task_smack *new_tsp = smack_cred(new);
  
        new_tsp->smk_task = old_tsp->smk_task;
        new_tsp->smk_forked = old_tsp->smk_task;
        mutex_init(&new_tsp->smk_rules_lock);
        INIT_LIST_HEAD(&new_tsp->smk_rules);
  
 -
        /* cbs copy rule list */
  }
  
   *
   * Sets the secid to contain a u32 version of the smack label.
   */
 -static void smack_cred_getsecid(const struct cred *c, u32 *secid)
 +static void smack_cred_getsecid(const struct cred *cred, u32 *secid)
  {
        struct smack_known *skp;
  
        rcu_read_lock();
 -      skp = smk_of_task(c->security);
 +      skp = smk_of_task(smack_cred(cred));
        *secid = skp->smk_secid;
        rcu_read_unlock();
  }
   */
  static int smack_kernel_act_as(struct cred *new, u32 secid)
  {
 -      struct task_smack *new_tsp = new->security;
 +      struct task_smack *new_tsp = smack_cred(new);
  
        new_tsp->smk_task = smack_from_secid(secid);
        return 0;
  static int smack_kernel_create_files_as(struct cred *new,
                                        struct inode *inode)
  {
 -      struct inode_smack *isp = inode->i_security;
 -      struct task_smack *tsp = new->security;
 +      struct inode_smack *isp = smack_inode(inode);
 +      struct task_smack *tsp = smack_cred(new);
  
        tsp->smk_forked = isp->smk_inode;
        tsp->smk_task = tsp->smk_forked;
@@@ -2122,7 -2201,7 +2122,7 @@@ static int smack_task_kill(struct task_
         * specific behavior. This is not clean. For one thing
         * we can't take privilege into account.
         */
 -      skp = smk_of_task(cred->security);
 +      skp = smk_of_task(smack_cred(cred));
        rc = smk_access(skp, tkp, MAY_DELIVER, &ad);
        rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc);
        return rc;
   */
  static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
  {
 -      struct inode_smack *isp = inode->i_security;
 +      struct inode_smack *isp = smack_inode(inode);
        struct smack_known *skp = smk_of_task_struct(p);
  
        isp->smk_inode = skp;
@@@ -2600,7 -2679,7 +2600,7 @@@ static int smack_inode_setsecurity(stru
                                   const void *value, size_t size, int flags)
  {
        struct smack_known *skp;
 -      struct inode_smack *nsp = inode->i_security;
 +      struct inode_smack *nsp = smack_inode(inode);
        struct socket_smack *ssp;
        struct socket *sock;
        int rc = 0;
@@@ -2809,12 -2888,23 +2809,12 @@@ static int smack_flags_to_may(int flags
   */
  static int smack_msg_msg_alloc_security(struct msg_msg *msg)
  {
 -      struct smack_known *skp = smk_of_current();
 +      struct smack_known **blob = smack_msg_msg(msg);
  
 -      msg->security = skp;
 +      *blob = smk_of_current();
        return 0;
  }
  
 -/**
 - * smack_msg_msg_free_security - Clear the security blob for msg_msg
 - * @msg: the object
 - *
 - * Clears the blob pointer
 - */
 -static void smack_msg_msg_free_security(struct msg_msg *msg)
 -{
 -      msg->security = NULL;
 -}
 -
  /**
   * smack_of_ipc - the smack pointer for the ipc
   * @isp: the object
   */
  static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp)
  {
 -      return (struct smack_known *)isp->security;
 +      struct smack_known **blob = smack_ipc(isp);
 +
 +      return *blob;
  }
  
  /**
   */
  static int smack_ipc_alloc_security(struct kern_ipc_perm *isp)
  {
 -      struct smack_known *skp = smk_of_current();
 +      struct smack_known **blob = smack_ipc(isp);
  
 -      isp->security = skp;
 +      *blob = smk_of_current();
        return 0;
  }
  
 -/**
 - * smack_ipc_free_security - Clear the security blob for ipc
 - * @isp: the object
 - *
 - * Clears the blob pointer
 - */
 -static void smack_ipc_free_security(struct kern_ipc_perm *isp)
 -{
 -      isp->security = NULL;
 -}
 -
  /**
   * smk_curacc_shm : check if current has access on shm
   * @isp : the object
@@@ -3139,8 -3238,7 +3139,8 @@@ static int smack_msg_queue_msgrcv(struc
   */
  static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
  {
 -      struct smack_known *iskp = ipp->security;
 +      struct smack_known **blob = smack_ipc(ipp);
 +      struct smack_known *iskp = *blob;
        int may = smack_flags_to_may(flag);
        struct smk_audit_info ad;
        int rc;
   */
  static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
  {
 -      struct smack_known *iskp = ipp->security;
 +      struct smack_known **blob = smack_ipc(ipp);
 +      struct smack_known *iskp = *blob;
  
        *secid = iskp->smk_secid;
  }
@@@ -3190,7 -3287,7 +3190,7 @@@ static void smack_d_instantiate(struct 
        if (inode == NULL)
                return;
  
 -      isp = inode->i_security;
 +      isp = smack_inode(inode);
  
        mutex_lock(&isp->smk_lock);
        /*
                 */
                final = &smack_known_star;
                /*
 -               * Fall through.
 -               *
                 * If a smack value has been set we want to use it,
                 * but since tmpfs isn't giving us the opportunity
                 * to set mount options simulate setting the
                 * superblock default.
                 */
 +              /* Fall through */
        default:
                /*
                 * This isn't an understood special case.
@@@ -3430,7 -3528,7 +3430,7 @@@ static int smack_getprocattr(struct tas
   */
  static int smack_setprocattr(const char *name, void *value, size_t size)
  {
 -      struct task_smack *tsp = current_security();
 +      struct task_smack *tsp = smack_cred(current_cred());
        struct cred *new;
        struct smack_known *skp;
        struct smack_known_list_elem *sklep;
        if (new == NULL)
                return -ENOMEM;
  
 -      tsp = new->security;
 +      tsp = smack_cred(new);
        tsp->smk_task = skp;
        /*
         * process can change its label only once
@@@ -4116,7 -4214,7 +4116,7 @@@ static void smack_inet_csk_clone(struc
  static int smack_key_alloc(struct key *key, const struct cred *cred,
                           unsigned long flags)
  {
 -      struct smack_known *skp = smk_of_task(cred->security);
 +      struct smack_known *skp = smk_of_task(smack_cred(cred));
  
        key->security = skp;
        return 0;
@@@ -4147,7 -4245,7 +4147,7 @@@ static int smack_key_permission(key_ref
  {
        struct key *keyp;
        struct smk_audit_info ad;
 -      struct smack_known *tkp = smk_of_task(cred->security);
 +      struct smack_known *tkp = smk_of_task(smack_cred(cred));
        int request = 0;
        int rc;
  
@@@ -4295,13 -4393,11 +4295,11 @@@ static int smack_audit_rule_known(struc
   * @field: audit rule flags given from user-space
   * @op: required testing operator
   * @vrule: smack internal rule presentation
-  * @actx: audit context associated with the check
   *
   * The core Audit hook. It's used to take the decision of
   * whether to audit or not to audit a given object.
   */
- static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
-                                 struct audit_context *actx)
+ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule)
  {
        struct smack_known *skp;
        char *rule = vrule;
@@@ -4422,12 -4518,12 +4420,12 @@@ static int smack_inode_copy_up(struct d
                        return -ENOMEM;
        }
  
 -      tsp = new_creds->security;
 +      tsp = smack_cred(new_creds);
  
        /*
         * Get label from overlay inode and set it in create_sid
         */
 -      isp = d_inode(dentry->d_parent)->i_security;
 +      isp = smack_inode(d_inode(dentry->d_parent));
        skp = isp->smk_inode;
        tsp->smk_task = skp;
        *new = new_creds;
@@@ -4450,8 -4546,8 +4448,8 @@@ static int smack_dentry_create_files_as
                                        const struct cred *old,
                                        struct cred *new)
  {
 -      struct task_smack *otsp = old->security;
 -      struct task_smack *ntsp = new->security;
 +      struct task_smack *otsp = smack_cred(old);
 +      struct task_smack *ntsp = smack_cred(new);
        struct inode_smack *isp;
        int may;
  
        /*
         * the attribute of the containing directory
         */
 -      isp = d_inode(dentry->d_parent)->i_security;
 +      isp = smack_inode(d_inode(dentry->d_parent));
  
        if (isp->smk_flags & SMK_INODE_TRANSMUTE) {
                rcu_read_lock();
        return 0;
  }
  
 +struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
 +      .lbs_cred = sizeof(struct task_smack),
 +      .lbs_file = sizeof(struct smack_known *),
 +      .lbs_inode = sizeof(struct inode_smack),
 +      .lbs_ipc = sizeof(struct smack_known *),
 +      .lbs_msg_msg = sizeof(struct smack_known *),
 +};
 +
  static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
        LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
  
        LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security),
 -      LSM_HOOK_INIT(inode_free_security, smack_inode_free_security),
        LSM_HOOK_INIT(inode_init_security, smack_inode_init_security),
        LSM_HOOK_INIT(inode_link, smack_inode_link),
        LSM_HOOK_INIT(inode_unlink, smack_inode_unlink),
        LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid),
  
        LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
 -      LSM_HOOK_INIT(file_free_security, smack_file_free_security),
        LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
        LSM_HOOK_INIT(file_lock, smack_file_lock),
        LSM_HOOK_INIT(file_fcntl, smack_file_fcntl),
        LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid),
  
        LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security),
 -      LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security),
  
        LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security),
 -      LSM_HOOK_INIT(msg_queue_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate),
        LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl),
        LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd),
        LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv),
  
        LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security),
 -      LSM_HOOK_INIT(shm_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(shm_associate, smack_shm_associate),
        LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl),
        LSM_HOOK_INIT(shm_shmat, smack_shm_shmat),
  
        LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security),
 -      LSM_HOOK_INIT(sem_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(sem_associate, smack_sem_associate),
        LSM_HOOK_INIT(sem_semctl, smack_sem_semctl),
        LSM_HOOK_INIT(sem_semop, smack_sem_semop),
@@@ -4663,23 -4757,23 +4661,23 @@@ static __init void init_smack_known_lis
   */
  static __init int smack_init(void)
  {
 -      struct cred *cred;
 +      struct cred *cred = (struct cred *) current->cred;
        struct task_smack *tsp;
  
 -      if (!security_module_enable("smack"))
 -              return 0;
 -
        smack_inode_cache = KMEM_CACHE(inode_smack, 0);
        if (!smack_inode_cache)
                return -ENOMEM;
  
 -      tsp = new_task_smack(&smack_known_floor, &smack_known_floor,
 -                              GFP_KERNEL);
 -      if (tsp == NULL) {
 -              kmem_cache_destroy(smack_inode_cache);
 -              return -ENOMEM;
 -      }
 +      /*
 +       * Set the security state for the initial task.
 +       */
 +      tsp = smack_cred(cred);
 +      init_task_smack(tsp, &smack_known_floor, &smack_known_floor);
  
 +      /*
 +       * Register with LSM
 +       */
 +      security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack");
        smack_enabled = 1;
  
        pr_info("Smack:  Initializing.\n");
        pr_info("Smack:  IPv6 Netfilter enabled.\n");
  #endif
  
 -      /*
 -       * Set the security state for the initial task.
 -       */
 -      cred = (struct cred *) current->cred;
 -      cred->security = tsp;
 -
        /* initialize the smack_known_list */
        init_smack_known_list();
  
 -      /*
 -       * Register with LSM
 -       */
 -      security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack");
 -
        return 0;
  }
  
   */
  DEFINE_LSM(smack) = {
        .name = "smack",
 +      .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
 +      .blobs = &smack_blob_sizes,
        .init = smack_init,
  };
This page took 0.192171 seconds and 4 git commands to generate.