Skip to content

Commit

Permalink
ima: annotate iint mutex to avoid lockdep false positive warnings
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
amir73il authored and gregkh committed Nov 28, 2023
1 parent db98de0 commit 2c63b9d
Showing 1 changed file with 37 additions and 11 deletions.
48 changes: 37 additions & 11 deletions security/integrity/iint.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,32 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
return iint;
}

static void iint_free(struct integrity_iint_cache *iint)
#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH+1)

/*
* 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.
* See ovl_lockdep_annotate_inode_mutex_key() for more details.
*/
static inline void iint_lockdep_annotate(struct integrity_iint_cache *iint,
struct inode *inode)
{
#ifdef CONFIG_LOCKDEP
static struct lock_class_key iint_mutex_key[IMA_MAX_NESTING];

int depth = inode->i_sb->s_stack_depth;

if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING))
depth = 0;

lockdep_set_class(&iint->mutex, &iint_mutex_key[depth]);
#endif
}

static void iint_init_always(struct integrity_iint_cache *iint,
struct inode *inode)
{
kfree(iint->ima_hash);
iint->ima_hash = NULL;
iint->version = 0;
iint->flags = 0UL;
Expand All @@ -80,6 +103,14 @@ static void iint_free(struct integrity_iint_cache *iint)
iint->ima_creds_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
iint->measured_pcrs = 0;
mutex_init(&iint->mutex);
iint_lockdep_annotate(iint, inode);
}

static void iint_free(struct integrity_iint_cache *iint)
{
kfree(iint->ima_hash);
mutex_destroy(&iint->mutex);
kmem_cache_free(iint_cache, iint);
}

Expand Down Expand Up @@ -112,6 +143,8 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
if (!iint)
return NULL;

iint_init_always(iint, inode);

write_lock(&integrity_iint_lock);

p = &integrity_iint_tree.rb_node;
Expand Down Expand Up @@ -161,25 +194,18 @@ void integrity_inode_free(struct inode *inode)
iint_free(iint);
}

static void init_once(void *foo)
static void iint_init_once(void *foo)
{
struct integrity_iint_cache *iint = (struct integrity_iint_cache *) foo;

memset(iint, 0, sizeof(*iint));
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->ima_creds_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
mutex_init(&iint->mutex);
}

static int __init integrity_iintcache_init(void)
{
iint_cache =
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
0, SLAB_PANIC, init_once);
0, SLAB_PANIC, iint_init_once);
return 0;
}
DEFINE_LSM(integrity) = {
Expand Down

0 comments on commit 2c63b9d

Please sign in to comment.