diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/lsm.h | 1 | ||||
| -rw-r--r-- | security/lsm_init.c | 9 | ||||
| -rw-r--r-- | security/security.c | 102 |
3 files changed, 112 insertions, 0 deletions
diff --git a/security/lsm.h b/security/lsm.h index db77cc83e158..32f808ad4335 100644 --- a/security/lsm.h +++ b/security/lsm.h @@ -29,6 +29,7 @@ extern struct lsm_blob_sizes blob_sizes; /* LSM blob caches */ extern struct kmem_cache *lsm_file_cache; +extern struct kmem_cache *lsm_backing_file_cache; extern struct kmem_cache *lsm_inode_cache; /* LSM blob allocators */ diff --git a/security/lsm_init.c b/security/lsm_init.c index 573e2a7250c4..7c0fd17f1601 100644 --- a/security/lsm_init.c +++ b/security/lsm_init.c @@ -293,6 +293,8 @@ static void __init lsm_prepare(struct lsm_info *lsm) blobs = lsm->blobs; lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred); lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file); + lsm_blob_size_update(&blobs->lbs_backing_file, + &blob_sizes.lbs_backing_file); lsm_blob_size_update(&blobs->lbs_ib, &blob_sizes.lbs_ib); /* inode blob gets an rcu_head in addition to LSM blobs. */ if (blobs->lbs_inode && blob_sizes.lbs_inode == 0) @@ -441,6 +443,8 @@ int __init security_init(void) if (lsm_debug) { lsm_pr("blob(cred) size %d\n", blob_sizes.lbs_cred); lsm_pr("blob(file) size %d\n", blob_sizes.lbs_file); + lsm_pr("blob(backing_file) size %d\n", + blob_sizes.lbs_backing_file); lsm_pr("blob(ib) size %d\n", blob_sizes.lbs_ib); lsm_pr("blob(inode) size %d\n", blob_sizes.lbs_inode); lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc); @@ -462,6 +466,11 @@ int __init security_init(void) lsm_file_cache = kmem_cache_create("lsm_file_cache", blob_sizes.lbs_file, 0, SLAB_PANIC, NULL); + if (blob_sizes.lbs_backing_file) + lsm_backing_file_cache = kmem_cache_create( + "lsm_backing_file_cache", + blob_sizes.lbs_backing_file, + 0, SLAB_PANIC, NULL); if (blob_sizes.lbs_inode) lsm_inode_cache = kmem_cache_create("lsm_inode_cache", blob_sizes.lbs_inode, 0, diff --git a/security/security.c b/security/security.c index 67af9228c4e9..680113625451 100644 --- a/security/security.c +++ b/security/security.c @@ -81,6 +81,7 @@ const struct lsm_id *lsm_idlist[MAX_LSM_COUNT]; struct lsm_blob_sizes blob_sizes; struct kmem_cache *lsm_file_cache; +struct kmem_cache *lsm_backing_file_cache; struct kmem_cache *lsm_inode_cache; #define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX @@ -173,6 +174,30 @@ static int lsm_file_alloc(struct file *file) } /** + * lsm_backing_file_alloc - allocate a composite backing file blob + * @backing_file: the backing file + * + * Allocate the backing file blob for all the modules. + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +static int lsm_backing_file_alloc(struct file *backing_file) +{ + void *blob; + + if (!lsm_backing_file_cache) { + backing_file_set_security(backing_file, NULL); + return 0; + } + + blob = kmem_cache_zalloc(lsm_backing_file_cache, GFP_KERNEL); + backing_file_set_security(backing_file, blob); + if (!blob) + return -ENOMEM; + return 0; +} + +/** * lsm_blob_alloc - allocate a composite blob * @dest: the destination for the blob * @size: the size of the blob @@ -2418,6 +2443,57 @@ void security_file_free(struct file *file) } /** + * security_backing_file_alloc() - Allocate and setup a backing file blob + * @backing_file: the backing file + * @user_file: the associated user visible file + * + * Allocate a backing file LSM blob and perform any necessary initialization of + * the LSM blob. There will be some operations where the LSM will not have + * access to @user_file after this point, so any important state associated + * with @user_file that is important to the LSM should be captured in the + * backing file's LSM blob. + * + * LSM's should avoid taking a reference to @user_file in this hook as it will + * result in problems later when the system attempts to drop/put the file + * references due to a circular dependency. + * + * Return: Return 0 if the hook is successful, negative values otherwise. + */ +int security_backing_file_alloc(struct file *backing_file, + const struct file *user_file) +{ + int rc; + + rc = lsm_backing_file_alloc(backing_file); + if (rc) + return rc; + rc = call_int_hook(backing_file_alloc, backing_file, user_file); + if (unlikely(rc)) + security_backing_file_free(backing_file); + + return rc; +} + +/** + * security_backing_file_free() - Free a backing file blob + * @backing_file: the backing file + * + * Free any LSM state associate with a backing file's LSM blob, including the + * blob itself. + */ +void security_backing_file_free(struct file *backing_file) +{ + void *blob = backing_file_security(backing_file); + + call_void_hook(backing_file_free, backing_file); + + if (blob) { + backing_file_set_security(backing_file, NULL); + kmem_cache_free(lsm_backing_file_cache, blob); + } +} + +/** * security_file_ioctl() - Check if an ioctl is allowed * @file: associated file * @cmd: ioctl cmd @@ -2506,6 +2582,32 @@ int security_mmap_file(struct file *file, unsigned long prot, } /** + * security_mmap_backing_file - Check if mmap'ing a backing file is allowed + * @vma: the vm_area_struct for the mmap'd region + * @backing_file: the backing file being mmap'd + * @user_file: the user file being mmap'd + * + * Check permissions for a mmap operation on a stacked filesystem. This hook + * is called after the security_mmap_file() and is responsible for authorizing + * the mmap on @backing_file. It is important to note that the mmap operation + * on @user_file has already been authorized and the @vma->vm_file has been + * set to @backing_file. + * + * Return: Returns 0 if permission is granted. + */ +int security_mmap_backing_file(struct vm_area_struct *vma, + struct file *backing_file, + struct file *user_file) +{ + /* recommended by the stackable filesystem devs */ + if (WARN_ON_ONCE(!(backing_file->f_mode & FMODE_BACKING))) + return -EIO; + + return call_int_hook(mmap_backing_file, vma, backing_file, user_file); +} +EXPORT_SYMBOL_GPL(security_mmap_backing_file); + +/** * security_mmap_addr() - Check if mmap'ing an address is allowed * @addr: address * |
