mirror of
https://github.com/torvalds/linux
synced 2024-07-21 02:23:16 +00:00
integrity-v6.7
-----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQQdXVVFGN5XqKr1Hj7LwZzRsCrn5QUCZUDyWhQcem9oYXJAbGlu dXguaWJtLmNvbQAKCRDLwZzRsCrn5QtIAPwLSdHw2qix1A6lMhbRiXqFOWINHcTF DMtZkiPmpeuTKAEA0KaXfddKq5OC5S/ixPEEZCVqOq2ixxfMDhudyoh/qQs= =lh3g -----END PGP SIGNATURE----- Merge tag 'integrity-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity 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
This commit is contained in:
commit
ca219be012
|
@ -88,7 +88,21 @@ config SECONDARY_TRUSTED_KEYRING
|
||||||
help
|
help
|
||||||
If set, provide a keyring to which extra keys may be added, provided
|
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
|
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
|
config SYSTEM_BLACKLIST_KEYRING
|
||||||
bool "Provide system-wide ring of blacklisted keys"
|
bool "Provide system-wide ring of blacklisted keys"
|
||||||
|
|
|
@ -102,6 +102,10 @@ int restrict_link_by_signature(struct key *dest_keyring,
|
||||||
|
|
||||||
if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
|
if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
|
||||||
ret = -ENOKEY;
|
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
|
else
|
||||||
ret = verify_signature(key, sig);
|
ret = verify_signature(key, sig);
|
||||||
key_put(key);
|
key_put(key);
|
||||||
|
|
|
@ -1499,7 +1499,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||||
#ifdef CONFIG_FS_POSIX_ACL
|
#ifdef CONFIG_FS_POSIX_ACL
|
||||||
sb->s_flags |= SB_POSIXACL;
|
sb->s_flags |= SB_POSIXACL;
|
||||||
#endif
|
#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
|
* Ensure that umask handling is done by the filesystems used
|
||||||
* for the the upper layer instead of overlayfs as that would
|
* for the the upper layer instead of overlayfs as that would
|
||||||
|
|
|
@ -34,10 +34,10 @@ config INTEGRITY_ASYMMETRIC_KEYS
|
||||||
bool "Enable asymmetric keys support"
|
bool "Enable asymmetric keys support"
|
||||||
depends on INTEGRITY_SIGNATURE
|
depends on INTEGRITY_SIGNATURE
|
||||||
default n
|
default n
|
||||||
select ASYMMETRIC_KEY_TYPE
|
select ASYMMETRIC_KEY_TYPE
|
||||||
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||||
select CRYPTO_RSA
|
select CRYPTO_RSA
|
||||||
select X509_CERTIFICATE_PARSER
|
select X509_CERTIFICATE_PARSER
|
||||||
help
|
help
|
||||||
This option enables digital signature verification using
|
This option enables digital signature verification using
|
||||||
asymmetric keys.
|
asymmetric keys.
|
||||||
|
@ -53,14 +53,14 @@ config INTEGRITY_TRUSTED_KEYRING
|
||||||
keyring.
|
keyring.
|
||||||
|
|
||||||
config INTEGRITY_PLATFORM_KEYRING
|
config INTEGRITY_PLATFORM_KEYRING
|
||||||
bool "Provide keyring for platform/firmware trusted keys"
|
bool "Provide keyring for platform/firmware trusted keys"
|
||||||
depends on INTEGRITY_ASYMMETRIC_KEYS
|
depends on INTEGRITY_ASYMMETRIC_KEYS
|
||||||
depends on SYSTEM_BLACKLIST_KEYRING
|
depends on SYSTEM_BLACKLIST_KEYRING
|
||||||
help
|
help
|
||||||
Provide a separate, distinct keyring for platform trusted keys, which
|
Provide a separate, distinct keyring for platform trusted keys, which
|
||||||
the kernel automatically populates during initialization from values
|
the kernel automatically populates during initialization from values
|
||||||
provided by the platform for verifying the kexec'ed kerned image
|
provided by the platform for verifying the kexec'ed kerned image
|
||||||
and, possibly, the initramfs signature.
|
and, possibly, the initramfs signature.
|
||||||
|
|
||||||
config INTEGRITY_MACHINE_KEYRING
|
config INTEGRITY_MACHINE_KEYRING
|
||||||
bool "Provide a keyring to which Machine Owner Keys may be added"
|
bool "Provide a keyring to which Machine Owner Keys may be added"
|
||||||
|
@ -69,10 +69,10 @@ config INTEGRITY_MACHINE_KEYRING
|
||||||
depends on SYSTEM_BLACKLIST_KEYRING
|
depends on SYSTEM_BLACKLIST_KEYRING
|
||||||
depends on LOAD_UEFI_KEYS || LOAD_PPC_KEYS
|
depends on LOAD_UEFI_KEYS || LOAD_PPC_KEYS
|
||||||
help
|
help
|
||||||
If set, provide a keyring to which Machine Owner Keys (MOK) may
|
If set, provide a keyring to which Machine Owner Keys (MOK) may
|
||||||
be added. This keyring shall contain just MOK keys. Unlike keys
|
be added. This keyring shall contain just MOK keys. Unlike keys
|
||||||
in the platform keyring, keys contained in the .machine keyring will
|
in the platform keyring, keys contained in the .machine keyring will
|
||||||
be trusted within the kernel.
|
be trusted within the kernel.
|
||||||
|
|
||||||
config INTEGRITY_CA_MACHINE_KEYRING
|
config INTEGRITY_CA_MACHINE_KEYRING
|
||||||
bool "Enforce Machine Keyring CA Restrictions"
|
bool "Enforce Machine Keyring CA Restrictions"
|
||||||
|
@ -97,14 +97,14 @@ config INTEGRITY_CA_MACHINE_KEYRING_MAX
|
||||||
.platform keyring.
|
.platform keyring.
|
||||||
|
|
||||||
config LOAD_UEFI_KEYS
|
config LOAD_UEFI_KEYS
|
||||||
depends on INTEGRITY_PLATFORM_KEYRING
|
depends on INTEGRITY_PLATFORM_KEYRING
|
||||||
depends on EFI
|
depends on EFI
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
config LOAD_IPL_KEYS
|
config LOAD_IPL_KEYS
|
||||||
depends on INTEGRITY_PLATFORM_KEYRING
|
depends on INTEGRITY_PLATFORM_KEYRING
|
||||||
depends on S390
|
depends on S390
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
config LOAD_PPC_KEYS
|
config LOAD_PPC_KEYS
|
||||||
bool "Enable loading of platform and blacklisted keys for POWER"
|
bool "Enable loading of platform and blacklisted keys for POWER"
|
||||||
|
|
|
@ -66,9 +66,32 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
|
||||||
return iint;
|
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->ima_hash = NULL;
|
||||||
iint->version = 0;
|
iint->version = 0;
|
||||||
iint->flags = 0UL;
|
iint->flags = 0UL;
|
||||||
|
@ -80,6 +103,14 @@ static void iint_free(struct integrity_iint_cache *iint)
|
||||||
iint->ima_creds_status = INTEGRITY_UNKNOWN;
|
iint->ima_creds_status = INTEGRITY_UNKNOWN;
|
||||||
iint->evm_status = INTEGRITY_UNKNOWN;
|
iint->evm_status = INTEGRITY_UNKNOWN;
|
||||||
iint->measured_pcrs = 0;
|
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);
|
kmem_cache_free(iint_cache, iint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +135,8 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
|
||||||
if (!iint)
|
if (!iint)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
iint_init_always(iint, inode);
|
||||||
|
|
||||||
write_lock(&integrity_iint_lock);
|
write_lock(&integrity_iint_lock);
|
||||||
|
|
||||||
p = &integrity_iint_tree.rb_node;
|
p = &integrity_iint_tree.rb_node;
|
||||||
|
@ -153,25 +186,18 @@ void integrity_inode_free(struct inode *inode)
|
||||||
iint_free(iint);
|
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;
|
struct integrity_iint_cache *iint = (struct integrity_iint_cache *) foo;
|
||||||
|
|
||||||
memset(iint, 0, sizeof(*iint));
|
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)
|
static int __init integrity_iintcache_init(void)
|
||||||
{
|
{
|
||||||
iint_cache =
|
iint_cache =
|
||||||
kmem_cache_create("iint_cache", sizeof(struct integrity_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;
|
return 0;
|
||||||
}
|
}
|
||||||
DEFINE_LSM(integrity) = {
|
DEFINE_LSM(integrity) = {
|
||||||
|
|
|
@ -243,6 +243,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
||||||
{
|
{
|
||||||
const char *audit_cause = "failed";
|
const char *audit_cause = "failed";
|
||||||
struct inode *inode = file_inode(file);
|
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;
|
const char *filename = file->f_path.dentry->d_name.name;
|
||||||
struct ima_max_digest_data hash;
|
struct ima_max_digest_data hash;
|
||||||
struct kstat stat;
|
struct kstat stat;
|
||||||
|
@ -302,6 +303,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
||||||
iint->ima_hash = tmpbuf;
|
iint->ima_hash = tmpbuf;
|
||||||
memcpy(iint->ima_hash, &hash, length);
|
memcpy(iint->ima_hash, &hash, length);
|
||||||
iint->version = i_version;
|
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) */
|
/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
|
||||||
if (!result)
|
if (!result)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/xattr.h>
|
#include <linux/xattr.h>
|
||||||
#include <linux/ima.h>
|
#include <linux/ima.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/iversion.h>
|
||||||
|
|
||||||
#include "ima.h"
|
#include "ima.h"
|
||||||
|
|
||||||
|
@ -207,7 +208,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
||||||
u32 secid, char *buf, loff_t size, int mask,
|
u32 secid, char *buf, loff_t size, int mask,
|
||||||
enum ima_hooks func)
|
enum ima_hooks func)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *backing_inode, *inode = file_inode(file);
|
||||||
struct integrity_iint_cache *iint = NULL;
|
struct integrity_iint_cache *iint = NULL;
|
||||||
struct ima_template_desc *template_desc = NULL;
|
struct ima_template_desc *template_desc = NULL;
|
||||||
char *pathbuf = NULL;
|
char *pathbuf = NULL;
|
||||||
|
@ -284,6 +285,19 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
||||||
iint->measured_pcrs = 0;
|
iint->measured_pcrs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Detect and re-evaluate changes made to the backing file. */
|
||||||
|
backing_inode = d_real_inode(file_dentry(file));
|
||||||
|
if (backing_inode != inode &&
|
||||||
|
(action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
|
||||||
|
if (!IS_I_VERSION(backing_inode) ||
|
||||||
|
backing_inode->i_sb->s_dev != iint->real_dev ||
|
||||||
|
backing_inode->i_ino != iint->real_ino ||
|
||||||
|
!inode_eq_iversion(backing_inode, iint->version)) {
|
||||||
|
iint->flags &= ~IMA_DONE_MASK;
|
||||||
|
iint->measured_pcrs = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine if already appraised/measured based on bitmask
|
/* Determine if already appraised/measured based on bitmask
|
||||||
* (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,
|
* (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,
|
||||||
* IMA_AUDIT, IMA_AUDITED)
|
* IMA_AUDIT, IMA_AUDITED)
|
||||||
|
|
|
@ -164,6 +164,8 @@ struct integrity_iint_cache {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned long measured_pcrs;
|
unsigned long measured_pcrs;
|
||||||
unsigned long atomic_flags;
|
unsigned long atomic_flags;
|
||||||
|
unsigned long real_ino;
|
||||||
|
dev_t real_dev;
|
||||||
enum integrity_status ima_file_status:4;
|
enum integrity_status ima_file_status:4;
|
||||||
enum integrity_status ima_mmap_status:4;
|
enum integrity_status ima_mmap_status:4;
|
||||||
enum integrity_status ima_bprm_status:4;
|
enum integrity_status ima_bprm_status:4;
|
||||||
|
|
Loading…
Reference in a new issue