@@ -1850,6 +1850,7 @@ struct security_hook_list {
struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
+ int lbs_inode;
};
/*
@@ -1905,6 +1906,7 @@ static inline void loadpin_add_hooks(void) { };
#endif
extern int lsm_cred_alloc(struct cred *cred, gfp_t gfp);
+extern int lsm_inode_alloc(struct inode *inode);
#ifdef CONFIG_SECURITY
static inline void lsm_early_cred(struct cred *cred)
@@ -86,6 +86,7 @@ int __init security_init(void)
#ifdef CONFIG_SECURITY_STACKING_DEBUG
pr_info("LSM: cred blob size = %d\n", blob_sizes.lbs_cred);
pr_info("LSM: file blob size = %d\n", blob_sizes.lbs_file);
+ pr_info("LSM: inode blob size = %d\n", blob_sizes.lbs_inode);
#endif
return 0;
@@ -225,6 +226,7 @@ void __init security_add_blobs(struct lsm_blob_sizes *needed)
{
lsm_set_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
lsm_set_size(&needed->lbs_file, &blob_sizes.lbs_file);
+ lsm_set_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
}
/**
@@ -252,6 +254,31 @@ int lsm_file_alloc(struct file *file)
return 0;
}
+/**
+ * lsm_inode_alloc - allocate a composite inode blob
+ * @inode: the inode that needs a blob
+ *
+ * Allocate the inode blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+int lsm_inode_alloc(struct inode *inode)
+{
+#ifdef CONFIG_SECURITY_STACKING_DEBUG
+ if (inode->i_security) {
+ pr_info("%s: Inbound inode blob is not NULL.\n", __func__);
+ return 0;
+ }
+#endif
+ if (blob_sizes.lbs_inode == 0)
+ return 0;
+
+ inode->i_security = kzalloc(blob_sizes.lbs_inode, GFP_KERNEL);
+ if (inode->i_security == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
/*
* Hook list operation macros.
*
@@ -500,7 +527,10 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);
int security_inode_alloc(struct inode *inode)
{
- inode->i_security = NULL;
+ int rc = lsm_inode_alloc(inode);
+
+ if (rc)
+ return rc;
return call_int_hook(inode_alloc_security, 0, inode);
}
@@ -508,6 +538,8 @@ void security_inode_free(struct inode *inode)
{
integrity_inode_free(inode);
call_void_hook(inode_free_security, inode);
+ kfree(inode->i_security);
+ inode->i_security = NULL;
}
int security_dentry_init_security(struct dentry *dentry, int mode,
@@ -125,8 +125,6 @@ __setup("selinux=", selinux_enabled_setup);
int selinux_enabled = 1;
#endif
-static struct kmem_cache *sel_inode_cache;
-
/**
* selinux_secmark_enabled - Check to see if SECMARK is currently enabled
*
@@ -220,20 +218,15 @@ static inline u32 current_sid(void)
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;
-
mutex_init(&isec->lock);
INIT_LIST_HEAD(&isec->list);
isec->inode = inode;
isec->sid = SECINITSID_UNLABELED;
isec->sclass = SECCLASS_FILE;
isec->task_sid = sid;
- inode->i_security = isec;
return 0;
}
@@ -311,14 +304,6 @@ static struct inode_security_struct *backing_inode_security(struct dentry *dentr
return selinux_inode(inode);
}
-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);
-}
-
static void inode_free_security(struct inode *inode)
{
struct inode_security_struct *isec = selinux_inode(inode);
@@ -340,17 +325,6 @@ 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 selinux_inode(inode) 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)
@@ -5991,6 +5965,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
struct lsm_blob_sizes selinux_blob_sizes = {
.lbs_cred = sizeof(struct task_security_struct),
.lbs_file = sizeof(struct file_security_struct),
+ .lbs_inode = sizeof(struct inode_security_struct),
};
static struct security_hook_list selinux_hooks[] = {
@@ -6235,9 +6210,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);
avc_init();
security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
@@ -291,33 +291,16 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
* @skp: a pointer to the Smack label entry to use in the blob
*
*/
-static void init_inode_smack(struct inode_smack *isp, struct smack_known *skp)
+static void init_inode_smack(struct inode *inode, struct smack_known *skp)
{
+ struct inode_smack *isp = smack_inode(inode);
+
isp->smk_inode = skp;
isp->smk_flags = 0;
mutex_init(&isp->smk_lock);
}
/**
- * new_inode_smack - allocate an inode security blob
- * @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)
-{
- struct inode_smack *isp;
-
- isp = kmem_cache_zalloc(smack_inode_cache, GFP_NOFS);
- if (isp == NULL)
- return NULL;
-
- init_inode_smack(isp, skp);
-
- return isp;
-}
-
-/**
* init_task_smack - initialize a task security blob
* @tsp: blob to initialize
* @task: a pointer to the Smack label for the running task
@@ -841,14 +824,16 @@ static int smack_set_mnt_opts(struct super_block *sb,
/*
* Initialize the root inode.
*/
- isp = smack_inode(inode);
- if (isp == NULL) {
- isp = new_inode_smack(sp->smk_root);
- if (isp == NULL)
- return -ENOMEM;
- inode->i_security = isp;
- } else
+ if (inode->i_security == NULL) {
+ i = lsm_inode_alloc(inode);
+ if (i)
+ return i;
+ isp = smack_inode(inode);
+ init_inode_smack(inode, sp->smk_root);
+ } else {
+ isp = smack_inode(inode);
isp->smk_inode = sp->smk_root;
+ }
if (transmute)
isp->smk_flags |= SMK_INODE_TRANSMUTE;
@@ -1006,25 +991,11 @@ 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_security - free an inode blob
- * @inode: the inode with a blob
- *
- * Clears the blob pointer in inode
- */
-static void smack_inode_free_security(struct inode *inode)
-{
- kmem_cache_free(smack_inode_cache, smack_inode(inode));
- inode->i_security = NULL;
-}
-
-/**
* smack_inode_init_security - copy out the smack from an inode
* @inode: the newly created inode
* @dir: containing directory object
@@ -4597,6 +4568,7 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
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),
};
static struct security_hook_list smack_hooks[] = {
@@ -4617,7 +4589,6 @@ static struct security_hook_list smack_hooks[] = {
LSM_HOOK_INIT(bprm_secureexec, smack_bprm_secureexec),
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),
Subject: [PATCH 18/25] LSM: Infrastructure managed inode security blob Move management of the inode security blob from the security modules to the LSM infrastructure. This requires that the modules declare the blob size they require, so the module registration process has to include that. A function lsm_inode_alloc() is provided so that modules can do early allocation of inode blobs during module initialization. Module hooks that are no longer required are removed. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hooks.h | 2 ++ security/security.c | 34 ++++++++++++++++++++++++++- security/selinux/hooks.c | 32 ++------------------------ security/smack/smack_lsm.c | 57 ++++++++++++---------------------------------- 4 files changed, 51 insertions(+), 74 deletions(-)