]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - security/smack/smack_lsm.c
Smack: Mark inode instant in smack_task_to_inode
[mirror_ubuntu-bionic-kernel.git] / security / smack / smack_lsm.c
index c412f7fdebebaff1980f6ff5e6077936471a4339..1211c333c722be6bc3ff03cb09f7a88bbdf2bff6 100644 (file)
@@ -165,7 +165,7 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
 static int smk_bu_inode(struct inode *inode, int mode, int rc)
 {
        struct task_smack *tsp = smack_cred(current_cred());
-       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)
@@ -197,7 +197,7 @@ static int smk_bu_file(struct file *file, int mode, int rc)
        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)
@@ -227,7 +227,7 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
        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)
@@ -287,24 +287,18 @@ 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;
 }
 
 /**
@@ -525,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;
@@ -539,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
@@ -745,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;
@@ -823,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;
 }
@@ -878,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;
 
@@ -911,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;
@@ -962,48 +935,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
@@ -1019,7 +954,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);
@@ -1204,7 +1139,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;
@@ -1357,7 +1292,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;
@@ -1438,7 +1373,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
@@ -1446,7 +1381,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)
@@ -1492,7 +1427,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;
@@ -1536,7 +1471,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;
 }
@@ -1570,24 +1505,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
@@ -1725,10 +1648,10 @@ 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;
@@ -1812,7 +1735,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();
 }
 
 /**
@@ -1829,6 +1754,7 @@ 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(smack_cred(tsk->cred));
        struct file *file;
@@ -1841,7 +1767,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))
@@ -1877,7 +1804,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;
+               ssp = smack_sock(sock->sk);
                tsp = smack_cred(current_cred());
                /*
                 * If the receiving process can't write to the
@@ -2046,7 +1973,7 @@ 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 inode_smack *isp = smack_inode(inode);
        struct task_smack *tsp = smack_cred(new);
 
        tsp->smk_forked = isp->smk_inode;
@@ -2248,10 +2175,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;
 }
 
 /*
@@ -2271,11 +2199,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.
@@ -2289,11 +2213,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
@@ -2302,7 +2225,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) {
@@ -2315,9 +2237,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
@@ -2435,7 +2356,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;
 
        /*
@@ -2480,7 +2401,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();
@@ -2556,7 +2477,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;
 
@@ -2643,7 +2564,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;
@@ -2710,7 +2631,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;
@@ -2737,7 +2658,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;
@@ -2785,7 +2706,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;
        }
@@ -2894,34 +2815,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
@@ -2930,26 +2829,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
@@ -2959,7 +2844,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;
 
@@ -3038,17 +2924,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
@@ -3057,26 +2932,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
@@ -3086,7 +2947,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;
 
@@ -3172,44 +3034,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
@@ -3219,7 +3056,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;
 
@@ -3322,7 +3160,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;
@@ -3343,7 +3182,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;
 }
@@ -3371,7 +3211,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);
        /*
@@ -3382,7 +3222,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.
@@ -3583,18 +3423,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);
 }
 
 /**
@@ -3676,9 +3514,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
@@ -3724,8 +3562,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;
 
@@ -3762,7 +3600,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;
@@ -3926,7 +3764,7 @@ 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;
@@ -4035,7 +3873,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;
@@ -4085,7 +3923,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:
@@ -4098,7 +3936,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) {
@@ -4136,7 +3974,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() */
@@ -4156,7 +3994,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;
@@ -4255,7 +4093,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) {
@@ -4287,23 +4125,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 **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
@@ -4316,6 +4144,8 @@ 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(smack_cred(cred));
@@ -4329,7 +4159,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
@@ -4345,8 +4177,8 @@ static int smack_key_permission(key_ref_t key_ref,
                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);
+       rc = smk_access(tkp, skp, request, &ad);
+       rc = smk_bu_note("key access", tkp, skp, request, rc);
        return rc;
 }
 
@@ -4361,11 +4193,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;
        }
@@ -4590,7 +4423,7 @@ static int smack_inode_copy_up(struct dentry *dentry, struct cred **new)
        /*
         * 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;
@@ -4627,7 +4460,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();
@@ -4649,6 +4482,15 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
 
 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 = {
@@ -4657,7 +4499,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
        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),
@@ -4667,7 +4508,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),
@@ -4686,7 +4526,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),
@@ -4721,23 +4560,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),
@@ -4760,7 +4595,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),
@@ -4768,7 +4605,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 */
@@ -4831,7 +4667,8 @@ static __init int smack_init(void)
        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) {