]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - security/smack/smack_lsm.c
smack: use GFP_NOFS while holding inode_smack::smk_lock
[mirror_ubuntu-bionic-kernel.git] / security / smack / smack_lsm.c
index 14cc7940b36d2d0a960a3fff9a87a649a50dbc64..80ef8813ba9d7e604168122820b135a7206ea613 100644 (file)
@@ -121,7 +121,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)
@@ -142,7 +142,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];
 
@@ -164,8 +164,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)
@@ -194,10 +194,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)
@@ -224,10 +224,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)
@@ -269,7 +269,7 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
        if (!(ip->i_opflags & IOP_XATTR))
                return ERR_PTR(-EOPNOTSUPP);
 
-       buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
+       buffer = kzalloc(SMK_LONGLABEL, GFP_NOFS);
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -287,50 +287,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;
 }
 
 /**
@@ -428,7 +413,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,
        }
 
        rcu_read_lock();
-       tsp = __task_cred(tracer)->security;
+       tsp = smack_cred(__task_cred(tracer));
        tracer_known = smk_of_task(tsp);
 
        if ((mode & PTRACE_MODE_ATTACH) &&
@@ -495,7 +480,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;
@@ -534,12 +519,7 @@ static int smack_syslog(int typefrom_file)
  */
 static int smack_sb_alloc_security(struct super_block *sb)
 {
-       struct superblock_smack *sbsp;
-
-       sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL);
-
-       if (sbsp == NULL)
-               return -ENOMEM;
+       struct superblock_smack *sbsp = smack_superblock(sb);
 
        sbsp->smk_root = &smack_known_floor;
        sbsp->smk_default = &smack_known_floor;
@@ -548,22 +528,10 @@ static int smack_sb_alloc_security(struct super_block *sb)
        /*
         * SMK_SB_INITIALIZED will be zero from kzalloc.
         */
-       sb->s_security = sbsp;
 
        return 0;
 }
 
-/**
- * smack_sb_free_security - free a superblock blob
- * @sb: the superblock getting the blob
- *
- */
-static void smack_sb_free_security(struct super_block *sb)
-{
-       kfree(sb->s_security);
-       sb->s_security = NULL;
-}
-
 /**
  * smack_sb_copy_data - copy mount options data for processing
  * @orig: where to start
@@ -754,7 +722,7 @@ static int smack_set_mnt_opts(struct super_block *sb,
 {
        struct dentry *root = sb->s_root;
        struct inode *inode = d_backing_inode(root);
-       struct superblock_smack *sp = sb->s_security;
+       struct superblock_smack *sp = smack_superblock(sb);
        struct inode_smack *isp;
        struct smack_known *skp;
        int i;
@@ -832,17 +800,13 @@ 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;
+       lsm_early_inode(inode);
+       init_inode_smack(inode, sp->smk_root);
 
-       if (transmute)
+       if (transmute) {
+               isp = smack_inode(inode);
                isp->smk_flags |= SMK_INODE_TRANSMUTE;
+       }
 
        return 0;
 }
@@ -887,7 +851,7 @@ out_err:
  */
 static int smack_sb_statfs(struct dentry *dentry)
 {
-       struct superblock_smack *sbp = dentry->d_sb->s_security;
+       struct superblock_smack *sbp = smack_superblock(dentry->d_sb);
        int rc;
        struct smk_audit_info ad;
 
@@ -912,7 +876,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;
@@ -920,11 +884,11 @@ 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;
 
-       sbsp = inode->i_sb->s_security;
+       sbsp = smack_superblock(inode->i_sb);
        if ((sbsp->smk_flags & SMK_SB_UNTRUSTED) &&
            isp->smk_task != sbsp->smk_root)
                return 0;
@@ -944,7 +908,8 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
 
                if (rc != 0)
                        return rc;
-       } else if (bprm->unsafe)
+       }
+       if (bprm->unsafe & ~LSM_UNSAFE_PTRACE)
                return -EPERM;
 
        bsp->smk_task = isp->smk_task;
