Skip to content

Commit ddc2f88

Browse files
amir73ilsmb49
authored andcommitted
ima: annotate iint mutex to avoid lockdep false positive warnings
BugLink: https://bugs.launchpad.net/bugs/2050038 commit e044374 upstream. It is not clear that IMA should be nested at all, but as long is it measures files both on overlayfs and on underlying fs, we need to annotate the iint mutex to avoid lockdep false positives related to IMA + overlayfs, same as overlayfs annotates the inode mutex. Reported-and-tested-by: syzbot+b42fe626038981fb7bfa@syzkaller.appspotmail.com Signed-off-by: Amir Goldstein <amir73il@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Mimi Zohar <zohar@linux.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Portia Stephens <portia.stephens@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 2482342 commit ddc2f88

File tree

1 file changed

+37
-11
lines changed

1 file changed

+37
-11
lines changed

security/integrity/iint.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,32 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
6666
return iint;
6767
}
6868

69-
static void iint_free(struct integrity_iint_cache *iint)
69+
#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH+1)
70+
71+
/*
72+
* It is not clear that IMA should be nested at all, but as long is it measures
73+
* files both on overlayfs and on underlying fs, we need to annotate the iint
74+
* mutex to avoid lockdep false positives related to IMA + overlayfs.
75+
* See ovl_lockdep_annotate_inode_mutex_key() for more details.
76+
*/
77+
static inline void iint_lockdep_annotate(struct integrity_iint_cache *iint,
78+
struct inode *inode)
79+
{
80+
#ifdef CONFIG_LOCKDEP
81+
static struct lock_class_key iint_mutex_key[IMA_MAX_NESTING];
82+
83+
int depth = inode->i_sb->s_stack_depth;
84+
85+
if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING))
86+
depth = 0;
87+
88+
lockdep_set_class(&iint->mutex, &iint_mutex_key[depth]);
89+
#endif
90+
}
91+
92+
static void iint_init_always(struct integrity_iint_cache *iint,
93+
struct inode *inode)
7094
{
71-
kfree(iint->ima_hash);
7295
iint->ima_hash = NULL;
7396
iint->version = 0;
7497
iint->flags = 0UL;
@@ -80,6 +103,14 @@ static void iint_free(struct integrity_iint_cache *iint)
80103
iint->ima_creds_status = INTEGRITY_UNKNOWN;
81104
iint->evm_status = INTEGRITY_UNKNOWN;
82105
iint->measured_pcrs = 0;
106+
mutex_init(&iint->mutex);
107+
iint_lockdep_annotate(iint, inode);
108+
}
109+
110+
static void iint_free(struct integrity_iint_cache *iint)
111+
{
112+
kfree(iint->ima_hash);
113+
mutex_destroy(&iint->mutex);
83114
kmem_cache_free(iint_cache, iint);
84115
}
85116

@@ -112,6 +143,8 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
112143
if (!iint)
113144
return NULL;
114145

146+
iint_init_always(iint, inode);
147+
115148
write_lock(&integrity_iint_lock);
116149

117150
p = &integrity_iint_tree.rb_node;
@@ -161,25 +194,18 @@ void integrity_inode_free(struct inode *inode)
161194
iint_free(iint);
162195
}
163196

164-
static void init_once(void *foo)
197+
static void iint_init_once(void *foo)
165198
{
166199
struct integrity_iint_cache *iint = (struct integrity_iint_cache *) foo;
167200

168201
memset(iint, 0, sizeof(*iint));
169-
iint->ima_file_status = INTEGRITY_UNKNOWN;
170-
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
171-
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
172-
iint->ima_read_status = INTEGRITY_UNKNOWN;
173-
iint->ima_creds_status = INTEGRITY_UNKNOWN;
174-
iint->evm_status = INTEGRITY_UNKNOWN;
175-
mutex_init(&iint->mutex);
176202
}
177203

178204
static int __init integrity_iintcache_init(void)
179205
{
180206
iint_cache =
181207
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
182-
0, SLAB_PANIC, init_once);
208+
0, SLAB_PANIC, iint_init_once);
183209
return 0;
184210
}
185211
DEFINE_LSM(integrity) = {

0 commit comments

Comments
 (0)