1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2008 IBM Corporation 4 * 5 * Authors: 6 * Mimi Zohar <zohar@us.ibm.com> 7 * 8 * File: ima_iint.c 9 * - implements the IMA hook: ima_inode_free 10 * - cache integrity information in the inode security blob 11 */ 12 #include <linux/slab.h> 13 14 #include "ima.h" 15 16 static struct kmem_cache *ima_iint_cache __ro_after_init; 17 18 /** 19 * ima_iint_find - Return the iint associated with an inode 20 * @inode: Pointer to the inode 21 * 22 * Return the IMA integrity information (iint) associated with an inode, if the 23 * inode was processed by IMA. 24 * 25 * Return: Found iint or NULL. 26 */ 27 struct ima_iint_cache *ima_iint_find(struct inode *inode) 28 { 29 if (!IS_IMA(inode)) 30 return NULL; 31 32 return ima_inode_get_iint(inode); 33 } 34 35 #define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH + 1) 36 37 /* 38 * It is not clear that IMA should be nested at all, but as long is it measures 39 * files both on overlayfs and on underlying fs, we need to annotate the iint 40 * mutex to avoid lockdep false positives related to IMA + overlayfs. 41 * See ovl_lockdep_annotate_inode_mutex_key() for more details. 42 */ 43 static inline void ima_iint_lockdep_annotate(struct ima_iint_cache *iint, 44 struct inode *inode) 45 { 46 #ifdef CONFIG_LOCKDEP 47 static struct lock_class_key ima_iint_mutex_key[IMA_MAX_NESTING]; 48 49 int depth = inode->i_sb->s_stack_depth; 50 51 if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING)) 52 depth = 0; 53 54 lockdep_set_class(&iint->mutex, &ima_iint_mutex_key[depth]); 55 #endif 56 } 57 58 static void ima_iint_init_always(struct ima_iint_cache *iint, 59 struct inode *inode) 60 { 61 iint->ima_hash = NULL; 62 iint->real_inode.version = 0; 63 iint->flags = 0UL; 64 iint->atomic_flags = 0UL; 65 iint->ima_file_status = INTEGRITY_UNKNOWN; 66 iint->ima_mmap_status = INTEGRITY_UNKNOWN; 67 iint->ima_bprm_status = INTEGRITY_UNKNOWN; 68 iint->ima_read_status = INTEGRITY_UNKNOWN; 69 iint->ima_creds_status = INTEGRITY_UNKNOWN; 70 iint->measured_pcrs = 0; 71 mutex_init(&iint->mutex); 72 ima_iint_lockdep_annotate(iint, inode); 73 } 74 75 static void ima_iint_free(struct ima_iint_cache *iint) 76 { 77 kfree(iint->ima_hash); 78 mutex_destroy(&iint->mutex); 79 kmem_cache_free(ima_iint_cache, iint); 80 } 81 82 /** 83 * ima_inode_get - Find or allocate an iint associated with an inode 84 * @inode: Pointer to the inode 85 * 86 * Find an iint associated with an inode, and allocate a new one if not found. 87 * Caller must lock i_mutex. 88 * 89 * Return: An iint on success, NULL on error. 90 */ 91 struct ima_iint_cache *ima_inode_get(struct inode *inode) 92 { 93 struct ima_iint_cache *iint; 94 95 iint = ima_iint_find(inode); 96 if (iint) 97 return iint; 98 99 iint = kmem_cache_alloc(ima_iint_cache, GFP_NOFS); 100 if (!iint) 101 return NULL; 102 103 ima_iint_init_always(iint, inode); 104 105 inode->i_flags |= S_IMA; 106 ima_inode_set_iint(inode, iint); 107 108 return iint; 109 } 110 111 /** 112 * ima_inode_free_rcu - Called to free an inode via a RCU callback 113 * @inode_security: The inode->i_security pointer 114 * 115 * Free the IMA data associated with an inode. 116 */ 117 void ima_inode_free_rcu(void *inode_security) 118 { 119 struct ima_iint_cache **iint_p = inode_security + ima_blob_sizes.lbs_inode; 120 121 /* *iint_p should be NULL if !IS_IMA(inode) */ 122 if (*iint_p) 123 ima_iint_free(*iint_p); 124 } 125 126 static void ima_iint_init_once(void *foo) 127 { 128 struct ima_iint_cache *iint = (struct ima_iint_cache *)foo; 129 130 memset(iint, 0, sizeof(*iint)); 131 } 132 133 void __init ima_iintcache_init(void) 134 { 135 ima_iint_cache = 136 kmem_cache_create("ima_iint_cache", sizeof(struct ima_iint_cache), 137 0, SLAB_PANIC, ima_iint_init_once); 138 } 139
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.