@@ -971,48 +936,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
@@ -1028,7 +955,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);
@@ -1213,7 +1140,7 @@ static int smack_inode_rename(struct inode *old_inode,
  */
 static int smack_inode_permission(struct inode *inode, int mask)
 {
-       struct superblock_smack *sbsp = inode->i_sb->s_security;
+       struct superblock_smack *sbsp = smack_superblock(inode->i_sb);
        struct smk_audit_info ad;
        int no_block = mask & MAY_NOT_BLOCK;
        int rc;
@@ -1366,7 +1293,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;
@@ -1447,7 +1374,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
@@ -1455,7 +1382,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
         */
        if (strcmp(name, XATTR_NAME_SMACK) == 0) {
                struct super_block *sbp = dentry->d_sb;
-               struct superblock_smack *sbsp = sbp->s_security;
+               struct superblock_smack *sbsp = smack_superblock(sbp);
 
                isp->smk_inode = sbsp->smk_default;
        } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0)
@@ -1501,7 +1428,7 @@ static int smack_inode_getsecurity(struct inode *inode,
                if (sock == NULL || sock->sk == NULL)
                        return -EOPNOTSUPP;
 
-               ssp = sock->sk->sk_security;
+               ssp = smack_sock(sock->sk);
 
                if (strcmp(name, XATTR_SMACK_IPIN) == 0)
                        isp = ssp->smk_in;
@@ -1545,7 +1472,7 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer,
  */
 static void smack_inode_getsecid(struct inode *inode, u32 *secid)
 {
-       struct inode_smack *isp = inode->i_security;
+       struct inode_smack *isp = smack_inode(inode);
 
        *secid = isp->smk_inode->smk_secid;
 }
@@ -1579,24 +1506,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
@@ -1734,16 +1649,16 @@ 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;
+       sbsp = smack_superblock(file_inode(file)->i_sb);
        if (sbsp->smk_flags & SMK_SB_UNTRUSTED &&
            isp->smk_mmap != sbsp->smk_root)
                return -EACCES;
        mkp = isp->smk_mmap;
 
-       tsp = current_security();
+       tsp = smack_cred(current_cred());
        skp = smk_of_current();
        rc = 0;
 
@@ -1821,7 +1736,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();
 }
 
 /**
@@ -1838,8 +1755,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));
        struct file *file;
        int rc;
        struct smk_audit_info ad;
@@ -1850,7 +1768,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);
        if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
@@ -1886,8 +1805,8 @@ 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();
+               ssp = smack_sock(sock->sk);
+               tsp = smack_cred(current_cred());
                /*
                 * If the receiving process can't write to the
                 * passed socket or if the passed socket can't
@@ -1929,7 +1848,7 @@ static int smack_file_receive(struct file *file)
  */
 static int smack_file_open(struct file *file, const struct cred *cred)
 {
-       struct task_smack *tsp = cred->security;
+       struct task_smack *tsp = smack_cred(cred);
        struct inode *inode = file_inode(file);
        struct smk_audit_info ad;
        int rc;
@@ -1957,14 +1876,7 @@ static int smack_file_open(struct file *file, const struct cred *cred)
  */
 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;
 }
 
@@ -1976,15 +1888,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) {
@@ -1992,7 +1900,6 @@ static void smack_cred_free(struct cred *cred)
                list_del(&rp->list);
                kfree(rp);
        }
-       kfree(tsp);
 }
 
 /**
@@ -2006,15 +1913,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)
@@ -2022,10 +1925,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;
 }
 
 /**
@@ -2037,15 +1937,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 */
 }
 
@@ -2058,7 +1957,7 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
  */
 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;
