Merge tag 'selinux-pr-20190305' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / security / selinux / hooks.c
index 81e012c66d95d756ab929479a093392b5be51700..2f82a54f870382440b621fde195ce69859bd286a 100644 (file)
@@ -79,7 +79,6 @@
 #include <linux/personality.h>
 #include <linux/audit.h>
 #include <linux/string.h>
-#include <linux/selinux.h>
 #include <linux/mutex.h>
 #include <linux/posix-timers.h>
 #include <linux/syslog.h>
@@ -121,9 +120,8 @@ __setup("enforcing=", enforcing_setup);
 #define selinux_enforcing_boot 1
 #endif
 
+int selinux_enabled __lsm_ro_after_init = 1;
 #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
-int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
-
 static int __init selinux_enabled_setup(char *str)
 {
        unsigned long enabled;
@@ -132,8 +130,6 @@ static int __init selinux_enabled_setup(char *str)
        return 1;
 }
 __setup("selinux=", selinux_enabled_setup);
-#else
-int selinux_enabled = 1;
 #endif
 
 static unsigned int selinux_checkreqprot_boot =
@@ -149,9 +145,6 @@ static int __init checkreqprot_setup(char *str)
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
-static struct kmem_cache *sel_inode_cache;
-static struct kmem_cache *file_security_cache;
-
 /**
  * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
  *
@@ -214,12 +207,8 @@ static void cred_init_security(void)
        struct cred *cred = (struct cred *) current->real_cred;
        struct task_security_struct *tsec;
 
-       tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
-       if (!tsec)
-               panic("SELinux:  Failed to initialize initial task.\n");
-
+       tsec = selinux_cred(cred);
        tsec->osid = tsec->sid = SECINITSID_KERNEL;
-       cred->security = tsec;
 }
 
 /*
@@ -229,7 +218,7 @@ static inline u32 cred_sid(const struct cred *cred)
 {
        const struct task_security_struct *tsec;
 
-       tsec = cred->security;
+       tsec = selinux_cred(cred);
        return tsec->sid;
 }
 
@@ -250,13 +239,9 @@ static inline u32 task_sid(const struct task_struct *task)
 
 static int inode_alloc_security(struct inode *inode)
 {
-       struct inode_security_struct *isec;
+       struct inode_security_struct *isec = selinux_inode(inode);
        u32 sid = current_sid();
 
-       isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
-       if (!isec)
-               return -ENOMEM;
-
        spin_lock_init(&isec->lock);
        INIT_LIST_HEAD(&isec->list);
        isec->inode = inode;
@@ -264,7 +249,6 @@ static int inode_alloc_security(struct inode *inode)
        isec->sclass = SECCLASS_FILE;
        isec->task_sid = sid;
        isec->initialized = LABEL_INVALID;
-       inode->i_security = isec;
 
        return 0;
 }
@@ -281,7 +265,7 @@ static int __inode_security_revalidate(struct inode *inode,
                                       struct dentry *dentry,
                                       bool may_sleep)
 {
-       struct inode_security_struct *isec = inode->i_security;
+       struct inode_security_struct *isec = selinux_inode(inode);
 
        might_sleep_if(may_sleep);
 
@@ -302,7 +286,7 @@ static int __inode_security_revalidate(struct inode *inode,
 
 static struct inode_security_struct *inode_security_novalidate(struct inode *inode)
 {
-       return inode->i_security;
+       return selinux_inode(inode);
 }
 
 static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu)
@@ -312,7 +296,7 @@ static struct inode_security_struct *inode_security_rcu(struct inode *inode, boo
        error = __inode_security_revalidate(inode, NULL, !rcu);
        if (error)
                return ERR_PTR(error);
-       return inode->i_security;
+       return selinux_inode(inode);
 }
 
 /*
@@ -321,14 +305,14 @@ static struct inode_security_struct *inode_security_rcu(struct inode *inode, boo
 static struct inode_security_struct *inode_security(struct inode *inode)
 {
        __inode_security_revalidate(inode, NULL, true);
-       return inode->i_security;
+       return selinux_inode(inode);
 }
 
 static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry)
 {
        struct inode *inode = d_backing_inode(dentry);
 
-       return inode->i_security;
+       return selinux_inode(inode);
 }
 
 /*
@@ -339,22 +323,17 @@ static struct inode_security_struct *backing_inode_security(struct dentry *dentr
        struct inode *inode = d_backing_inode(dentry);
 
        __inode_security_revalidate(inode, dentry, true);
-       return inode->i_security;
-}
-
-static void inode_free_rcu(struct rcu_head *head)
-{
-       struct inode_security_struct *isec;
-
-       isec = container_of(head, struct inode_security_struct, rcu);
-       kmem_cache_free(sel_inode_cache, isec);
+       return selinux_inode(inode);
 }
 
 static void inode_free_security(struct inode *inode)
 {
-       struct inode_security_struct *isec = inode->i_security;
-       struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+       struct inode_security_struct *isec = selinux_inode(inode);
+       struct superblock_security_struct *sbsec;
 
+       if (!isec)
+               return;
+       sbsec = inode->i_sb->s_security;
        /*
         * As not all inode security structures are in a list, we check for
         * empty list outside of the lock to make sure that we won't waste
@@ -370,42 +349,19 @@ static void inode_free_security(struct inode *inode)
                list_del_init(&isec->list);
                spin_unlock(&sbsec->isec_lock);
        }
-
-       /*
-        * The inode may still be referenced in a path walk and
-        * a call to selinux_inode_permission() can be made
-        * after inode_free_security() is called. Ideally, the VFS
-        * wouldn't do this, but fixing that is a much harder
-        * job. For now, simply free the i_security via RCU, and
-        * leave the current inode->i_security pointer intact.
-        * The inode will be freed after the RCU grace period too.
-        */
-       call_rcu(&isec->rcu, inode_free_rcu);
 }
 
 static int file_alloc_security(struct file *file)
 {
-       struct file_security_struct *fsec;
+       struct file_security_struct *fsec = selinux_file(file);
        u32 sid = current_sid();
 
-       fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
-       if (!fsec)
-               return -ENOMEM;
-
        fsec->sid = sid;
        fsec->fown_sid = sid;
-       file->f_security = fsec;
 
        return 0;
 }
 
