Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next-integrity
From: Mimi Zohar <zohar@linux.ibm.com> Linux 5.0 introduced the platform keyring to allow verifying the IMA kexec kernel image signature using the pre-boot keys. This pull request similarly makes keys on the platform keyring accessible for verifying the PE kernel image signature.* Also included in this pull request is a new IMA hook that tags tmp files, in policy, indicating the file hash needs to be calculated. The remaining patches are cleanup. *Upstream commit "993a110319a4 (x86/kexec: Fix a kexec_file_load() failure)" is required for testing.
This commit is contained in:
commit
2e884fc975
|
@ -531,9 +531,17 @@ static int bzImage64_cleanup(void *loader_data)
|
||||||
#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
|
#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
|
||||||
static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
|
static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
|
||||||
{
|
{
|
||||||
return verify_pefile_signature(kernel, kernel_len,
|
int ret;
|
||||||
VERIFY_USE_SECONDARY_KEYRING,
|
|
||||||
VERIFYING_KEXEC_PE_SIGNATURE);
|
ret = verify_pefile_signature(kernel, kernel_len,
|
||||||
|
VERIFY_USE_SECONDARY_KEYRING,
|
||||||
|
VERIFYING_KEXEC_PE_SIGNATURE);
|
||||||
|
if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) {
|
||||||
|
ret = verify_pefile_signature(kernel, kernel_len,
|
||||||
|
VERIFY_USE_PLATFORM_KEYRING,
|
||||||
|
VERIFYING_KEXEC_PE_SIGNATURE);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ static struct key *builtin_trusted_keys;
|
||||||
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
|
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
|
||||||
static struct key *secondary_trusted_keys;
|
static struct key *secondary_trusted_keys;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
|
||||||
|
static struct key *platform_trusted_keys;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern __initconst const u8 system_certificate_list[];
|
extern __initconst const u8 system_certificate_list[];
|
||||||
extern __initconst const unsigned long system_certificate_list_size;
|
extern __initconst const unsigned long system_certificate_list_size;
|
||||||
|
@ -237,11 +240,22 @@ int verify_pkcs7_signature(const void *data, size_t len,
|
||||||
#else
|
#else
|
||||||
trusted_keys = builtin_trusted_keys;
|
trusted_keys = builtin_trusted_keys;
|
||||||
#endif
|
#endif
|
||||||
|
} else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) {
|
||||||
|
#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
|
||||||
|
trusted_keys = platform_trusted_keys;
|
||||||
|
#else
|
||||||
|
trusted_keys = NULL;
|
||||||
|
#endif
|
||||||
|
if (!trusted_keys) {
|
||||||
|
ret = -ENOKEY;
|
||||||
|
pr_devel("PKCS#7 platform keyring is not available\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret = pkcs7_validate_trust(pkcs7, trusted_keys);
|
ret = pkcs7_validate_trust(pkcs7, trusted_keys);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == -ENOKEY)
|
if (ret == -ENOKEY)
|
||||||
pr_err("PKCS#7 signature not signed with a trusted key\n");
|
pr_devel("PKCS#7 signature not signed with a trusted key\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,3 +280,10 @@ int verify_pkcs7_signature(const void *data, size_t len,
|
||||||
EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
|
EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
|
||||||
|
|
||||||
#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
|
#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
|
||||||
|
|
||||||
|
#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
|
||||||
|
void __init set_platform_trusted_keys(struct key *keyring)
|
||||||
|
{
|
||||||
|
platform_trusted_keys = keyring;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -3462,6 +3462,7 @@ struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag)
|
||||||
inode->i_state |= I_LINKABLE;
|
inode->i_state |= I_LINKABLE;
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
}
|
}
|
||||||
|
ima_post_create_tmpfile(inode);
|
||||||
return child;
|
return child;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
|
|
|
@ -61,5 +61,13 @@ static inline struct key *get_ima_blacklist_keyring(void)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IMA_BLACKLIST_KEYRING */
|
#endif /* CONFIG_IMA_BLACKLIST_KEYRING */
|
||||||
|
|
||||||
|
#if defined(CONFIG_INTEGRITY_PLATFORM_KEYRING) && \
|
||||||
|
defined(CONFIG_SYSTEM_TRUSTED_KEYRING)
|
||||||
|
extern void __init set_platform_trusted_keys(struct key *keyring);
|
||||||
|
#else
|
||||||
|
static inline void set_platform_trusted_keys(struct key *keyring)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _KEYS_SYSTEM_KEYRING_H */
|
#endif /* _KEYS_SYSTEM_KEYRING_H */
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct linux_binprm;
|
||||||
#ifdef CONFIG_IMA
|
#ifdef CONFIG_IMA
|
||||||
extern int ima_bprm_check(struct linux_binprm *bprm);
|
extern int ima_bprm_check(struct linux_binprm *bprm);
|
||||||
extern int ima_file_check(struct file *file, int mask);
|
extern int ima_file_check(struct file *file, int mask);
|
||||||
|
extern void ima_post_create_tmpfile(struct inode *inode);
|
||||||
extern void ima_file_free(struct file *file);
|
extern void ima_file_free(struct file *file);
|
||||||
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
||||||
extern int ima_load_data(enum kernel_load_data_id id);
|
extern int ima_load_data(enum kernel_load_data_id id);
|
||||||
|
@ -56,6 +57,10 @@ static inline int ima_file_check(struct file *file, int mask)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ima_post_create_tmpfile(struct inode *inode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ima_file_free(struct file *file)
|
static inline void ima_file_free(struct file *file)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* should be used.
|
* should be used.
|
||||||
*/
|
*/
|
||||||
#define VERIFY_USE_SECONDARY_KEYRING ((struct key *)1UL)
|
#define VERIFY_USE_SECONDARY_KEYRING ((struct key *)1UL)
|
||||||
|
#define VERIFY_USE_PLATFORM_KEYRING ((struct key *)2UL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The use to which an asymmetric key is being put.
|
* The use to which an asymmetric key is being put.
|
||||||
|
|
|
@ -87,6 +87,9 @@ static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
|
||||||
pr_info("Can't allocate %s keyring (%d)\n",
|
pr_info("Can't allocate %s keyring (%d)\n",
|
||||||
keyring_name[id], err);
|
keyring_name[id], err);
|
||||||
keyring[id] = NULL;
|
keyring[id] = NULL;
|
||||||
|
} else {
|
||||||
|
if (id == INTEGRITY_KEYRING_PLATFORM)
|
||||||
|
set_platform_trusted_keys(keyring[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -173,8 +173,7 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
|
||||||
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
|
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
|
||||||
if ((evm_hmac_attrs & EVM_ATTR_FSUUID) &&
|
if ((evm_hmac_attrs & EVM_ATTR_FSUUID) &&
|
||||||
type != EVM_XATTR_PORTABLE_DIGSIG)
|
type != EVM_XATTR_PORTABLE_DIGSIG)
|
||||||
crypto_shash_update(desc, &inode->i_sb->s_uuid.b[0],
|
crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE);
|
||||||
sizeof(inode->i_sb->s_uuid));
|
|
||||||
crypto_shash_final(desc, digest);
|
crypto_shash_final(desc, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -563,7 +563,6 @@ static int __init init_evm(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct list_head *pos, *q;
|
struct list_head *pos, *q;
|
||||||
struct xattr_list *xattr;
|
|
||||||
|
|
||||||
evm_init_config();
|
evm_init_config();
|
||||||
|
|
||||||
|
@ -580,11 +579,8 @@ static int __init init_evm(void)
|
||||||
error:
|
error:
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
if (!list_empty(&evm_config_xattrnames)) {
|
if (!list_empty(&evm_config_xattrnames)) {
|
||||||
list_for_each_safe(pos, q, &evm_config_xattrnames) {
|
list_for_each_safe(pos, q, &evm_config_xattrnames)
|
||||||
xattr = list_entry(pos, struct xattr_list,
|
|
||||||
list);
|
|
||||||
list_del(pos);
|
list_del(pos);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -396,6 +396,33 @@ int ima_file_check(struct file *file, int mask)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ima_file_check);
|
EXPORT_SYMBOL_GPL(ima_file_check);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ima_post_create_tmpfile - mark newly created tmpfile as new
|
||||||
|
* @file : newly created tmpfile
|
||||||
|
*
|
||||||
|
* No measuring, appraising or auditing of newly created tmpfiles is needed.
|
||||||
|
* Skip calling process_measurement(), but indicate which newly, created
|
||||||
|
* tmpfiles are in policy.
|
||||||
|
*/
|
||||||
|
void ima_post_create_tmpfile(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct integrity_iint_cache *iint;
|
||||||
|
int must_appraise;
|
||||||
|
|
||||||
|
must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK);
|
||||||
|
if (!must_appraise)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Nothing to do if we can't allocate memory */
|
||||||
|
iint = integrity_inode_get(inode);
|
||||||
|
if (!iint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* needed for writing the security xattrs */
|
||||||
|
set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
|
||||||
|
iint->ima_file_status = INTEGRITY_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ima_post_path_mknod - mark as a new inode
|
* ima_post_path_mknod - mark as a new inode
|
||||||
* @dentry: newly created dentry
|
* @dentry: newly created dentry
|
||||||
|
@ -413,9 +440,13 @@ void ima_post_path_mknod(struct dentry *dentry)
|
||||||
if (!must_appraise)
|
if (!must_appraise)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Nothing to do if we can't allocate memory */
|
||||||
iint = integrity_inode_get(inode);
|
iint = integrity_inode_get(inode);
|
||||||
if (iint)
|
if (!iint)
|
||||||
iint->flags |= IMA_NEW_FILE;
|
return;
|
||||||
|
|
||||||
|
/* needed for re-opening empty files */
|
||||||
|
iint->flags |= IMA_NEW_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -60,11 +60,11 @@ static int blksize;
|
||||||
static struct crypto_shash *hash_tfm;
|
static struct crypto_shash *hash_tfm;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Opt_err = -1, Opt_new, Opt_load, Opt_update
|
Opt_new, Opt_load, Opt_update, Opt_err
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Opt_error = -1, Opt_default, Opt_ecryptfs, Opt_enc32
|
Opt_default, Opt_ecryptfs, Opt_enc32, Opt_error
|
||||||
};
|
};
|
||||||
|
|
||||||
static const match_table_t key_format_tokens = {
|
static const match_table_t key_format_tokens = {
|
||||||
|
|
Loading…
Reference in New Issue