@@ -2075,8 +1974,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;
@@ -2277,10 +2176,11 @@ static int smack_task_kill(struct task_struct *p, struct 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;
+       isp->smk_flags |= SMK_INODE_INSTANT;
 }
 
 /*
@@ -2300,11 +2200,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
 static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
 {
        struct smack_known *skp = smk_of_current();
-       struct socket_smack *ssp;
-
-       ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
-       if (ssp == NULL)
-               return -ENOMEM;
+       struct socket_smack *ssp = smack_sock(sk);
 
        /*
         * Sockets created by kernel threads receive web label.
@@ -2318,11 +2214,10 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
        }
        ssp->smk_packet = NULL;
 
-       sk->sk_security = ssp;
-
        return 0;
 }
 
+#ifdef SMACK_IPV6_PORT_LABELING
 /**
  * smack_sk_free_security - Free a socket blob
  * @sk: the socket
@@ -2331,7 +2226,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
  */
 static void smack_sk_free_security(struct sock *sk)
 {
-#ifdef SMACK_IPV6_PORT_LABELING
        struct smk_port_label *spp;
 
        if (sk->sk_family == PF_INET6) {
@@ -2344,9 +2238,8 @@ static void smack_sk_free_security(struct sock *sk)
                }
                rcu_read_unlock();
        }
-#endif
-       kfree(sk->sk_security);
 }
+#endif
 
 /**
 * smack_ipv4host_label - check host based restrictions
@@ -2464,7 +2357,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
 static int smack_netlabel(struct sock *sk, int labeled)
 {
        struct smack_known *skp;
-       struct socket_smack *ssp = sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sk);
        int rc = 0;
 
        /*
@@ -2509,7 +2402,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
        int rc;
        int sk_lbl;
        struct smack_known *hkp;
-       struct socket_smack *ssp = sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sk);
        struct smk_audit_info ad;
 
        rcu_read_lock();
@@ -2585,7 +2478,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
 {
        struct sock *sk = sock->sk;
        struct sockaddr_in6 *addr6;
-       struct socket_smack *ssp = sock->sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sock->sk);
        struct smk_port_label *spp;
        unsigned short port = 0;
 
@@ -2672,7 +2565,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
                                int act)
 {
        struct smk_port_label *spp;
-       struct socket_smack *ssp = sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sk);
        struct smack_known *skp = NULL;
        unsigned short port;
        struct smack_known *object;
@@ -2739,7 +2632,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;
@@ -2766,7 +2659,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
        if (sock == NULL || sock->sk == NULL)
                return -EOPNOTSUPP;
 
-       ssp = sock->sk->sk_security;
+       ssp = smack_sock(sock->sk);
 
        if (strcmp(name, XATTR_SMACK_IPIN) == 0)
                ssp->smk_in = skp;
@@ -2814,7 +2707,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
         * Sockets created by kernel threads receive web label.
         */
        if (unlikely(current->flags & PF_KTHREAD)) {
-               ssp = sock->sk->sk_security;
+               ssp = smack_sock(sock->sk);
                ssp->smk_in = &smack_known_web;
                ssp->smk_out = &smack_known_web;
        }
@@ -2923,34 +2816,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_shm - the smack pointer for the shm
- * @shp: the object
- *
- * Returns a pointer to the smack value
- */
-static struct smack_known *smack_of_shm(struct shmid_kernel *shp)
-{
-       return (struct smack_known *)shp->shm_perm.security;
-}
-
 /**
  * smack_shm_alloc_security - Set the security blob for shm
  * @shp: the object
@@ -2959,26 +2830,12 @@ static struct smack_known *smack_of_shm(struct shmid_kernel *shp)
  */
 static int smack_shm_alloc_security(struct shmid_kernel *shp)
 {
-       struct kern_ipc_perm *isp = &shp->shm_perm;
-       struct smack_known *skp = smk_of_current();
+       struct smack_known **blob = smack_ipc(&shp->shm_perm);
 
-       isp->security = skp;
+       *blob = smk_of_current();
        return 0;
 }
 
