summaryrefslogtreecommitdiffstats
path: root/security/integrity/ima
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2024-07-10 01:43:06 +0200
committerPaul Moore <paul@paul-moore.com>2024-08-12 21:35:04 +0200
commit63dff3e48871b0583be5032ff8fb7260c349a18c (patch)
tree658e21e7c21fc865f459a1c6dcd9fad7059f0323 /security/integrity/ima
parentlsm: cleanup lsm_hooks.h (diff)
downloadlinux-63dff3e48871b0583be5032ff8fb7260c349a18c.tar.xz
linux-63dff3e48871b0583be5032ff8fb7260c349a18c.zip
lsm: add the inode_free_security_rcu() LSM implementation hook
The LSM framework has an existing inode_free_security() hook which is used by LSMs that manage state associated with an inode, but due to the use of RCU to protect the inode, special care must be taken to ensure that the LSMs do not fully release the inode state until it is safe from a RCU perspective. This patch implements a new inode_free_security_rcu() implementation hook which is called when it is safe to free the LSM's internal inode state. Unfortunately, this new hook does not have access to the inode itself as it may already be released, so the existing inode_free_security() hook is retained for those LSMs which require access to the inode. Cc: stable@vger.kernel.org Reported-by: syzbot+5446fbf332b0602ede0b@syzkaller.appspotmail.com Closes: https://lore.kernel.org/r/00000000000076ba3b0617f65cc8@google.com Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_iint.c20
-rw-r--r--security/integrity/ima/ima_main.c2
3 files changed, 10 insertions, 14 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c51e24d24d1e..3c323ca213d4 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -223,7 +223,7 @@ static inline void ima_inode_set_iint(const struct inode *inode,
struct ima_iint_cache *ima_iint_find(struct inode *inode);
struct ima_iint_cache *ima_inode_get(struct inode *inode);
-void ima_inode_free(struct inode *inode);
+void ima_inode_free_rcu(void *inode_security);
void __init ima_iintcache_init(void);
extern const int read_idmap[];
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index e23412a2c56b..00b249101f98 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -109,22 +109,18 @@ struct ima_iint_cache *ima_inode_get(struct inode *inode)
}
/**
- * ima_inode_free - Called on inode free
- * @inode: Pointer to the inode
+ * ima_inode_free_rcu - Called to free an inode via a RCU callback
+ * @inode_security: The inode->i_security pointer
*
- * Free the iint associated with an inode.
+ * Free the IMA data associated with an inode.
*/
-void ima_inode_free(struct inode *inode)
+void ima_inode_free_rcu(void *inode_security)
{
- struct ima_iint_cache *iint;
-
- if (!IS_IMA(inode))
- return;
-
- iint = ima_iint_find(inode);
- ima_inode_set_iint(inode, NULL);
+ struct ima_iint_cache **iint_p = inode_security + ima_blob_sizes.lbs_inode;
- ima_iint_free(iint);
+ /* *iint_p should be NULL if !IS_IMA(inode) */
+ if (*iint_p)
+ ima_iint_free(*iint_p);
}
static void ima_iint_init_once(void *foo)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index f04f43af651c..5b3394864b21 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -1193,7 +1193,7 @@ static struct security_hook_list ima_hooks[] __ro_after_init = {
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request),
#endif
- LSM_HOOK_INIT(inode_free_security, ima_inode_free),
+ LSM_HOOK_INIT(inode_free_security_rcu, ima_inode_free_rcu),
};
static const struct lsm_id ima_lsmid = {