Commit ca219be0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull integrity updates from Mimi Zohar:
 "Four integrity changes: two IMA-overlay updates, an integrity Kconfig
  cleanup, and a secondary keyring update"

* tag 'integrity-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
  ima: detect changes to the backing overlay file
  certs: Only allow certs signed by keys on the builtin keyring
  integrity: fix indentation of config attributes
  ima: annotate iint mutex to avoid lockdep false positive warnings
parents 21e80f38 b836c4d2
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -88,7 +88,21 @@ config SECONDARY_TRUSTED_KEYRING
	help
	  If set, provide a keyring to which extra keys may be added, provided
	  those keys are not blacklisted and are vouched for by a key built
	  into the kernel or already in the secondary trusted keyring.
	  into the kernel, machine keyring (if configured), or already in the
	  secondary trusted keyring.

config SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN
	bool "Only allow additional certs signed by keys on the builtin trusted keyring"
	depends on SECONDARY_TRUSTED_KEYRING
	help
	  If set, only certificates signed by keys on the builtin trusted
	  keyring may be loaded onto the secondary trusted keyring.

	  Note: The machine keyring, if configured, will be linked to the
	  secondary keyring.  When enabling this option, it is recommended
	  to also configure INTEGRITY_CA_MACHINE_KEYRING_MAX to prevent
	  linking code signing keys with imputed trust to the secondary
	  trusted keyring.

config SYSTEM_BLACKLIST_KEYRING
	bool "Provide system-wide ring of blacklisted keys"
+4 −0
Original line number Diff line number Diff line
@@ -102,6 +102,10 @@ int restrict_link_by_signature(struct key *dest_keyring,

	if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
		ret = -ENOKEY;
	else if (IS_BUILTIN(CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN) &&
		 !strcmp(dest_keyring->description, ".secondary_trusted_keys") &&
		 !test_bit(KEY_FLAG_BUILTIN, &key->flags))
		ret = -ENOKEY;
	else
		ret = verify_signature(key, sig);
	key_put(key);
+1 −1
Original line number Diff line number Diff line
@@ -1499,7 +1499,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
#ifdef CONFIG_FS_POSIX_ACL
	sb->s_flags |= SB_POSIXACL;
#endif
	sb->s_iflags |= SB_I_SKIP_SYNC | SB_I_IMA_UNVERIFIABLE_SIGNATURE;
	sb->s_iflags |= SB_I_SKIP_SYNC;
	/*
	 * Ensure that umask handling is done by the filesystems used
	 * for the the upper layer instead of overlayfs as that would
+37 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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);
}

@@ -104,6 +135,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;
@@ -153,25 +186,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) = {
+5 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
{
	const char *audit_cause = "failed";
	struct inode *inode = file_inode(file);
	struct inode *real_inode = d_real_inode(file_dentry(file));
	const char *filename = file->f_path.dentry->d_name.name;
	struct ima_max_digest_data hash;
	struct kstat stat;
@@ -302,6 +303,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
	iint->ima_hash = tmpbuf;
	memcpy(iint->ima_hash, &hash, length);
	iint->version = i_version;
	if (real_inode != inode) {
		iint->real_ino = real_inode->i_ino;
		iint->real_dev = real_inode->i_sb->s_dev;
	}

	/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
	if (!result)
Loading