-/**
- * smack_shm_free_security - Clear the security blob for shm
- * @shp: the object
- *
- * Clears the blob pointer
- */
-static void smack_shm_free_security(struct shmid_kernel *shp)
-{
-       struct kern_ipc_perm *isp = &shp->shm_perm;
-
-       isp->security = NULL;
-}
-
 /**
  * smk_curacc_shm : check if current has access on shm
  * @shp : the object
@@ -2988,7 +2845,8 @@ static void smack_shm_free_security(struct shmid_kernel *shp)
  */
 static int smk_curacc_shm(struct shmid_kernel *shp, int access)
 {
-       struct smack_known *ssp = smack_of_shm(shp);
+       struct smack_known **blob = smack_ipc(&shp->shm_perm);
+       struct smack_known *ssp = *blob;
        struct smk_audit_info ad;
        int rc;
 
@@ -3067,17 +2925,6 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
        return smk_curacc_shm(shp, may);
 }
 
-/**
- * smack_of_sem - the smack pointer for the sem
- * @sma: the object
- *
- * Returns a pointer to the smack value
- */
-static struct smack_known *smack_of_sem(struct sem_array *sma)
-{
-       return (struct smack_known *)sma->sem_perm.security;
-}
-
 /**
  * smack_sem_alloc_security - Set the security blob for sem
  * @sma: the object
@@ -3086,26 +2933,12 @@ static struct smack_known *smack_of_sem(struct sem_array *sma)
  */
 static int smack_sem_alloc_security(struct sem_array *sma)
 {
-       struct kern_ipc_perm *isp = &sma->sem_perm;
-       struct smack_known *skp = smk_of_current();
+       struct smack_known **blob = smack_ipc(&sma->sem_perm);
 
-       isp->security = skp;
+       *blob = smk_of_current();
        return 0;
 }
 
-/**
- * smack_sem_free_security - Clear the security blob for sem
- * @sma: the object
- *
- * Clears the blob pointer
- */
-static void smack_sem_free_security(struct sem_array *sma)
-{
-       struct kern_ipc_perm *isp = &sma->sem_perm;
-
-       isp->security = NULL;
-}
-
 /**
  * smk_curacc_sem : check if current has access on sem
  * @sma : the object
@@ -3115,7 +2948,8 @@ static void smack_sem_free_security(struct sem_array *sma)
  */
 static int smk_curacc_sem(struct sem_array *sma, int access)
 {
-       struct smack_known *ssp = smack_of_sem(sma);
+       struct smack_known **blob = smack_ipc(&sma->sem_perm);
+       struct smack_known *ssp = *blob;
        struct smk_audit_info ad;
        int rc;
 
@@ -3201,44 +3035,19 @@ static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
 }
 
 /**
- * smack_msg_alloc_security - Set the security blob for msg
+ * smack_msg_queue_alloc_security - Set the security blob for msg
  * @msq: the object
  *
  * Returns 0
  */
 static int smack_msg_queue_alloc_security(struct msg_queue *msq)
 {
-       struct kern_ipc_perm *kisp = &msq->q_perm;
-       struct smack_known *skp = smk_of_current();
+       struct smack_known **blob = smack_ipc(&msq->q_perm);
 
-       kisp->security = skp;
+       *blob = smk_of_current();
        return 0;
 }
 
-/**
- * smack_msg_free_security - Clear the security blob for msg
- * @msq: the object
- *
- * Clears the blob pointer
- */
-static void smack_msg_queue_free_security(struct msg_queue *msq)
-{
-       struct kern_ipc_perm *kisp = &msq->q_perm;
-
-       kisp->security = NULL;
-}
-
-/**
- * smack_of_msq - the smack pointer for the msq
- * @msq: the object
- *
- * Returns a pointer to the smack label entry
- */
-static struct smack_known *smack_of_msq(struct msg_queue *msq)
-{
-       return (struct smack_known *)msq->q_perm.security;
-}
-
 /**
  * smk_curacc_msq : helper to check if current has access on msq
  * @msq : the msq
@@ -3248,7 +3057,8 @@ static struct smack_known *smack_of_msq(struct msg_queue *msq)
  */
 static int smk_curacc_msq(struct msg_queue *msq, int access)
 {
-       struct smack_known *msp = smack_of_msq(msq);
+       struct smack_known **blob = smack_ipc(&msq->q_perm);
+       struct smack_known *msp = *blob;
        struct smk_audit_info ad;
        int rc;
 
@@ -3351,7 +3161,8 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, 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;
@@ -3372,7 +3183,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;
 }
