All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mimi Zohar <zohar@linux.ibm.com>
To: Matthew Garrett <matthewgarrett@google.com>,
	linux-integrity@vger.kernel.org
Cc: dhowells@redhat.com, dmitry.kasatkin@gmail.com,
	Matthew Garrett <mjg59@google.com>
Subject: Re: [RFC] kexec: Allow kexec_file() with appropriate IMA policy when locked down
Date: Wed, 13 Mar 2019 07:58:36 -0400	[thread overview]
Message-ID: <1552478316.24794.210.camel@linux.ibm.com> (raw)
In-Reply-To: <20190312195715.101995-1-matthewgarrett@google.com>

On Tue, 2019-03-12 at 12:57 -0700, Matthew Garrett wrote:
> Systems in lockdown mode should block the kexec of untrusted kernels.
> For x86 and ARM we can ensure that a kernel is trustworthy by validating
> a PE signature, but this isn't possible on other architectures. On those
> platforms we can use IMA instead, either with native IMA digital
> signatures or EVM-protected IMA hashes. Add a function to determine
> whether IMA will verify signatures on kexec files, and if so permit
> kexec_file() even if the kernel is otherwise locked down. This is
> restricted to cases where CONFIG_INTEGRITY_TRUSTED_KEYRING is set in
> order to prevent an attacker from loading additional keys at runtime.

Thank you for working on this!  With the changes suggested below, it
might work.  :)

> 
> Signed-off-by: Matthew Garrett <mjg59@google.com>
> ---
>  include/linux/evm.h                 |  6 +++++
>  include/linux/ima.h                 |  9 ++++++++
>  kernel/kexec_file.c                 |  9 ++++++--
>  security/integrity/evm/evm_main.c   |  2 +-
>  security/integrity/ima/ima_policy.c | 35 +++++++++++++++++++++++++++++
>  5 files changed, 58 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/evm.h b/include/linux/evm.h
> index 8302bc29bb35..6e89d046b716 100644
> --- a/include/linux/evm.h
> +++ b/include/linux/evm.h
> @@ -15,6 +15,7 @@
>  struct integrity_iint_cache;
>  
>  #ifdef CONFIG_EVM
> +extern bool evm_key_loaded(void);
>  extern int evm_set_key(void *key, size_t keylen);
>  extern enum integrity_status evm_verifyxattr(struct dentry *dentry,
>  					     const char *xattr_name,
> @@ -45,6 +46,11 @@ static inline int posix_xattr_acl(const char *xattrname)
>  #endif
>  #else
>  
> +static inline bool evm_key_loaded(void)
> +{
> +	return false;
> +}
> +
>  static inline int evm_set_key(void *key, size_t keylen)
>  {
>  	return -EOPNOTSUPP;
> diff --git a/include/linux/ima.h b/include/linux/ima.h
> index dc12fbcf484c..2ec593537c9b 100644
> --- a/include/linux/ima.h
> +++ b/include/linux/ima.h
> @@ -132,4 +132,13 @@ static inline int ima_inode_removexattr(struct dentry *dentry,
>  	return 0;
>  }
>  #endif /* CONFIG_IMA_APPRAISE */
> +
> +#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
> +extern bool ima_appraise_kexec_signature(void);
> +#else
> +static inline bool ima_appraise_kexec_signature(void)
> +{
> +	return false;
> +}
> +#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */
>  #endif /* _LINUX_IMA_H */
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 0cfe4f6f7f85..8ca607f1b515 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -20,11 +20,11 @@
>  #include <linux/mutex.h>
>  #include <linux/list.h>
>  #include <linux/fs.h>
> -#include <linux/ima.h>
>  #include <crypto/hash.h>
>  #include <crypto/sha.h>
>  #include <linux/elf.h>
>  #include <linux/elfcore.h>
> +#include <linux/ima.h>
>  #include <linux/kernel.h>
>  #include <linux/syscalls.h>
>  #include <linux/vmalloc.h>
> @@ -240,7 +240,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
>  
>  		ret = 0;
>  
> -		if (kernel_is_locked_down(reason)) {
> +		/* If IMA is guaranteed to appraise a signature on the kexec
> +		 * image, permit it even if the kernel is otherwise locked
> +		 * down.
> +		 */
> +		if (!ima_appraise_kexec_signature() &&
> +		    kernel_is_locked_down(reason)) {
>  			ret = -EPERM;
>  			goto out;
>  		}
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index b6d9f14bc234..aad61bc0f774 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -87,7 +87,7 @@ static void __init evm_init_config(void)
>  	pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs);
>  }
>  
> -static bool evm_key_loaded(void)
> +bool evm_key_loaded(void)
>  {
>  	return (bool)(evm_initialized & EVM_KEY_MASK);
>  }

This might be sufficient for your environment, but in general it
isn't.


> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 8bc8a1c8cb3f..c06b1a6b3528 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -21,6 +21,7 @@
>  #include <linux/genhd.h>
>  #include <linux/seq_file.h>
>  #include <linux/ima.h>
> +#include <linux/evm.h>
>  
>  #include "ima.h"
>  
> @@ -1336,4 +1337,38 @@ int ima_policy_show(struct seq_file *m, void *v)
>  	seq_puts(m, "\n");
>  	return 0;
>  }
> +
>  #endif	/* CONFIG_IMA_READ_POLICY */
> +
> +#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)

