Merge branch 'work.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-block.git] / security / smack / smack_lsm.c
index 03176f600a877ddb18a9bc1c385570b7cd561dda..5c1613519d5ad3c49696d3cc28ef8bc5edbedf25 100644 (file)
@@ -141,7 +141,7 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
 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)
@@ -162,7 +162,7 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
 #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];
 
@@ -184,8 +184,8 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
 #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)
@@ -214,10 +214,10 @@ static int smk_bu_inode(struct inode *inode, int mode, int rc)
 #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)
@@ -244,10 +244,10 @@ static int smk_bu_file(struct file *file, int mode, int rc)
 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)
@@ -307,50 +307,35 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
 }
 
 /**
- * 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;
 }
 
 /**
@@ -450,7 +435,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,
 
        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) &&
@@ -517,7 +502,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
        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;
@@ -805,6 +790,13 @@ static int smack_set_mnt_opts(struct super_block *sb,
        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.
@@ -869,17 +861,12 @@ static int smack_set_mnt_opts(struct super_block *sb,
        /*
         * 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;
 }
@@ -918,7 +905,7 @@ static int smack_sb_statfs(struct dentry *dentry)
 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;
@@ -926,7 +913,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
        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;
 
@@ -977,48 +964,10 @@ static int smack_inode_alloc_security(struct inode *inode)
 {
        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
@@ -1034,7 +983,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
                                     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);
@@ -1372,7 +1321,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
                                      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;
@@ -1453,7 +1402,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
        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
@@ -1585,24 +1534,12 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid)
  */
 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
@@ -1740,7 +1677,7 @@ static int smack_mmap_file(struct file *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;
@@ -1749,7 +1686,7 @@ static int smack_mmap_file(struct file *file,
                return -EACCES;
        mkp = isp->smk_mmap;
 
-       tsp = current_security();
+       tsp = smack_cred(current_cred());
        skp = smk_of_current();
        rc = 0;
 
@@ -1827,7 +1764,9 @@ static int smack_mmap_file(struct file *file,
  */
 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();
 }
 
 /**
@@ -1844,8 +1783,9 @@ static void smack_file_set_fowner(struct file *file)
 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;
@@ -1857,7 +1797,8 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
        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);
 
@@ -1898,7 +1839,7 @@ static int smack_file_receive(struct file *file)
        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
@@ -1940,7 +1881,7 @@ static int smack_file_receive(struct file *file)
  */
 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;
@@ -1968,14 +1909,7 @@ static int smack_file_open(struct file *file)
  */
 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;
 }
 
@@ -1987,15 +1921,11 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
  */
 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) {
@@ -2003,7 +1933,6 @@ static void smack_cred_free(struct cred *cred)
                list_del(&rp->list);
                kfree(rp);
        }
-       kfree(tsp);
 }
 
 /**
@@ -2017,15 +1946,11 @@ static void smack_cred_free(struct cred *cred)
 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)
@@ -2033,10 +1958,7 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
 
        rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel,
                                gfp);
-       if (rc != 0)
-               return rc;
-
-       return 0;
+       return rc;
 }
 
 /**
@@ -2048,15 +1970,14 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
  */
 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 */
 }
 
@@ -2067,12 +1988,12 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
  *
  * 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();
 }
@@ -2086,7 +2007,7 @@ static void smack_cred_getsecid(const struct cred *c, u32 *secid)
  */
 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;
@@ -2103,8 +2024,8 @@ static int smack_kernel_act_as(struct cred *new, u32 secid)
 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;
@@ -2288,7 +2209,7 @@ static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info,
         * 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;
@@ -2303,7 +2224,7 @@ static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info,
  */
 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;
@@ -2766,7 +2687,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
                                   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;
@@ -2975,23 +2896,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
@@ -3000,7 +2910,9 @@ static void smack_msg_msg_free_security(struct msg_msg *msg)
  */
 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;
 }
 
 /**
@@ -3011,23 +2923,12 @@ static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp)
  */
 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
@@ -3325,7 +3226,8 @@ static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp, struct msg_msg *msg
  */
 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;
@@ -3346,7 +3248,8 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
  */
 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;
 }
@@ -3374,7 +3277,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
        if (inode == NULL)
                return;
 
-       isp = inode->i_security;
+       isp = smack_inode(inode);
 
        mutex_lock(&isp->smk_lock);
        /*
@@ -3477,13 +3380,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 */
                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.
@@ -3615,7 +3517,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
  */
 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;
@@ -3656,7 +3558,7 @@ static int smack_setprocattr(const char *name, void *value, size_t size)
        if (new == NULL)
                return -ENOMEM;
 
-       tsp = new->security;
+       tsp = smack_cred(new);
        tsp->smk_task = skp;
        /*
         * process can change its label only once
@@ -4301,7 +4203,7 @@ static void smack_inet_csk_clone(struct sock *sk,
 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;
@@ -4332,7 +4234,7 @@ static int smack_key_permission(key_ref_t 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;
 
@@ -4480,13 +4382,11 @@ static int smack_audit_rule_known(struct audit_krule *krule)
  * @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;
@@ -4607,12 +4507,12 @@ static int smack_inode_copy_up(struct dentry *dentry, struct cred **new)
                        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;
@@ -4635,8 +4535,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
                                        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;
 
@@ -4649,7 +4549,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
        /*
         * 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();
@@ -4669,6 +4569,14 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
        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),
@@ -4687,7 +4595,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        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),
@@ -4706,7 +4613,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        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),
@@ -4742,23 +4648,19 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        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),
@@ -4849,23 +4751,23 @@ static __init void init_smack_known_list(void)
  */
 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");
@@ -4879,20 +4781,9 @@ static __init int smack_init(void)
        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;
 }
 
@@ -4902,5 +4793,7 @@ static __init int smack_init(void)
  */
 DEFINE_LSM(smack) = {
        .name = "smack",
+       .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
+       .blobs = &smack_blob_sizes,
        .init = smack_init,
 };