@@ -3400,7 +3212,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);
        /*
@@ -3411,7 +3223,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                goto unlockandout;
 
        sbp = inode->i_sb;
-       sbsp = sbp->s_security;
+       sbsp = smack_superblock(sbp);
        /*
         * We're going to use the superblock default label
         * if there's no label on the file.
@@ -3612,18 +3424,16 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
 {
        struct smack_known *skp = smk_of_task_struct(p);
        char *cp;
-       int slen;
 
-       if (strcmp(name, "current") != 0)
+       if (strcmp(name, "current") == 0) {
+               cp = kstrdup(skp->smk_known, GFP_KERNEL);
+               if (cp == NULL)
+                       return -ENOMEM;
+       } else
                return -EINVAL;
 
-       cp = kstrdup(skp->smk_known, GFP_KERNEL);
-       if (cp == NULL)
-               return -ENOMEM;
-
-       slen = strlen(cp);
        *value = cp;
-       return slen;
+       return strlen(cp);
 }
 
 /**
@@ -3639,7 +3449,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;
@@ -3680,7 +3490,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
@@ -3705,9 +3515,9 @@ static int smack_unix_stream_connect(struct sock *sock,
 {
        struct smack_known *skp;
        struct smack_known *okp;
-       struct socket_smack *ssp = sock->sk_security;
-       struct socket_smack *osp = other->sk_security;
-       struct socket_smack *nsp = newsk->sk_security;
+       struct socket_smack *ssp = smack_sock(sock);
+       struct socket_smack *osp = smack_sock(other);
+       struct socket_smack *nsp = smack_sock(newsk);
        struct smk_audit_info ad;
        int rc = 0;
 #ifdef CONFIG_AUDIT
@@ -3753,8 +3563,8 @@ static int smack_unix_stream_connect(struct sock *sock,
  */
 static int smack_unix_may_send(struct socket *sock, struct socket *other)
 {
-       struct socket_smack *ssp = sock->sk->sk_security;
-       struct socket_smack *osp = other->sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sock->sk);
+       struct socket_smack *osp = smack_sock(other->sk);
        struct smk_audit_info ad;
        int rc;
 
@@ -3791,7 +3601,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
        struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
 #endif
 #ifdef SMACK_IPV6_SECMARK_LABELING
-       struct socket_smack *ssp = sock->sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sock->sk);
        struct smack_known *rsp;
 #endif
        int rc = 0;
@@ -3955,19 +3765,23 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
 static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct netlbl_lsm_secattr secattr;
-       struct socket_smack *ssp = sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sk);
        struct smack_known *skp = NULL;
        int rc = 0;
        struct smk_audit_info ad;
+       u16 family = sk->sk_family;
 #ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
 #endif
 #if IS_ENABLED(CONFIG_IPV6)
        struct sockaddr_in6 sadd;
        int proto;
+
+       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+               family = PF_INET;
 #endif /* CONFIG_IPV6 */
 