-static void file_free_security(struct file *file)
-{
-       struct file_security_struct *fsec = file->f_security;
-       file->f_security = NULL;
-       kmem_cache_free(file_security_cache, fsec);
-}
-
 static int superblock_alloc_security(struct super_block *sb)
 {
        struct superblock_security_struct *sbsec;
@@ -501,7 +457,7 @@ static int may_context_mount_sb_relabel(u32 sid,
                        struct superblock_security_struct *sbsec,
                        const struct cred *cred)
 {
-       const struct task_security_struct *tsec = cred->security;
+       const struct task_security_struct *tsec = selinux_cred(cred);
        int rc;
 
        rc = avc_has_perm(&selinux_state,
@@ -520,7 +476,7 @@ static int may_context_mount_inode_relabel(u32 sid,
                        struct superblock_security_struct *sbsec,
                        const struct cred *cred)
 {
-       const struct task_security_struct *tsec = cred->security;
+       const struct task_security_struct *tsec = selinux_cred(cred);
        int rc;
        rc = avc_has_perm(&selinux_state,
                          tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
@@ -1396,7 +1352,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
 static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
 {
        struct superblock_security_struct *sbsec = NULL;
-       struct inode_security_struct *isec = inode->i_security;
+       struct inode_security_struct *isec = selinux_inode(inode);
        u32 task_sid, sid = 0;
        u16 sclass;
        struct dentry *dentry;
@@ -1643,7 +1599,7 @@ static inline u32 signal_to_av(int sig)
 
 /* Check whether a task is allowed to use a capability. */
 static int cred_has_capability(const struct cred *cred,
-                              int cap, int audit, bool initns)
+                              int cap, unsigned int opts, bool initns)
 {
        struct common_audit_data ad;
        struct av_decision avd;
@@ -1670,7 +1626,7 @@ static int cred_has_capability(const struct cred *cred,
 
        rc = avc_has_perm_noaudit(&selinux_state,
                                  sid, sid, sclass, av, 0, &avd);
-       if (audit == SECURITY_CAP_AUDIT) {
+       if (!(opts & CAP_OPT_NOAUDIT)) {
                int rc2 = avc_audit(&selinux_state,
                                    sid, sid, sclass, av, &avd, rc, &ad, 0);
                if (rc2)
@@ -1696,7 +1652,7 @@ static int inode_has_perm(const struct cred *cred,
                return 0;
 
        sid = cred_sid(cred);
-       isec = inode->i_security;
+       isec = selinux_inode(inode);
 
        return avc_has_perm(&selinux_state,
                            sid, isec->sid, isec->sclass, perms, adp);
@@ -1762,7 +1718,7 @@ static int file_has_perm(const struct cred *cred,
                         struct file *file,
                         u32 av)
 {
-       struct file_security_struct *fsec = file->f_security;
+       struct file_security_struct *fsec = selinux_file(file);
        struct inode *inode = file_inode(file);
        struct common_audit_data ad;
        u32 sid = cred_sid(cred);
@@ -1828,7 +1784,7 @@ static int may_create(struct inode *dir,
                      struct dentry *dentry,
                      u16 tclass)
 {
-       const struct task_security_struct *tsec = current_security();
+       const struct task_security_struct *tsec = selinux_cred(current_cred());
        struct inode_security_struct *dsec;
        struct superblock_security_struct *sbsec;
        u32 sid, newsid;
@@ -1850,7 +1806,7 @@ static int may_create(struct inode *dir,
        if (rc)
                return rc;
 
-       rc = selinux_determine_inode_label(current_security(), dir,
+       rc = selinux_determine_inode_label(selinux_cred(current_cred()), dir,
                                           &dentry->d_name, tclass, &newsid);
        if (rc)
                return rc;
@@ -2106,7 +2062,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
                                        struct file *file)
 {
        u32 sid = task_sid(to);
-       struct file_security_struct *fsec = file->f_security;
+       struct file_security_struct *fsec = selinux_file(file);
        struct dentry *dentry = file->f_path.dentry;
        struct inode_security_struct *isec;
        struct common_audit_data ad;
@@ -2190,9 +2146,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
  */
 
 static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
-                          int cap, int audit)
+                          int cap, unsigned int opts)
 {
-       return cred_has_capability(cred, cap, audit, ns == &init_user_ns);
+       return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
 }
 
 static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -2266,7 +2222,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
        int rc, cap_sys_admin = 0;
 
        rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
-                                SECURITY_CAP_NOAUDIT, true);
+                                CAP_OPT_NOAUDIT, true);
        if (rc == 0)
                cap_sys_admin = 1;
 
@@ -2357,8 +2313,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
        if (bprm->called_set_creds)
                return 0;
 
-       old_tsec = current_security();
-       new_tsec = bprm->cred->security;
+       old_tsec = selinux_cred(current_cred());
+       new_tsec = selinux_cred(bprm->cred);
        isec = inode_security(inode);
 
        /* Default to the current task SID. */
@@ -2522,7 +2478,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
        struct rlimit *rlim, *initrlim;
        int rc, i;
 
-       new_tsec = bprm->cred->security;
+       new_tsec = selinux_cred(bprm->cred);
        if (new_tsec->sid == new_tsec->osid)
                return;
 
@@ -2565,7 +2521,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
  */
 static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
 {
-       const struct task_security_struct *tsec = current_security();
+       const struct task_security_struct *tsec = selinux_cred(current_cred());
        struct itimerval itimer;
        u32 osid, sid;
        int rc, i;
@@ -2802,7 +2758,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
        u32 newsid;
        int rc;
 
-       rc = selinux_determine_inode_label(current_security(),
+       rc = selinux_determine_inode_label(selinux_cred(current_cred()),
                                           d_inode(dentry->d_parent), name,
                                           inode_mode_to_security_class(mode),
                                           &newsid);
@@ -2822,14 +2778,14 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
        int rc;
        struct task_security_struct *tsec;
 
-       rc = selinux_determine_inode_label(old->security,
+       rc = selinux_determine_inode_label(selinux_cred(old),
                                           d_inode(dentry->d_parent), name,
                                           inode_mode_to_security_class(mode),
                                           &newsid);
        if (rc)
                return rc;
 
-       tsec = new->security;
+       tsec = selinux_cred(new);
        tsec->create_sid = newsid;
        return 0;
 }
@@ -2839,7 +2795,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
                                       const char **name,
                                       void **value, size_t *len)
 {
-       const struct task_security_struct *tsec = current_security();
+       const struct task_security_struct *tsec = selinux_cred(current_cred());
        struct superblock_security_struct *sbsec;
        u32 newsid, clen;
        int rc;
@@ -2849,7 +2805,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 
        newsid = tsec->create_sid;
 
-       rc = selinux_determine_inode_label(current_security(),
+       rc = selinux_determine_inode_label(selinux_cred(current_cred()),
                dir, qstr,
                inode_mode_to_security_class(inode->i_mode),
                &newsid);
@@ -2858,7 +2814,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 
        /* Possibly defer initialization to selinux_complete_init. */
        if (sbsec->flags & SE_SBINITIALIZED) {
-               struct inode_security_struct *isec = inode->i_security;
+               struct inode_security_struct *isec = selinux_inode(inode);
                isec->sclass = inode_mode_to_security_class(inode->i_mode);
                isec->sid = newsid;
                isec->initialized = LABEL_INITIALIZED;
@@ -2957,7 +2913,7 @@ static noinline int audit_inode_permission(struct inode *inode,
                                           unsigned flags)
 {
        struct common_audit_data ad;
-       struct inode_security_struct *isec = inode->i_security;
+       struct inode_security_struct *isec = selinux_inode(inode);
        int rc;
 
        ad.type = LSM_AUDIT_DATA_INODE;
@@ -3054,11 +3010,11 @@ static int selinux_inode_getattr(const struct path *path)
 static bool has_cap_mac_admin(bool audit)
 {
        const struct cred *cred = current_cred();
-       int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
+       unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
 
-       if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
+       if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
                return false;
-       if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
+       if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
                return false;
        return true;
 }
@@ -3316,7 +3272,7 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
                        return -ENOMEM;
        }
 
-       tsec = new_creds->security;
+       tsec = selinux_cred(new_creds);
        /* Get label from overlay inode and set it in create_sid */
        selinux_inode_getsecid(d_inode(src), &sid);
        tsec->create_sid = sid;
@@ -3357,7 +3313,7 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
 static int selinux_file_permission(struct file *file, int mask)
 {
        struct inode *inode = file_inode(file);
-       struct file_security_struct *fsec = file->f_security;
+       struct file_security_struct *fsec = selinux_file(file);
        struct inode_security_struct *isec;
        u32 sid = current_sid();
 
@@ -3379,11 +3335,6 @@ static int selinux_file_alloc_security(struct file *file)
        return file_alloc_security(file);
 }
 
-static void selinux_file_free_security(struct file *file)
-{
-       file_free_security(file);
-}
-
 /*
  * Check whether a task has the ioctl permission and cmd
  * operation to an inode.
@@ -3392,7 +3343,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
                u32 requested, u16 cmd)
 {
        struct common_audit_data ad;
-       struct file_security_struct *fsec = file->f_security;
+       struct file_security_struct *fsec = selinux_file(file);
        struct inode *inode = file_inode(file);
        struct inode_security_struct *isec;
        struct lsm_ioctlop_audit ioctl;
@@ -3462,7 +3413,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
        case KDSKBENT:
        case KDSKBSENT:
                error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
-                                           SECURITY_CAP_AUDIT, true);
+                                           CAP_OPT_NONE, true);
                break;
 
        /* default case assumes that the command will go
@@ -3644,7 +3595,7 @@ static void selinux_file_set_fowner(struct file *file)
 {
        struct file_security_struct *fsec;
 
-       fsec = file->f_security;
+       fsec = selinux_file(file);
        fsec->fown_sid = current_sid();
 }
 
@@ -3659,7 +3610,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
        /* struct fown_struct is never outside the context of a struct file */
        file = container_of(fown, struct file, f_owner);
 
-       fsec = file->f_security;
+       fsec = selinux_file(file);
 
        if (!signum)
                perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
@@ -3683,7 +3634,7 @@ static int selinux_file_open(struct file *file)
        struct file_security_struct *fsec;
        struct inode_security_struct *isec;
 
-       fsec = file->f_security;
+       fsec = selinux_file(file);
        isec = inode_security(file_inode(file));
        /*
         * Save inode label and policy sequence number
@@ -3716,53 +3667,16 @@ static int selinux_task_alloc(struct task_struct *task,
                            sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
 }
 
-/*
- * allocate the SELinux part of blank credentials
- */
-static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
-{
-       struct task_security_struct *tsec;
-
-       tsec = kzalloc(sizeof(struct task_security_struct), gfp);
-       if (!tsec)
-               return -ENOMEM;
-
-       cred->security = tsec;
-       return 0;
-}
-
-/*
- * detach and free the LSM part of a set of credentials
- */
-static void selinux_cred_free(struct cred *cred)
-{
-       struct task_security_struct *tsec = cred->security;
-
-       /*
-        * cred->security == NULL if security_cred_alloc_blank() or
-        * security_prepare_creds() returned an error.
-        */
-       BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
-       cred->security = (void *) 0x7UL;
-       kfree(tsec);
-}
-
 /*
  * prepare a new set of credentials for modification
  */
 static int selinux_cred_prepare(struct cred *new, const struct cred *old,
                                gfp_t gfp)
 {
-       const struct task_security_struct *old_tsec;
-       struct task_security_struct *tsec;
+       const struct task_security_struct *old_tsec = selinux_cred(old);
+       struct task_security_struct *tsec = selinux_cred(new);
 
-       old_tsec = old->security;
-
-       tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
-       if (!tsec)
-               return -ENOMEM;
-
-       new->security = tsec;
+       *tsec = *old_tsec;
        return 0;
 }
 
@@ -3771,8 +3685,8 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
  */
 static void selinux_cred_transfer(struct cred *new, const struct cred *old)
 {
-       const struct task_security_struct *old_tsec = old->security;
-       struct task_security_struct *tsec = new->security;
+       const struct task_security_struct *old_tsec = selinux_cred(old);
+       struct task_security_struct *tsec = selinux_cred(new);
 
        *tsec = *old_tsec;
 }
@@ -3788,7 +3702,7 @@ static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
  */
 static int selinux_kernel_act_as(struct cred *new, u32 secid)
 {
-       struct task_security_struct *tsec = new->security;
+       struct task_security_struct *tsec = selinux_cred(new);
        u32 sid = current_sid();
        int ret;
 
@@ -3813,7 +3727,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)
 static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
 {
        struct inode_security_struct *isec = inode_security(inode);
-       struct task_security_struct *tsec = new->security;
+       struct task_security_struct *tsec = selinux_cred(new);
        u32 sid = current_sid();
        int ret;
 
@@ -3859,7 +3773,7 @@ static int selinux_kernel_module_from_file(struct file *file)
        ad.type = LSM_AUDIT_DATA_FILE;
        ad.u.file = file;
 
-       fsec = file->f_security;
+       fsec = selinux_file(file);
        if (sid != fsec->sid) {
                rc = avc_has_perm(&selinux_state,
                                  sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
@@ -4025,7 +3939,7 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
 static void selinux_task_to_inode(struct task_struct *p,
                                  struct inode *inode)
 {
-       struct inode_security_struct *isec = inode->i_security;
+       struct inode_security_struct *isec = selinux_inode(inode);
        u32 sid = task_sid(p);
 
        spin_lock(&isec->lock);
@@ -4362,7 +4276,7 @@ static int sock_has_perm(struct sock *sk, u32 perms)
 static int selinux_socket_create(int family, int type,
                                 int protocol, int kern)
 {
-       const struct task_security_struct *tsec = current_security();
+       const struct task_security_struct *tsec = selinux_cred(current_cred());
        u32 newsid;
        u16 secclass;
        int rc;
@@ -4382,7 +4296,7 @@ static int selinux_socket_create(int family, int type,
 static int selinux_socket_post_create(struct socket *sock, int family,
                                      int type, int protocol, int kern)
 {
-       const struct task_security_struct *tsec = current_security();
+       const struct task_security_struct *tsec = selinux_cred(current_cred());
        struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
        struct sk_security_struct *sksec;
        u16 sclass = socket_type_to_security_class(family, type, protocol);
@@ -5263,7 +5177,7 @@ static int selinux_secmark_relabel_packet(u32 sid)
        const struct task_security_struct *__tsec;
        u32 tsid;
 
-       __tsec = current_security();
+       __tsec = selinux_cred(current_cred());
        tsid = __tsec->sid;
 
        return avc_has_perm(&selinux_state,
@@ -5738,51 +5652,22 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
        return selinux_nlmsg_perm(sk, skb);
 }
 
-static int ipc_alloc_security(struct kern_ipc_perm *perm,
-                             u16 sclass)
+static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass)
 {
-       struct ipc_security_struct *isec;
-
-       isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
-       if (!isec)
-               return -ENOMEM;
-
        isec->sclass = sclass;
        isec->sid = current_sid();
-       perm->security = isec;
-
-       return 0;
-}
-
-static void ipc_free_security(struct kern_ipc_perm *perm)
-{
-       struct ipc_security_struct *isec = perm->security;
-       perm->security = NULL;
-       kfree(isec);
 }
 
 static int msg_msg_alloc_security(struct msg_msg *msg)
 {
        struct msg_security_struct *msec;
 
-       msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
-       if (!msec)
-               return -ENOMEM;
-
+       msec = selinux_msg_msg(msg);
        msec->sid = SECINITSID_UNLABELED;
-       msg->security = msec;
 
        return 0;
 }
 
-static void msg_msg_free_security(struct msg_msg *msg)
-{
-       struct msg_security_struct *msec = msg->security;
-
-       msg->security = NULL;
-       kfree(msec);
-}
-
 static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
                        u32 perms)
 {
@@ -5790,7 +5675,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = ipc_perms->security;
+       isec = selinux_ipc(ipc_perms);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = ipc_perms->key;
@@ -5804,11 +5689,6 @@ static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
        return msg_msg_alloc_security(msg);
 }
 
-static void selinux_msg_msg_free_security(struct msg_msg *msg)
-{
-       msg_msg_free_security(msg);
-}
-
 /* message queue security operations */
 static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
 {
@@ -5817,11 +5697,8 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(msq, SECCLASS_MSGQ);
-       if (rc)
-               return rc;
-
-       isec = msq->security;
+       isec = selinux_ipc(msq);
+       ipc_init_security(isec, SECCLASS_MSGQ);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
@@ -5829,16 +5706,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
        rc = avc_has_perm(&selinux_state,
                          sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__CREATE, &ad);
-       if (rc) {
-               ipc_free_security(msq);
-               return rc;
-       }
-       return 0;
-}
-
-static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)
-{
-       ipc_free_security(msq);
+       return rc;
 }
 
 static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
@@ -5847,7 +5715,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = msq->security;
+       isec = selinux_ipc(msq);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
@@ -5896,8 +5764,8 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
        u32 sid = current_sid();
        int rc;
 
-       isec = msq->security;
-       msec = msg->security;
+       isec = selinux_ipc(msq);
+       msec = selinux_msg_msg(msg);
 
        /*
         * First time through, need to assign label to the message
@@ -5944,8 +5812,8 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
        u32 sid = task_sid(target);
        int rc;
 
-       isec = msq->security;
-       msec = msg->security;
+       isec = selinux_ipc(msq);
+       msec = selinux_msg_msg(msg);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
@@ -5968,11 +5836,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(shp, SECCLASS_SHM);
-       if (rc)
-               return rc;
-
-       isec = shp->security;
+       isec = selinux_ipc(shp);
+       ipc_init_security(isec, SECCLASS_SHM);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->key;
@@ -5980,16 +5845,7 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
        rc = avc_has_perm(&selinux_state,
                          sid, isec->sid, SECCLASS_SHM,
                          SHM__CREATE, &ad);
-       if (rc) {
-               ipc_free_security(shp);
-               return rc;
-       }
-       return 0;
-}
-
-static void selinux_shm_free_security(struct kern_ipc_perm *shp)
-{
-       ipc_free_security(shp);
+       return rc;
 }
 
 static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
@@ -5998,7 +5854,7 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = shp->security;
+       isec = selinux_ipc(shp);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->key;
@@ -6065,11 +5921,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
        u32 sid = current_sid();
        int rc;
 
-       rc = ipc_alloc_security(sma, SECCLASS_SEM);
-       if (rc)
-               return rc;
-
-       isec = sma->security;
+       isec = selinux_ipc(sma);
+       ipc_init_security(isec, SECCLASS_SEM);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->key;
@@ -6077,16 +5930,7 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
        rc = avc_has_perm(&selinux_state,
                          sid, isec->sid, SECCLASS_SEM,
                          SEM__CREATE, &ad);
-       if (rc) {
-               ipc_free_security(sma);
-               return rc;
-       }
-       return 0;
-}
-
-static void selinux_sem_free_security(struct kern_ipc_perm *sma)
-{
-       ipc_free_security(sma);
+       return rc;
 }
 
 static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
@@ -6095,7 +5939,7 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
        struct common_audit_data ad;
        u32 sid = current_sid();
 
-       isec = sma->security;
+       isec = selinux_ipc(sma);
 
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->key;
@@ -6181,7 +6025,7 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 
 static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
 {
-       struct ipc_security_struct *isec = ipcp->security;
+       struct ipc_security_struct *isec = selinux_ipc(ipcp);
        *secid = isec->sid;
 }
 
@@ -6200,7 +6044,7 @@ static int selinux_getprocattr(struct task_struct *p,
        unsigned len;
 
        rcu_read_lock();
-       __tsec = __task_cred(p)->security;
+       __tsec = selinux_cred(__task_cred(p));
 
        if (current != p) {
                error = avc_has_perm(&selinux_state,
@@ -6323,7 +6167,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
           operation.  See selinux_bprm_set_creds for the execve
           checks and may_create for the file creation checks. The
           operation will then fail if the context is not permitted. */
-       tsec = new->security;
+       tsec = selinux_cred(new);
        if (!strcmp(name, "exec")) {
                tsec->exec_sid = sid;
        } else if (!strcmp(name, "fscreate")) {
@@ -6407,7 +6251,7 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
 
 static void selinux_inode_invalidate_secctx(struct inode *inode)
 {
-       struct inode_security_struct *isec = inode->i_security;
+       struct inode_security_struct *isec = selinux_inode(inode);
 
        spin_lock(&isec->lock);
        isec->initialized = LABEL_INVALID;
@@ -6455,7 +6299,7 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred,
        if (!ksec)
                return -ENOMEM;
 
-       tsec = cred->security;
+       tsec = selinux_cred(cred);
        if (tsec->keycreate_sid)
                ksec->sid = tsec->keycreate_sid;
        else
@@ -6718,6 +6562,14 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 }
 #endif
 
+struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
+       .lbs_cred = sizeof(struct task_security_struct),
+       .lbs_file = sizeof(struct file_security_struct),
+       .lbs_inode = sizeof(struct inode_security_struct),
+       .lbs_ipc = sizeof(struct ipc_security_struct),
+       .lbs_msg_msg = sizeof(struct msg_security_struct),
+};
+
 static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
        LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
@@ -6787,7 +6639,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 
        LSM_HOOK_INIT(file_permission, selinux_file_permission),
        LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
-       LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
        LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
        LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
        LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
@@ -6801,8 +6652,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(file_open, selinux_file_open),
 
        LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
-       LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
-       LSM_HOOK_INIT(cred_free, selinux_cred_free),
        LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
        LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
        LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid),
@@ -6830,24 +6679,20 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
 
        LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
-       LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
 
        LSM_HOOK_INIT(msg_queue_alloc_security,
                        selinux_msg_queue_alloc_security),
-       LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
        LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
        LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
        LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
        LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
 
        LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
-       LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
        LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
        LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
        LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
 
        LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
-       LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
        LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
        LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
        LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
@@ -6958,16 +6803,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 
 static __init int selinux_init(void)
 {
-       if (!security_module_enable("selinux")) {
-               selinux_enabled = 0;
-               return 0;
-       }
-
-       if (!selinux_enabled) {
-               pr_info("SELinux:  Disabled at boot.\n");
-               return 0;
-       }
-
        pr_info("SELinux:  Initializing.\n");
 
        memset(&selinux_state, 0, sizeof(selinux_state));
@@ -6981,12 +6816,6 @@ static __init int selinux_init(void)
 
        default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
 
-       sel_inode_cache = kmem_cache_create("selinux_inode_security",
-                                           sizeof(struct inode_security_struct),
-                                           0, SLAB_PANIC, NULL);
-       file_security_cache = kmem_cache_create("selinux_file_security",
-                                           sizeof(struct file_security_struct),
-                                           0, SLAB_PANIC, NULL);
        avc_init();
 
        avtab_cache_init();
@@ -7029,6 +6858,9 @@ void selinux_complete_init(void)
    all processes and objects when they are created. */
 DEFINE_LSM(selinux) = {
        .name = "selinux",
+       .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
+       .enabled = &selinux_enabled,
+       .blobs = &selinux_blob_sizes,
        .init = selinux_init,
 };