With these defines, the function isn't limited to just "lockdown".
 Either fix the defines or the patch description.

> +/*
> + * ima_appraise_kexec: whether IMA will appraise a kexec image, either via
> + * IMA digital signatures or with a hash and EVM validation
> + */
> +bool ima_appraise_kexec_signature(void)

Instead of making this specific to kexec, how about naming the
function something like ima_require_appraise_signature() and pass the
kernel_read_file_id (eg. READING_KEXEC_IMAGE, READING_MODULE).

> +{
> +	struct ima_rule_entry *entry;
> +	bool found = false;
> +
> +	rcu_read_lock();
> +	list_for_each_entry_rcu(entry, ima_rules, list) {
> +		if (entry->func != KEXEC_KERNEL_CHECK ||
> +		    entry->action != APPRAISE)
> +			continue;
> +
> +		/*
> +		 * We require this to be a digital signature, not a raw IMA
> +		 * hash. An IMA hash is acceptable as long as it's covered
> +		 * by an EVM signature.
> +		 */
> +		if (entry->flags & IMA_DIGSIG_REQUIRED ||
> +		    evm_key_loaded()) {

evm_key_loaded() is a problem.

> +			found = true;
> +			break;
> +		}

The first matching rule dictates the policy.  Move the "break" here.

Walking the list looking for a specific rule might not be a true
indication of the policy.  For example, with a generic rule prior to a
specific rule, the generic rule might take precedence.

As long as the generic rules require a signature, there isn't a
problem.  I would stop walking the policy rules after the first
"appraise" rule that doesn't require a signature.  This will prevent
returning a false positive.

The builtin and arch policy rules are by design forced to be first.

Mimi


> +	}
> +
> +	rcu_read_unlock();
> +	return found;
> +}
> +#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */


  reply	other threads:[~2019-03-13 11:58 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-12 19:57 [RFC] kexec: Allow kexec_file() with appropriate IMA policy when locked down Matthew Garrett
2019-03-13 11:58 ` Mimi Zohar [this message]
2019-03-13 20:36   ` Matthew Garrett
2019-03-13 21:29     ` Mimi Zohar
2019-03-13 21:59       ` Matthew Garrett
2019-03-14  1:08         ` Mimi Zohar
2019-03-14 21:08           ` Matthew Garrett
2019-03-14 22:31             ` Mimi Zohar
2019-03-14 22:54               ` Matthew Garrett
2019-03-14 23:58                 ` Mimi Zohar
2019-03-15 22:03                   ` Matthew Garrett
2019-03-17 11:39                     ` Mimi Zohar
2019-03-17 11:39                       ` Mimi Zohar
2019-03-18 19:51                       ` Matthew Garrett
2019-03-18 19:51                         ` Matthew Garrett

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1552478316.24794.210.camel@linux.ibm.com \
    --to=zohar@linux.ibm.com \
    --cc=dhowells@redhat.com \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=linux-integrity@vger.kernel.org \
    --cc=matthewgarrett@google.com \
    --cc=mjg59@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.