-       switch (sk->sk_family) {
+       switch (family) {
        case PF_INET:
 #ifdef CONFIG_SECURITY_SMACK_NETFILTER
                /*
@@ -3985,7 +3799,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                 */
                netlbl_secattr_init(&secattr);
 
-               rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
+               rc = netlbl_skbuff_getattr(skb, family, &secattr);
                if (rc == 0)
                        skp = smack_from_secattr(&secattr, ssp);
                else
@@ -3998,7 +3812,7 @@ access_check:
 #endif
 #ifdef CONFIG_AUDIT
                smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-               ad.a.u.net->family = sk->sk_family;
+               ad.a.u.net->family = family;
                ad.a.u.net->netif = skb->skb_iif;
                ipv4_skb_to_auditdata(skb, &ad.a, NULL);
 #endif
@@ -4012,7 +3826,7 @@ access_check:
                rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in,
                                        MAY_WRITE, rc);
                if (rc != 0)
-                       netlbl_skbuff_err(skb, sk->sk_family, rc, 0);
+                       netlbl_skbuff_err(skb, family, rc, 0);
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
@@ -4026,9 +3840,11 @@ access_check:
                        skp = smack_ipv6host_label(&sadd);
                if (skp == NULL)
                        skp = smack_net_ambient;
+               if (skb == NULL)
+                       break;
 #ifdef CONFIG_AUDIT
                smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-               ad.a.u.net->family = sk->sk_family;
+               ad.a.u.net->family = family;
                ad.a.u.net->netif = skb->skb_iif;
                ipv6_skb_to_auditdata(skb, &ad.a, NULL);
 #endif /* CONFIG_AUDIT */
@@ -4064,7 +3880,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
        int slen = 1;
        int rc = 0;
 
-       ssp = sock->sk->sk_security;
+       ssp = smack_sock(sock->sk);
        if (ssp->smk_packet != NULL) {
                rcp = ssp->smk_packet->smk_known;
                slen = strlen(rcp) + 1;
@@ -4114,7 +3930,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
 
        switch (family) {
        case PF_UNIX:
-               ssp = sock->sk->sk_security;
+               ssp = smack_sock(sock->sk);
                s = ssp->smk_out->smk_secid;
                break;
        case PF_INET:
@@ -4127,7 +3943,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
                 * Translate what netlabel gave us.
                 */
                if (sock != NULL && sock->sk != NULL)
-                       ssp = sock->sk->sk_security;
+                       ssp = smack_sock(sock->sk);
                netlbl_secattr_init(&secattr);
                rc = netlbl_skbuff_getattr(skb, family, &secattr);
                if (rc == 0) {
@@ -4165,7 +3981,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
            (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
                return;
 
-       ssp = sk->sk_security;
+       ssp = smack_sock(sk);
        ssp->smk_in = skp;
        ssp->smk_out = skp;
        /* cssp->smk_packet is already set in smack_inet_csk_clone() */
@@ -4185,7 +4001,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 {
        u16 family = sk->sk_family;
        struct smack_known *skp;
-       struct socket_smack *ssp = sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sk);
        struct netlbl_lsm_secattr secattr;
        struct sockaddr_in addr;
        struct iphdr *hdr;
@@ -4284,7 +4100,7 @@ access_check:
 static void smack_inet_csk_clone(struct sock *sk,
                                 const struct request_sock *req)
 {
-       struct socket_smack *ssp = sk->sk_security;
+       struct socket_smack *ssp = smack_sock(sk);
        struct smack_known *skp;
 
        if (req->peer_secid != 0) {
@@ -4316,23 +4132,13 @@ 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 **blob = smack_key(key);
+       struct smack_known *skp = smk_of_task(smack_cred(cred));
 
-       key->security = skp;
+       *blob = skp;
        return 0;
 }
 
-/**
- * smack_key_free - Clear the key security blob
- * @key: the object
- *
- * Clear the blob pointer
- */
-static void smack_key_free(struct key *key)
-{
-       key->security = NULL;
-}
-
 /**
  * smack_key_permission - Smack access on a key
  * @key_ref: gets to the object
@@ -4345,12 +4151,20 @@ static void smack_key_free(struct key *key)
 static int smack_key_permission(key_ref_t key_ref,
                                const struct cred *cred, unsigned perm)
 {
+       struct smack_known **blob;
+       struct smack_known *skp;
        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;
 
+       /*
+        * Validate requested permissions
+        */
+       if (perm & ~KEY_NEED_ALL)
+               return -EINVAL;
+
        keyp = key_ref_to_ptr(key_ref);
        if (keyp == NULL)
                return -EINVAL;
@@ -4358,7 +4172,9 @@ static int smack_key_permission(key_ref_t key_ref,
         * If the key hasn't been initialized give it access so that
         * it may do so.
         */
-       if (keyp->security == NULL)
+       blob = smack_key(keyp);
+       skp = *blob;
+       if (skp == NULL)
                return 0;
        /*
         * This should not occur
@@ -4370,12 +4186,12 @@ static int smack_key_permission(key_ref_t key_ref,
        ad.a.u.key_struct.key = keyp->serial;
        ad.a.u.key_struct.key_desc = keyp->description;
 #endif
-       if (perm & KEY_NEED_READ)
-               request = MAY_READ;
+       if (perm & (KEY_NEED_READ | KEY_NEED_SEARCH | KEY_NEED_VIEW))
+               request |= MAY_READ;
        if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
-               request = MAY_WRITE;
-       rc = smk_access(tkp, keyp->security, request, &ad);
-       rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
+               request |= MAY_WRITE;
+       rc = smk_access(tkp, skp, request, &ad);
+       rc = smk_bu_note("key access", tkp, skp, request, rc);
        return rc;
 }
 
@@ -4390,11 +4206,12 @@ static int smack_key_permission(key_ref_t key_ref,
  */
 static int smack_key_getsecurity(struct key *key, char **_buffer)
 {
-       struct smack_known *skp = key->security;
+       struct smack_known **blob = smack_key(key);
+       struct smack_known *skp = *blob;
        size_t length;
        char *copy;
 
-       if (key->security == NULL) {
+       if (skp == NULL) {
                *_buffer = NULL;
                return 0;
        }
@@ -4614,12 +4431,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;
@@ -4642,8 +4459,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;
 
@@ -4656,7 +4473,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();
@@ -4676,13 +4493,25 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
        return 0;
 }
 
+struct lsm_blob_sizes smack_blob_sizes = {
+       .lbs_cred = sizeof(struct task_smack),
+       .lbs_file = sizeof(struct smack_known *),
+       .lbs_inode = sizeof(struct inode_smack),
+       .lbs_ipc = sizeof(struct smack_known *),
+#ifdef CONFIG_KEYS
+       .lbs_key = sizeof(struct smack_known *),
+#endif /* CONFIG_KEYS */
+       .lbs_msg_msg = sizeof(struct smack_known *),
+       .lbs_sock = sizeof(struct socket_smack),
+       .lbs_superblock = sizeof(struct superblock_smack),
+};
+
 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(syslog, smack_syslog),
 
        LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
-       LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
        LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
        LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
        LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
@@ -4692,7 +4521,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),
@@ -4711,7 +4539,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),
@@ -4746,23 +4573,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_msg_queue_alloc_security),
-       LSM_HOOK_INIT(msg_queue_free_security, smack_msg_queue_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_shm_alloc_security),
-       LSM_HOOK_INIT(shm_free_security, smack_shm_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_sem_alloc_security),
-       LSM_HOOK_INIT(sem_free_security, smack_sem_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),
@@ -4785,7 +4608,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
        LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
        LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
+#ifdef SMACK_IPV6_PORT_LABELING
        LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+#endif
        LSM_HOOK_INIT(sock_graft, smack_sock_graft),
        LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
        LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
@@ -4793,7 +4618,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
  /* key management security hooks */
 #ifdef CONFIG_KEYS
        LSM_HOOK_INIT(key_alloc, smack_key_alloc),
-       LSM_HOOK_INIT(key_free, smack_key_free),
        LSM_HOOK_INIT(key_permission, smack_key_permission),
        LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity),
 #endif /* CONFIG_KEYS */
@@ -4852,23 +4676,36 @@ static __init void init_smack_known_list(void)
  */
 static __init int smack_init(void)
 {
-       struct cred *cred;
+       static int finish;
+       struct cred *cred = (struct cred *) current->cred;
        struct task_smack *tsp;
 
-       if (!security_module_enable("smack"))
+       if (!security_module_enable("smack",
+                               IS_ENABLED(CONFIG_SECURITY_SMACK_STACKED)))
+               return 0;
+
+       if (!finish) {
+               security_add_blobs(&smack_blob_sizes);
+               finish = 1;
                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;
-       }
+       lsm_early_cred(cred);
 
+       /*
+        * 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");
@@ -4882,20 +4719,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;
 }