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 */
ima_iint_find(struct inode * inode)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 */
ima_iint_lockdep_annotate(struct ima_iint_cache * iint,struct inode * inode)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
ima_iint_init_always(struct ima_iint_cache * iint,struct inode * inode)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
ima_iint_free(struct ima_iint_cache * iint)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 */
ima_inode_get(struct inode * inode)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 */
ima_inode_free_rcu(void * inode_security)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
ima_iint_init_once(void * foo)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
ima_iintcache_init(void)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