aboutsummaryrefslogtreecommitdiffstats
path: root/security/security.c
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2018-09-21 20:19:29 -0400
committerKees Cook <keescook@chromium.org>2019-01-08 16:18:45 -0500
commitafb1cbe37440c7f38b9cf46fc331cc9dfd5cce21 (patch)
tree050d1e2575f9a79e20c67634660aef927981694c /security/security.c
parentfb4021b6fb5818df1228a35b7e2645038d01bb9f (diff)
LSM: Infrastructure management of the inode security
Move management of the inode->i_security blob out of the individual security modules and into the security infrastructure. Instead of allocating the blobs from within the modules the modules tell the infrastructure how much space is required, and the space is allocated there. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: Kees Cook <keescook@chromium.org> [kees: adjusted for ordered init series] Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'security/security.c')
-rw-r--r--security/security.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/security/security.c b/security/security.c
index f32d7d2075c6..4989fb65e662 100644
--- a/security/security.c
+++ b/security/security.c
@@ -41,6 +41,7 @@ struct security_hook_heads security_hook_heads __lsm_ro_after_init;
41static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); 41static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
42 42
43static struct kmem_cache *lsm_file_cache; 43static struct kmem_cache *lsm_file_cache;
44static struct kmem_cache *lsm_inode_cache;
44 45
45char *lsm_names; 46char *lsm_names;
46static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init; 47static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
@@ -161,6 +162,13 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
161 162
162 lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred); 163 lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
163 lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file); 164 lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file);
165 /*
166 * The inode blob gets an rcu_head in addition to
167 * what the modules might need.
168 */
169 if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
170 blob_sizes.lbs_inode = sizeof(struct rcu_head);
171 lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
164} 172}
165 173
166/* Prepare LSM for initialization. */ 174/* Prepare LSM for initialization. */
@@ -283,6 +291,7 @@ static void __init ordered_lsm_init(void)
283 291
284 init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); 292 init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
285 init_debug("file blob size = %d\n", blob_sizes.lbs_file); 293 init_debug("file blob size = %d\n", blob_sizes.lbs_file);
294 init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
286 295
287 /* 296 /*
288 * Create any kmem_caches needed for blobs 297 * Create any kmem_caches needed for blobs
@@ -291,6 +300,10 @@ static void __init ordered_lsm_init(void)
291 lsm_file_cache = kmem_cache_create("lsm_file_cache", 300 lsm_file_cache = kmem_cache_create("lsm_file_cache",
292 blob_sizes.lbs_file, 0, 301 blob_sizes.lbs_file, 0,
293 SLAB_PANIC, NULL); 302 SLAB_PANIC, NULL);
303 if (blob_sizes.lbs_inode)
304 lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
305 blob_sizes.lbs_inode, 0,
306 SLAB_PANIC, NULL);
294 307
295 for (lsm = ordered_lsms; *lsm; lsm++) 308 for (lsm = ordered_lsms; *lsm; lsm++)
296 initialize_lsm(*lsm); 309 initialize_lsm(*lsm);
@@ -481,6 +494,27 @@ static int lsm_file_alloc(struct file *file)
481 return 0; 494 return 0;
482} 495}
483 496
497/**
498 * lsm_inode_alloc - allocate a composite inode blob
499 * @inode: the inode that needs a blob
500 *
501 * Allocate the inode blob for all the modules
502 *
503 * Returns 0, or -ENOMEM if memory can't be allocated.
504 */
505int lsm_inode_alloc(struct inode *inode)
506{
507 if (!lsm_inode_cache) {
508 inode->i_security = NULL;
509 return 0;
510 }
511
512 inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS);
513 if (inode->i_security == NULL)
514 return -ENOMEM;
515 return 0;
516}
517
484/* 518/*
485 * Hook list operation macros. 519 * Hook list operation macros.
486 * 520 *
@@ -740,14 +774,40 @@ EXPORT_SYMBOL(security_add_mnt_opt);
740 774
741int security_inode_alloc(struct inode *inode) 775int security_inode_alloc(struct inode *inode)
742{ 776{
743 inode->i_security = NULL; 777 int rc = lsm_inode_alloc(inode);
744 return call_int_hook(inode_alloc_security, 0, inode); 778
779 if (unlikely(rc))
780 return rc;
781 rc = call_int_hook(inode_alloc_security, 0, inode);
782 if (unlikely(rc))
783 security_inode_free(inode);
784 return rc;
785}
786
787static void inode_free_by_rcu(struct rcu_head *head)
788{
789 /*
790 * The rcu head is at the start of the inode blob
791 */
792 kmem_cache_free(lsm_inode_cache, head);
745} 793}
746 794
747void security_inode_free(struct inode *inode) 795void security_inode_free(struct inode *inode)
748{ 796{
749 integrity_inode_free(inode); 797 integrity_inode_free(inode);
750 call_void_hook(inode_free_security, inode); 798 call_void_hook(inode_free_security, inode);
799 /*
800 * The inode may still be referenced in a path walk and
801 * a call to security_inode_permission() can be made
802 * after inode_free_security() is called. Ideally, the VFS
803 * wouldn't do this, but fixing that is a much harder
804 * job. For now, simply free the i_security via RCU, and
805 * leave the current inode->i_security pointer intact.
806 * The inode will be freed after the RCU grace period too.
807 */
808 if (inode->i_security)
809 call_rcu((struct rcu_head *)inode->i_security,
810 inode_free_by_rcu);
751} 811}
752 812
753int security_dentry_init_security(struct dentry *dentry, int mode, 813int security_dentry_init_security(struct dentry *dentry, int mode,