diff mbox

[V6] EVM: Add support for portable signature format

Message ID 20171107151742.25122-1-mjg59@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

Matthew Garrett Nov. 7, 2017, 3:17 p.m. UTC
The EVM signature includes the inode number and (optionally) the
filesystem UUID, making it impractical to ship EVM signatures in
packages. This patch adds a new portable format intended to allow
distributions to include EVM signatures. It is identical to the existing
format but hardcodes the inode and generation numbers to 0 and does not
include the filesystem UUID even if the kernel is configured to do so.

Removing the inode means that the metadata and signature from one file
could be copied to another file without invalidating it. This is avoided
by ensuring that an IMA xattr is present during EVM validation.

Portable signatures are intended to be immutable - ie, they will never
be transformed into HMACs.

Based on earlier work by Dmitry Kasatkin and Mikhail Kurinnoi.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Cc: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
Cc: Mikhail Kurinnoi <viewizard@viewizard.com>
---

Sigh. Get rid of an unused variable declaration.

 include/linux/integrity.h             |  1 +
 security/integrity/evm/evm.h          |  2 +-
 security/integrity/evm/evm_crypto.c   | 75 ++++++++++++++++++++++++++++++-----
 security/integrity/evm/evm_main.c     | 27 ++++++++-----
 security/integrity/ima/ima_appraise.c |  4 +-
 security/integrity/integrity.h        |  2 +
 6 files changed, 91 insertions(+), 20 deletions(-)

Comments

Mimi Zohar Nov. 8, 2017, 7:37 p.m. UTC | #1
On Tue, 2017-11-07 at 07:17 -0800, Matthew Garrett wrote:
> The EVM signature includes the inode number and (optionally) the
> filesystem UUID, making it impractical to ship EVM signatures in
> packages. This patch adds a new portable format intended to allow
> distributions to include EVM signatures. It is identical to the existing
> format but hardcodes the inode and generation numbers to 0 and does not
> include the filesystem UUID even if the kernel is configured to do so.
> 
> Removing the inode means that the metadata and signature from one file
> could be copied to another file without invalidating it. This is avoided
> by ensuring that an IMA xattr is present during EVM validation.
> 
> Portable signatures are intended to be immutable - ie, they will never
> be transformed into HMACs.
> 
> Based on earlier work by Dmitry Kasatkin and Mikhail Kurinnoi.
> 
> Signed-off-by: Matthew Garrett <mjg59@google.com>
> Cc: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
> Cc: Mikhail Kurinnoi <viewizard@viewizard.com>

Thanks!  I've queued "EVM: Allow userland to permit modification of
EVM-protected metadata" and this patch in the next-queued (linux-4.16) 
branch.

There's a disconnect between what is in ima-evm-utils and actually
supported in the kernel.  We need to remove the portable version that
is currently there, and replace it with this version.  This will give
us time to figure out how to add support in ima-evm-utils, before it
is upstreamed in the kernel.

Mimi

> ---
> 
> Sigh. Get rid of an unused variable declaration.
> 
>  include/linux/integrity.h             |  1 +
>  security/integrity/evm/evm.h          |  2 +-
>  security/integrity/evm/evm_crypto.c   | 75 ++++++++++++++++++++++++++++++-----
>  security/integrity/evm/evm_main.c     | 27 ++++++++-----
>  security/integrity/ima/ima_appraise.c |  4 +-
>  security/integrity/integrity.h        |  2 +
>  6 files changed, 91 insertions(+), 20 deletions(-)
> 
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index c2d6082a1a4c..858d3f4a2241 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -14,6 +14,7 @@
> 
>  enum integrity_status {
>  	INTEGRITY_PASS = 0,
> +	INTEGRITY_PASS_IMMUTABLE,
>  	INTEGRITY_FAIL,
>  	INTEGRITY_NOLABEL,
>  	INTEGRITY_NOXATTRS,
> diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
> index f5f12727771a..2ff02459fcfd 100644
> --- a/security/integrity/evm/evm.h
> +++ b/security/integrity/evm/evm.h
> @@ -48,7 +48,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
>  		  size_t req_xattr_value_len, char *digest);
>  int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
>  		  const char *req_xattr_value,
> -		  size_t req_xattr_value_len, char *digest);
> +		  size_t req_xattr_value_len, char type, char *digest);
>  int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
>  		  char *hmac_val);
>  int evm_init_secfs(void);
> diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
> index 1d32cd20009a..e526f0f5aaaf 100644
> --- a/security/integrity/evm/evm_crypto.c
> +++ b/security/integrity/evm/evm_crypto.c
> @@ -138,7 +138,7 @@ static struct shash_desc *init_desc(char type)
>   * protection.)
>   */
>  static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
> -			  char *digest)
> +			  char type, char *digest)
>  {
>  	struct h_misc {
>  		unsigned long ino;
> @@ -149,8 +149,13 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
>  	} hmac_misc;
> 
>  	memset(&hmac_misc, 0, sizeof(hmac_misc));
> -	hmac_misc.ino = inode->i_ino;
> -	hmac_misc.generation = inode->i_generation;
> +	/* Don't include the inode or generation number in portable
> +	 * signatures
> +	 */
> +	if (type != EVM_XATTR_PORTABLE_DIGSIG) {
> +		hmac_misc.ino = inode->i_ino;
> +		hmac_misc.generation = inode->i_generation;
> +	}
>  	/* The hmac uid and gid must be encoded in the initial user
>  	 * namespace (not the filesystems user namespace) as encoding
>  	 * them in the filesystems user namespace allows an attack
> @@ -163,7 +168,8 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
>  	hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
>  	hmac_misc.mode = inode->i_mode;
>  	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)
>  		crypto_shash_update(desc, &inode->i_sb->s_uuid.b[0],
>  				    sizeof(inode->i_sb->s_uuid));
>  	crypto_shash_final(desc, digest);
> @@ -189,6 +195,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
>  	char *xattr_value = NULL;
>  	int error;
>  	int size;
> +	bool ima_present = false;
> 
>  	if (!(inode->i_opflags & IOP_XATTR))
>  		return -EOPNOTSUPP;
> @@ -199,11 +206,18 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
> 
>  	error = -ENODATA;
>  	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
> +		bool is_ima = false;
> +
> +		if (strcmp(*xattrname, XATTR_NAME_IMA) == 0)
> +			is_ima = true;
> +
>  		if ((req_xattr_name && req_xattr_value)
>  		    && !strcmp(*xattrname, req_xattr_name)) {
>  			error = 0;
>  			crypto_shash_update(desc, (const u8 *)req_xattr_value,
>  					     req_xattr_value_len);
> +			if (is_ima)
> +				ima_present = true;
>  			continue;
>  		}
>  		size = vfs_getxattr_alloc(dentry, *xattrname,
> @@ -218,9 +232,14 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
>  		error = 0;
>  		xattr_size = size;
>  		crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
> +		if (is_ima)
> +			ima_present = true;
>  	}
> -	hmac_add_misc(desc, inode, digest);
> +	hmac_add_misc(desc, inode, type, digest);
> 
> +	/* Portable EVM signatures must include an IMA hash */
> +	if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
> +		return -EPERM;
>  out:
>  	kfree(xattr_value);
>  	kfree(desc);
> @@ -232,17 +251,45 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
>  		  char *digest)
>  {
>  	return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
> -				req_xattr_value_len, EVM_XATTR_HMAC, digest);
> +			       req_xattr_value_len, EVM_XATTR_HMAC, digest);
>  }
> 
>  int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
>  		  const char *req_xattr_value, size_t req_xattr_value_len,
> -		  char *digest)
> +		  char type, char *digest)
>  {
>  	return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
> -				req_xattr_value_len, IMA_XATTR_DIGEST, digest);
> +				     req_xattr_value_len, type, digest);
> +}
> +
> +static int evm_is_immutable(struct dentry *dentry, struct inode *inode)
> +{
> +	const struct evm_ima_xattr_data *xattr_data = NULL;
> +	struct integrity_iint_cache *iint;
> +	int rc = 0;
> +
> +	iint = integrity_iint_find(inode);
> +	if (iint && (iint->flags & EVM_IMMUTABLE_DIGSIG))
> +		return 1;
> +
> +	/* Do this the hard way */
> +	rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
> +				GFP_NOFS);
> +	if (rc <= 0) {
> +		if (rc == -ENODATA)
> +			return 0;
> +		return rc;
> +	}
> +	if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG)
> +		rc = 1;
> +	else
> +		rc = 0;
> +
> +	kfree(xattr_data);
> +	return rc;
>  }
> 
> +
>  /*
>   * Calculate the hmac and update security.evm xattr
>   *
> @@ -255,6 +302,16 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
>  	struct evm_ima_xattr_data xattr_data;
>  	int rc = 0;
> 
> +	/*
> +	 * Don't permit any transformation of the EVM xattr if the signature
> +	 * is of an immutable type
> +	 */
> +	rc = evm_is_immutable(dentry, inode);
> +	if (rc < 0)
> +		return rc;
> +	if (rc)
> +		return -EPERM;
> +
>  	rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
>  			   xattr_value_len, xattr_data.digest);
>  	if (rc == 0) {
> @@ -280,7 +337,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
>  	}
> 
>  	crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
> -	hmac_add_misc(desc, inode, hmac_val);
> +	hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val);
>  	kfree(desc);
>  	return 0;
>  }
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index 063d38aef64e..485f235234ab 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -120,7 +120,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
>  	enum integrity_status evm_status = INTEGRITY_PASS;
>  	int rc, xattr_len;
> 
> -	if (iint && iint->evm_status == INTEGRITY_PASS)
> +	if (iint && (iint->evm_status == INTEGRITY_PASS ||
> +		     iint->evm_status == INTEGRITY_PASS_IMMUTABLE))
>  		return iint->evm_status;
> 
>  	/* if status is not PASS, try to check again - against -ENOMEM */
> @@ -161,22 +162,26 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
>  			rc = -EINVAL;
>  		break;
>  	case EVM_IMA_XATTR_DIGSIG:
> +	case EVM_XATTR_PORTABLE_DIGSIG:
>  		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
> -				xattr_value_len, calc.digest);
> +				   xattr_value_len, xattr_data->type,
> +				   calc.digest);
>  		if (rc)
>  			break;
>  		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
>  					(const char *)xattr_data, xattr_len,
>  					calc.digest, sizeof(calc.digest));
>  		if (!rc) {
> -			/* Replace RSA with HMAC if not mounted readonly and
> -			 * not immutable
> -			 */
> -			if (!IS_RDONLY(d_backing_inode(dentry)) &&
> -			    !IS_IMMUTABLE(d_backing_inode(dentry)))
> +			if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
> +				if (iint)
> +					iint->flags |= EVM_IMMUTABLE_DIGSIG;
> +				evm_status = INTEGRITY_PASS_IMMUTABLE;
> +			} else if (!IS_RDONLY(d_backing_inode(dentry)) &&
> +				   !IS_IMMUTABLE(d_backing_inode(dentry))) {
>  				evm_update_evmxattr(dentry, xattr_name,
>  						    xattr_value,
>  						    xattr_value_len);
> +			}
>  		}
>  		break;
>  	default:
> @@ -277,7 +282,7 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
>   * affect security.evm.  An interesting side affect of writing posix xattr
>   * acls is their modifying of the i_mode, which is included in security.evm.
>   * For posix xattr acls only, permit security.evm, even if it currently
> - * doesn't exist, to be updated.
> + * doesn't exist, to be updated unless the EVM signature is immutable.
>   */
>  static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
>  			     const void *xattr_value, size_t xattr_value_len)
> @@ -345,7 +350,8 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
>  	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
>  		if (!xattr_value_len)
>  			return -EINVAL;
> -		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG)
> +		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG &&
> +		    xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG)
>  			return -EPERM;
>  	}
>  	return evm_protect_xattr(dentry, xattr_name, xattr_value,
> @@ -422,6 +428,9 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
>  /**
>   * evm_inode_setattr - prevent updating an invalid EVM extended attribute
>   * @dentry: pointer to the affected dentry
> + *
> + * Permit update of file attributes when files have a valid EVM signature,
> + * except in the case of them having an immutable portable signature.
>   */
>  int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
>  {
> diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
> index 809ba70fbbbf..8336c70dc6bc 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -229,7 +229,9 @@ int ima_appraise_measurement(enum ima_hooks func,
>  	}
> 
>  	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> -	if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> +	if ((status != INTEGRITY_PASS) &&
> +	    (status != INTEGRITY_PASS_IMMUTABLE) &&
> +	    (status != INTEGRITY_UNKNOWN)) {
>  		if ((status == INTEGRITY_NOLABEL)
>  		    || (status == INTEGRITY_NOXATTRS))
>  			cause = "missing-HMAC";
> diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
> index a53e7e4ab06c..cbc7de33fac7 100644
> --- a/security/integrity/integrity.h
> +++ b/security/integrity/integrity.h
> @@ -33,6 +33,7 @@
>  #define IMA_DIGSIG_REQUIRED	0x02000000
>  #define IMA_PERMIT_DIRECTIO	0x04000000
>  #define IMA_NEW_FILE		0x08000000
> +#define EVM_IMMUTABLE_DIGSIG	0x10000000
> 
>  #define IMA_DO_MASK		(IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
>  				 IMA_APPRAISE_SUBMASK)
> @@ -58,6 +59,7 @@ enum evm_ima_xattr_type {
>  	EVM_XATTR_HMAC,
>  	EVM_IMA_XATTR_DIGSIG,
>  	IMA_XATTR_DIGEST_NG,
> +	EVM_XATTR_PORTABLE_DIGSIG,
>  	IMA_XATTR_LAST
>  };
>
Patrick Ohly Nov. 15, 2017, 5:26 p.m. UTC | #2
On Tue, 2017-11-07 at 07:17 -0800, Matthew Garrett wrote:
> The EVM signature includes the inode number and (optionally) the
> filesystem UUID, making it impractical to ship EVM signatures in
> packages. This patch adds a new portable format intended to allow
> distributions to include EVM signatures. It is identical to the
> existing format but hardcodes the inode and generation numbers to 0
> and does not include the filesystem UUID even if the kernel is
> configured to do so.
> 
> Removing the inode means that the metadata and signature from one
> file could be copied to another file without invalidating it. This is
> avoided by ensuring that an IMA xattr is present during EVM
> validation.
> 
> Portable signatures are intended to be immutable - ie, they will
> never be transformed into HMACs.

I've been following this patch series and related discussions with
interest. It aims at making appraisal more secure. As discussed on the
old list earlier this year, I tried to use IMA for that and just
(re)discovered that appraisal had too many known loopholes to be
useful, at least as it existed at the time. The main gap was that
directory integrity wasn't protected and that there was no way to
specify a policy that ensured that all files used by sensitive
processes were appraised.

What hasn't become obvious to me yet is how portable signatures help
fit into the overall system. What kind of IMA policy is it meant to
use? Is the entire partition considered read-only except when
installing system software or does it also contain data files from
untrusted apps? Which MAC, if any, and does that matter? Are there
known holes that need to be plugged before this system is considered
secure, and is there a "master plan" for getting there?

To repeat one of the offline attacks that I outlined in the past:
suppose systemd is the init system. How is going to be ensured that an
attacker cannot install a service unit file for his Python script which
then causes systemd to start that service with arbitrary privileges?

Roberto's "ima: preserve integrity of dynamic data" seems to address
that, but according to Mimi, isn't using the right approach for solving
the issue.
Matthew Garrett Nov. 15, 2017, 5:58 p.m. UTC | #3
On Wed, Nov 15, 2017 at 9:26 AM, Patrick Ohly <patrick.ohly@intel.com> wrote:
> What hasn't become obvious to me yet is how portable signatures help
> fit into the overall system. What kind of IMA policy is it meant to
> use? Is the entire partition considered read-only except when
> installing system software or does it also contain data files from
> untrusted apps? Which MAC, if any, and does that matter? Are there
> known holes that need to be plugged before this system is considered
> secure, and is there a "master plan" for getting there?

Our approach is to combine appraisal with LSM in order to allow a more
fine-grained policy (we're using Apparmor, but this applies equally
well to SELinux or SMACK). Execution that attempts to transition into
a more privileged Apparmor context will be subject to appraisal,
execution that transitions into an unprivileged context won't be. Long
term, this also allows for writing policy that ensures that (eg) all
files read by systemd are appraised without having to impose the same
requirement on root in general.
Patrick Ohly Nov. 15, 2017, 6:21 p.m. UTC | #4
On Wed, 2017-11-15 at 09:58 -0800, Matthew Garrett wrote:
> On Wed, Nov 15, 2017 at 9:26 AM, Patrick Ohly <patrick.ohly@intel.com
> > wrote:
> > What hasn't become obvious to me yet is how portable signatures
> > help
> > fit into the overall system. What kind of IMA policy is it meant to
> > use? Is the entire partition considered read-only except when
> > installing system software or does it also contain data files from
> > untrusted apps? Which MAC, if any, and does that matter? Are there
> > known holes that need to be plugged before this system is
> > considered
> > secure, and is there a "master plan" for getting there?
> 
> Our approach is to combine appraisal with LSM in order to allow a
> more fine-grained policy (we're using Apparmor, but this applies
> equally well to SELinux or SMACK).

I have some experience with SMACK, but not with Apparmor. At least with
SMACK the problem is that the LSM depends on integrity protection of
the xattrs, but the integrity protection itself depends on the LSM, so
there's a cycle. An attacker can much too easily make offline changes
which then defeat whatever IMA policy the system might be using.

>  Execution that attempts to transition intoa more privileged Apparmor
> context will be subject to appraisal,execution that transitions into
> an unprivileged context won't be.

Is that something that already works with the upstream kernel plus your
 portable signatures, or do you have additional kernel patches?

If it already works, can you share the IMA policy and/or be a bit more
specific about how to set up such a system? I'd love to reproduce it.
Matthew Garrett Nov. 15, 2017, 6:28 p.m. UTC | #5
On Wed, Nov 15, 2017 at 10:21 AM, Patrick Ohly <patrick.ohly@intel.com> wrote:
> I have some experience with SMACK, but not with Apparmor. At least with
> SMACK the problem is that the LSM depends on integrity protection of
> the xattrs, but the integrity protection itself depends on the LSM, so
> there's a cycle. An attacker can much too easily make offline changes
> which then defeat whatever IMA policy the system might be using.

We load the core policy from the initramfs, which is part of our
signed payload that's enforced by the firmware.

>>  Execution that attempts to transition intoa more privileged Apparmor
>> context will be subject to appraisal,execution that transitions into
>> an unprivileged context won't be.
>
> Is that something that already works with the upstream kernel plus your
>  portable signatures, or do you have additional kernel patches?

It doesn't quite work as is - see
https://www.mail-archive.com/selinux@tycho.nsa.gov/msg05830.html and
the 2/2 patch in the series. Then it's just a matter of something
like:

appraise func=CREDS_CHECK subj_user=privileged_t

and anything that's being executed as privileged_t will be appraised
before execution.
James Morris Nov. 16, 2017, 12:02 a.m. UTC | #6
On Wed, 15 Nov 2017, Patrick Ohly wrote:

> I have some experience with SMACK, but not with Apparmor. At least with
> SMACK the problem is that the LSM depends on integrity protection of
> the xattrs, but the integrity protection itself depends on the LSM, so
> there's a cycle. An attacker can much too easily make offline changes
> which then defeat whatever IMA policy the system might be using.

Isn't this what EVM is supposed to mitigate?

Can you explain the offline attack in this scenario?
Matthew Garrett Nov. 16, 2017, 12:05 a.m. UTC | #7
On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
> On Wed, 15 Nov 2017, Patrick Ohly wrote:
>
>> I have some experience with SMACK, but not with Apparmor. At least with
>> SMACK the problem is that the LSM depends on integrity protection of
>> the xattrs, but the integrity protection itself depends on the LSM, so
>> there's a cycle. An attacker can much too easily make offline changes
>> which then defeat whatever IMA policy the system might be using.
>
> Isn't this what EVM is supposed to mitigate?

If the path to the loading of the LSM policy isn't fully appraised,
then it can be modified offline in order to permit modification of the
EVM xattrs at runtime, at which point the kernel will happily generate
a new HMAC.
Mimi Zohar Nov. 16, 2017, 2:13 a.m. UTC | #8
On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
> > On Wed, 15 Nov 2017, Patrick Ohly wrote:
> >
> >> I have some experience with SMACK, but not with Apparmor. At least with
> >> SMACK the problem is that the LSM depends on integrity protection of
> >> the xattrs, but the integrity protection itself depends on the LSM, so
> >> there's a cycle. An attacker can much too easily make offline changes
> >> which then defeat whatever IMA policy the system might be using.
> >
> > Isn't this what EVM is supposed to mitigate?
> 
> If the path to the loading of the LSM policy isn't fully appraised,
> then it can be modified offline in order to permit modification of the
> EVM xattrs at runtime, at which point the kernel will happily generate
> a new HMAC.

Matthew, your explanation is a valid problem, but different than what
Patrick was describing.  Your description is of protecting the LSM
policy itself.  Patrick, correct me if I'm wrong, was describing the
situation where the LSM labels are modified, causing the file being
appraised not to be in the IMA policy.

To solve Matthew's problem requires modifying the LSMs so that instead
of userspace reading the policy, processing it and loading it into the
kernel, the LSMs read the policy file directly.

Mimi
Roberto Sassu Nov. 16, 2017, 9:23 a.m. UTC | #9
On 11/16/2017 3:13 AM, Mimi Zohar wrote:
> On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
>> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
>>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
>>>
>>>> I have some experience with SMACK, but not with Apparmor. At least with
>>>> SMACK the problem is that the LSM depends on integrity protection of
>>>> the xattrs, but the integrity protection itself depends on the LSM, so
>>>> there's a cycle. An attacker can much too easily make offline changes
>>>> which then defeat whatever IMA policy the system might be using.
>>>
>>> Isn't this what EVM is supposed to mitigate?

With the default appraisal policy, it can't. IMA determines if a file
must be appraised depending on metadata whose integrity has not been
verified yet. A root process is able to load appraised files with
i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
same time.

Me and Matthew are considering policies based on subject criteria rather
than object criteria. The integrity of a process can be guaranteed
because everything that process reads or executes will be appraised.


>> If the path to the loading of the LSM policy isn't fully appraised,
>> then it can be modified offline in order to permit modification of the
>> EVM xattrs at runtime, at which point the kernel will happily generate
>> a new HMAC.
> 
> Matthew, your explanation is a valid problem, but different than what
> Patrick was describing.  Your description is of protecting the LSM
> policy itself.  Patrick, correct me if I'm wrong, was describing the
> situation where the LSM labels are modified, causing the file being
> appraised not to be in the IMA policy.

If the LSM policy is parsed in user space and then uploaded by the
kernel, an offline attack would be to modify the file i_uid to be != 0,
so that any policy can be loaded. Unless, as Matthew mentioned, the
policy is included in a signed initial ram disk.


> To solve Matthew's problem requires modifying the LSMs so that instead
> of userspace reading the policy, processing it and loading it into the
> kernel, the LSMs read the policy file directly.

I agree. The same applies to digest lists, IMA parses them directly.

Roberto
Patrick Ohly Nov. 16, 2017, 10:20 a.m. UTC | #10
On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
> > On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
> > > On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@ora
> > > cle.com> wrote:
> > > > On Wed, 15 Nov 2017, Patrick Ohly wrote:
> > > > 
> > > > > I have some experience with SMACK, but not with Apparmor. At
> > > > > least with
> > > > > SMACK the problem is that the LSM depends on integrity
> > > > > protection of
> > > > > the xattrs, but the integrity protection itself depends on
> > > > > the LSM, so
> > > > > there's a cycle. An attacker can much too easily make offline
> > > > > changes
> > > > > which then defeat whatever IMA policy the system might be
> > > > > using.
> > > > 
> > > > Isn't this what EVM is supposed to mitigate?
> 
> With the default appraisal policy, it can't. IMA determines if a file
> must be appraised depending on metadata whose integrity has not been
> verified yet. A root process is able to load appraised files with
> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
> same time.

Exactly. Therefore a policy that says "appraise only files owned by
root" or "with a certain SMACK label" is vulnerable to offline attacks.

> Me and Matthew are considering policies based on subject criteria
> rather than object criteria. The integrity of a process can be
> guaranteed because everything that process reads or executes will be
> appraised.

Even then you still have the problem that the integrity of the process
may also depend on the presence (or absence) of files. My favorite
example for that is systemd: suppose that the integrity of the system
depends on starting a certain service via systemd. It's trivial for an
attacker to remove the corresponding unit file when the system is
offline.

Adding a custom service written by an attacker gets prevented, but an
attacker can still install unit files prepared by the vendor. For
example, suppose a device is not supposed to have an ssh daemon, but
there is a package for OpenSSH properly signed by the vendor. Then an
attacker can take those files and add them to the device while offline.
 It could get even worse (telnet? A debugging service?), so a vendor
has to be very careful about what is getting signed.

Another attack vector that also remains open is replacing files with
other files from the vendor. Suppose there's a binary that does some
check and signals the result to the calling process with its exit code.
An attacker can control the result of the check by replacing the binary
with /bin/true or /bin/false, depending on what result is desired.
Mimi Zohar Nov. 16, 2017, 1:06 p.m. UTC | #11
On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
> > On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
> >> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
> >>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
> >>>
> >>>> I have some experience with SMACK, but not with Apparmor. At least with
> >>>> SMACK the problem is that the LSM depends on integrity protection of
> >>>> the xattrs, but the integrity protection itself depends on the LSM, so
> >>>> there's a cycle. An attacker can much too easily make offline changes
> >>>> which then defeat whatever IMA policy the system might be using.
> >>>
> >>> Isn't this what EVM is supposed to mitigate?
> 
> With the default appraisal policy, it can't. IMA determines if a file
> must be appraised depending on metadata whose integrity has not been
> verified yet. A root process is able to load appraised files with
> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
> same time.

The LSMs are responsible for protecting their own labels.  They have
the opportunity to verify and deny access to files based on LSM
labels, BEFORE IMA-appraisal is called to verify the file's integrity.

Look at security/security.c and see that IMA is called AFTER the
LSMs.  The same is true for the other IMA hooks, that are not co-
located with LSM hooks.  For example, the security_file_open hook is
called before the ima_file_check() hook.

Mimi
Mimi Zohar Nov. 16, 2017, 1:13 p.m. UTC | #12
On Thu, 2017-11-16 at 11:20 +0100, Patrick Ohly wrote:
> On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:

> > Me and Matthew are considering policies based on subject criteria
> > rather than object criteria. The integrity of a process can be
> > guaranteed because everything that process reads or executes will be
> > appraised.
> 
> Even then you still have the problem that the integrity of the process
> may also depend on the presence (or absence) of files. My favorite
> example for that is systemd: suppose that the integrity of the system
> depends on starting a certain service via systemd. It's trivial for an
> attacker to remove the corresponding unit file when the system is
> offline.
> 
> Adding a custom service written by an attacker gets prevented, but an
> attacker can still install unit files prepared by the vendor. For
> example, suppose a device is not supposed to have an ssh daemon, but
> there is a package for OpenSSH properly signed by the vendor. Then an
> attacker can take those files and add them to the device while offline.
>  It could get even worse (telnet? A debugging service?), so a vendor
> has to be very careful about what is getting signed.
> 
> Another attack vector that also remains open is replacing files with
> other files from the vendor. Suppose there's a binary that does some
> check and signals the result to the calling process with its exit code.
> An attacker can control the result of the check by replacing the binary
> with /bin/true or /bin/false, depending on what result is desired.

Right, both of these examples can be detected by protecting the
directory information.

Mimi
Roberto Sassu Nov. 16, 2017, 2:18 p.m. UTC | #13
On 11/16/2017 11:20 AM, Patrick Ohly wrote:
> On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
>> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
>>> On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
>>>> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@ora
>>>> cle.com> wrote:
>>>>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
>>>>>
>>>>>> I have some experience with SMACK, but not with Apparmor. At
>>>>>> least with
>>>>>> SMACK the problem is that the LSM depends on integrity
>>>>>> protection of
>>>>>> the xattrs, but the integrity protection itself depends on
>>>>>> the LSM, so
>>>>>> there's a cycle. An attacker can much too easily make offline
>>>>>> changes
>>>>>> which then defeat whatever IMA policy the system might be
>>>>>> using.
>>>>>
>>>>> Isn't this what EVM is supposed to mitigate?
>>
>> With the default appraisal policy, it can't. IMA determines if a file
>> must be appraised depending on metadata whose integrity has not been
>> verified yet. A root process is able to load appraised files with
>> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
>> same time.
> 
> Exactly. Therefore a policy that says "appraise only files owned by
> root" or "with a certain SMACK label" is vulnerable to offline attacks.
> 
>> Me and Matthew are considering policies based on subject criteria
>> rather than object criteria. The integrity of a process can be
>> guaranteed because everything that process reads or executes will be
>> appraised.
> 
> Even then you still have the problem that the integrity of the process
> may also depend on the presence (or absence) of files. My favorite
> example for that is systemd: suppose that the integrity of the system
> depends on starting a certain service via systemd. It's trivial for an
> attacker to remove the corresponding unit file when the system is
> offline.

If the system state (PCR 10 value) is predictable, the TPM could be used
to enforce a sealing policy which requires that the PCR is extended with
the digest of desired files. If systemd does not access those files,
unsealed data won't be available.

Currently, defining a policy on PCR 10 is not possible because the order
in which files are measured is not deterministic.

With digest lists, the PCR is extended when unknown files are accessed,
but no distinction is made between files modified during an offline
attack and files which have been modified only by the TCB. In the second
case, the measurement can be avoided because the TCB will not be
compromised by those files, if they were not initially corrupted.

With the dynamic data work, the PCR is not extended when the Biba strict
policy is enforced on appraised files (no writes by processes outside
the TCB) and the appraisal status is INTEGRITY_PASS.

At the moment, digest lists do not provide information about which files
have been actually accessed. To support your requirement, it would be
necessary to further extend IMA to create a new measurement entry when a
given set of files has been accessed. The benefit of using digest lists
would be that the system state remains predictable, because the PCR
will be extended only with the digest of digest lists and the digest of
the new measurement created when all files in the given set have been
accessed.


> Adding a custom service written by an attacker gets prevented, but an
> attacker can still install unit files prepared by the vendor. For
> example, suppose a device is not supposed to have an ssh daemon, but
> there is a package for OpenSSH properly signed by the vendor. Then an
> attacker can take those files and add them to the device while offline.
>   It could get even worse (telnet? A debugging service?), so a vendor
> has to be very careful about what is getting signed.

With digest lists, you would be able to limit what it can be accessed by
the TCB.


> Another attack vector that also remains open is replacing files with
> other files from the vendor. Suppose there's a binary that does some
> check and signals the result to the calling process with its exit code.
> An attacker can control the result of the check by replacing the binary
> with /bin/true or /bin/false, depending on what result is desired.

This issue could be addressed with an LSM, by defining with a policy
which files can be executed by the calling process.

Roberto
Roberto Sassu Nov. 17, 2017, 12:20 p.m. UTC | #14
On 11/16/2017 2:06 PM, Mimi Zohar wrote:
> On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
>> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
>>> On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
>>>> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
>>>>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
>>>>>
>>>>>> I have some experience with SMACK, but not with Apparmor. At least with
>>>>>> SMACK the problem is that the LSM depends on integrity protection of
>>>>>> the xattrs, but the integrity protection itself depends on the LSM, so
>>>>>> there's a cycle. An attacker can much too easily make offline changes
>>>>>> which then defeat whatever IMA policy the system might be using.
>>>>>
>>>>> Isn't this what EVM is supposed to mitigate?
>>
>> With the default appraisal policy, it can't. IMA determines if a file
>> must be appraised depending on metadata whose integrity has not been
>> verified yet. A root process is able to load appraised files with
>> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
>> same time.
> 
> The LSMs are responsible for protecting their own labels.  Theyhave
> the opportunity to verify and deny access to files based on LSM
> labels, BEFORE IMA-appraisal is called to verify the file's integrity.

Adding in CC the linux-security-module mailing list.

LSMs are responsible to enforce a security policy at run-time, while
IMA/EVM protect data and metadata against offline attacks. However, if
IMA/EVM protect only part of the system, the security policy might not
be enforced as expected. I give an example.

Suppose that a security policy preserves the integrity of a database by
allowing only one application to modify it. Suppose also, that the
security policy allows that application to modify files which are not
appraised by IMA. Only the database is appraised.

Then, the integrity of the database cannot be guaranteed anymore. When
the system is offline, the database label is swapped with one that is
not included in the IMA policy. When the system is online again, LSMs
would allow the application to access the database, but its integrity
is no longer verified. From the users perspective, the application is
working correctly, while unauthorized modifications could have be done
on the database.

In my opinion, protecting the integrity of a TCB against offline and
online attacks with LSMs and IMA/EVM, can be achieved in two ways:

- all objects accessed by LSM TCB subjects are a subset of IMA TCB
   objects, and LSM prevents accesses to LSM TCB objects by processes
   outside LSM TCB

- all objects accessed by IMA TCB subjects are protected by IMA, IMA
   prevents accesses to IMA TCB objects by processes outside IMA TCB, and
   LSM TCB subjects are a subset of IMA TCB subjects

As you can see, in both cases there is a dependency between the LSM
policy and the IMA policy. In the first case, the dependency is on
objects and LSM is enforcing integrity. In the second case, the
dependency is on subjects, IMA is enforcing integrity and LSM could
enforce a more strict integrity policy or a policy with different goals.

I prefer the second option because:

1) it easier to write a policy in term of subjects rather than objects

2) LSM does not necessarily enforce an integrity policy; LSM could
    enforce a policy for isolation and containment, while IMA could
    enforce an integrity policy

3) an integrity policy can be enforced without LSM, and both LSM and IMA
    can enforce their own integrity policy

4) the effort necessary to enforce an integrity policy with IMA is very
    low: if files with valid signature/HMAC are in the IMA TCB and the
    IMA policy identifies TCB subjects, the required modification would
    be to simply deny access to appraised files if the subject does not
    match policy criteria

The first version of the patch set which adds support for the
enforcement of the Biba strict policy can be found at the URL:

https://www.spinics.net/lists/linux-integrity/msg00392.html

Roberto


> Look at security/security.c and see that IMA is called AFTER the
> LSMs.  The same is true for the other IMA hooks, that are not co-
> located with LSM hooks.  For example, the security_file_open hook is
> called before the ima_file_check() hook.
> 
> Mimi
>
Mimi Zohar Nov. 17, 2017, 1:42 p.m. UTC | #15
On Fri, 2017-11-17 at 13:20 +0100, Roberto Sassu wrote:
> On 11/16/2017 2:06 PM, Mimi Zohar wrote:
> > On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
> >> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
> >>> On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
> >>>> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
> >>>>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
> >>>>>
> >>>>>> I have some experience with SMACK, but not with Apparmor. At least with
> >>>>>> SMACK the problem is that the LSM depends on integrity protection of
> >>>>>> the xattrs, but the integrity protection itself depends on the LSM, so
> >>>>>> there's a cycle. An attacker can much too easily make offline changes
> >>>>>> which then defeat whatever IMA policy the system might be using.
> >>>>>
> >>>>> Isn't this what EVM is supposed to mitigate?
> >>
> >> With the default appraisal policy, it can't. IMA determines if a file
> >> must be appraised depending on metadata whose integrity has not been
> >> verified yet. A root process is able to load appraised files with
> >> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
> >> same time.
> > 
> > The LSMs are responsible for protecting their own labels.  Theyhave
> > the opportunity to verify and deny access to files based on LSM
> > labels, BEFORE IMA-appraisal is called to verify the file's integrity.
> 
> Adding in CC the linux-security-module mailing list.

We need to first clarify, for those reading this thread, that are not
fully aware of the context of this discussion, that the discussion is
not relevant to the "lockdown" patch set.

Kernel modules, the kexec image, IMA policy and firmware call the pre
and post LSM kernel_read_file hooks.  For these LSM hooks, IMA policy
rules are not written in terms of LSM labels or any other file
metadata.  File signatures will always be appraised.

> LSMs are responsible to enforce a security policy at run-time, while
> IMA/EVM protect data and metadata against offline attacks. However, if
> IMA/EVM protect only part of the system, the security policy might not
> be enforced as expected. I give an example.
> 
> Suppose that a security policy preserves the integrity of a database by
> allowing only one application to modify it. Suppose also, that the
> security policy allows that application to modify files which are not
> appraised by IMA. Only the database is appraised.

This use case scenario is really strange.  The IMA policy should be
verifying the integrity of the application that is allowed to modify
the database, not the database.

From my limited knowledge of databases, databases tend to manage data
caching themselves at the application level (eg. Direct IO), and avoid
file buffer caching.  Having IMA calculate the file hash, would negate
the performance benefits of doing their own data caching.

> Then, the integrity of the database cannot be guaranteed anymore. When
> the system is offline, the database label is swapped with one that is
> not included in the IMA policy. When the system is online again, LSMs
> would allow the application to access the database, but its integrity
> is no longer verified. From the users perspective, the application is
> working correctly, while unauthorized modifications could have be done
> on the database.
> 
> In my opinion, protecting the integrity of a TCB against offline and
> online attacks with LSMs and IMA/EVM, can be achieved in two ways:

I really doubt that anyone's definition of TCB would include
databases.

> 
> - all objects accessed by LSM TCB subjects are a subset of IMA TCB
>    objects, and LSM prevents accesses to LSM TCB objects by processes
>    outside LSM TCB
> 
> - all objects accessed by IMA TCB subjects are protected by IMA, IMA
>    prevents accesses to IMA TCB objects by processes outside IMA TCB, and
>    LSM TCB subjects are a subset of IMA TCB subjects
> 
> As you can see, in both cases there is a dependency between the LSM
> policy and the IMA policy. In the first case, the dependency is on
> objects and LSM is enforcing integrity. In the second case, the
> dependency is on subjects, IMA is enforcing integrity and LSM could
> enforce a more strict integrity policy or a policy with different goals.
> 
> I prefer the second option because:
> 
> 1) it easier to write a policy in term of subjects rather than objects
> 
> 2) LSM does not necessarily enforce an integrity policy; LSM could
>     enforce a policy for isolation and containment, while IMA could
>     enforce an integrity policy
> 
> 3) an integrity policy can be enforced without LSM, and both LSM and IMA
>     can enforce their own integrity policy
> 
> 4) the effort necessary to enforce an integrity policy with IMA is very
>     low: if files with valid signature/HMAC are in the IMA TCB and the
>     IMA policy identifies TCB subjects, the required modification would
>     be to simply deny access to appraised files if the subject does not
>     match policy criteria
> 
> The first version of the patch set which adds support for the
> enforcement of the Biba strict policy can be found at the URL:
> 
> https://www.spinics.net/lists/linux-integrity/msg00392.html

I'd be interested in hearing what other people think.

Mimi
Roberto Sassu Nov. 17, 2017, 2:32 p.m. UTC | #16
On 11/17/2017 2:42 PM, Mimi Zohar wrote:
> On Fri, 2017-11-17 at 13:20 +0100, Roberto Sassu wrote:
>> On 11/16/2017 2:06 PM, Mimi Zohar wrote:
>>> On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
>>>> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
>>>>> On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
>>>>>> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morris@oracle.com> wrote:
>>>>>>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
>>>>>>>
>>>>>>>> I have some experience with SMACK, but not with Apparmor. At least with
>>>>>>>> SMACK the problem is that the LSM depends on integrity protection of
>>>>>>>> the xattrs, but the integrity protection itself depends on the LSM, so
>>>>>>>> there's a cycle. An attacker can much too easily make offline changes
>>>>>>>> which then defeat whatever IMA policy the system might be using.
>>>>>>>
>>>>>>> Isn't this what EVM is supposed to mitigate?
>>>>
>>>> With the default appraisal policy, it can't. IMA determines if a file
>>>> must be appraised depending on metadata whose integrity has not been
>>>> verified yet. A root process is able to load appraised files with
>>>> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0, at the
>>>> same time.
>>>
>>> The LSMs are responsible for protecting their own labels.  Theyhave
>>> the opportunity to verify and deny access to files based on LSM
>>> labels, BEFORE IMA-appraisal is called to verify the file's integrity.
>>
>> Adding in CC the linux-security-module mailing list.
> 
> We need to first clarify, for those reading this thread, that are not
> fully aware of the context of this discussion, that the discussion is
> not relevant to the "lockdown" patch set.
> 
> Kernel modules, the kexec image, IMA policy and firmware call the pre
> and post LSM kernel_read_file hooks.  For these LSM hooks, IMA policy
> rules are not written in terms of LSM labels or any other file
> metadata.  File signatures will always be appraised.
> 
>> LSMs are responsible to enforce a security policy at run-time, while
>> IMA/EVM protect data and metadata against offline attacks. However, if
>> IMA/EVM protect only part of the system, the security policy might not
>> be enforced as expected. I give an example.
>>
>> Suppose that a security policy preserves the integrity of a database by
>> allowing only one application to modify it. Suppose also, that the
>> security policy allows that application to modify files which are not
>> appraised by IMA. Only the database is appraised.
> 
> This use case scenario is really strange.  The IMA policy should be
> verifying the integrity of the application that is allowed to modify
> the database, not the database.

Also the integrity of the database should be verified if you want to
detect offline attacks.


>  From my limited knowledge of databases, databases tend to manage data
> caching themselves at the application level (eg. Direct IO), and avoid
> file buffer caching.  Having IMA calculate the file hash, would negate
> the performance benefits of doing their own data caching.

Maybe I didn't choose a good example. I wanted to show an application
allowed by LSM to access valuable information (appraised) and
non-valuable information (not appraised), and the consequence of not
verifying the association between data and metadata (label) before LSM
makes a security decision.


>> Then, the integrity of the database cannot be guaranteed anymore. When
>> the system is offline, the database label is swapped with one that is
>> not included in the IMA policy. When the system is online again, LSMs
>> would allow the application to access the database, but its integrity
>> is no longer verified. From the users perspective, the application is
>> working correctly, while unauthorized modifications could have be done
>> on the database.
>>
>> In my opinion, protecting the integrity of a TCB against offline and
>> online attacks with LSMs and IMA/EVM, can be achieved in two ways:
> 
> I really doubt that anyone's definition of TCB would include
> databases.

I think it should be, if the goal is to protect the integrity of the
database.

Roberto


>> - all objects accessed by LSM TCB subjects are a subset of IMA TCB
>>     objects, and LSM prevents accesses to LSM TCB objects by processes
>>     outside LSM TCB
>>
>> - all objects accessed by IMA TCB subjects are protected by IMA, IMA
>>     prevents accesses to IMA TCB objects by processes outside IMA TCB, and
>>     LSM TCB subjects are a subset of IMA TCB subjects
>>
>> As you can see, in both cases there is a dependency between the LSM
>> policy and the IMA policy. In the first case, the dependency is on
>> objects and LSM is enforcing integrity. In the second case, the
>> dependency is on subjects, IMA is enforcing integrity and LSM could
>> enforce a more strict integrity policy or a policy with different goals.
>>
>> I prefer the second option because:
>>
>> 1) it easier to write a policy in term of subjects rather than objects
>>
>> 2) LSM does not necessarily enforce an integrity policy; LSM could
>>      enforce a policy for isolation and containment, while IMA could
>>      enforce an integrity policy
>>
>> 3) an integrity policy can be enforced without LSM, and both LSM and IMA
>>      can enforce their own integrity policy
>>
>> 4) the effort necessary to enforce an integrity policy with IMA is very
>>      low: if files with valid signature/HMAC are in the IMA TCB and the
>>      IMA policy identifies TCB subjects, the required modification would
>>      be to simply deny access to appraised files if the subject does not
>>      match policy criteria
>>
>> The first version of the patch set which adds support for the
>> enforcement of the Biba strict policy can be found at the URL:
>>
>> https://www.spinics.net/lists/linux-integrity/msg00392.html
> 
> I'd be interested in hearing what other people think.
> 
> Mimi
>
Stephen Smalley Nov. 17, 2017, 3:58 p.m. UTC | #17
On Fri, 2017-11-17 at 08:42 -0500, Mimi Zohar wrote:
> On Fri, 2017-11-17 at 13:20 +0100, Roberto Sassu wrote:
> > On 11/16/2017 2:06 PM, Mimi Zohar wrote:
> > > On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
> > > > On 11/16/2017 3:13 AM, Mimi Zohar wrote:
> > > > > On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
> > > > > > On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morr
> > > > > > is@oracle.com> wrote:
> > > > > > > On Wed, 15 Nov 2017, Patrick Ohly wrote:
> > > > > > > 
> > > > > > > > I have some experience with SMACK, but not with
> > > > > > > > Apparmor. At least with
> > > > > > > > SMACK the problem is that the LSM depends on integrity
> > > > > > > > protection of
> > > > > > > > the xattrs, but the integrity protection itself depends
> > > > > > > > on the LSM, so
> > > > > > > > there's a cycle. An attacker can much too easily make
> > > > > > > > offline changes
> > > > > > > > which then defeat whatever IMA policy the system might
> > > > > > > > be using.
> > > > > > > 
> > > > > > > Isn't this what EVM is supposed to mitigate?
> > > > 
> > > > With the default appraisal policy, it can't. IMA determines if
> > > > a file
> > > > must be appraised depending on metadata whose integrity has not
> > > > been
> > > > verified yet. A root process is able to load appraised files
> > > > with
> > > > i_uid = 0 and files with missing/invalid HMAC and i_uid != 0,
> > > > at the
> > > > same time.
> > > 
> > > The LSMs are responsible for protecting their own
> > > labels.  Theyhave
> > > the opportunity to verify and deny access to files based on LSM
> > > labels, BEFORE IMA-appraisal is called to verify the file's
> > > integrity.
> > 
> > Adding in CC the linux-security-module mailing list.
> 
> We need to first clarify, for those reading this thread, that are not
> fully aware of the context of this discussion, that the discussion is
> not relevant to the "lockdown" patch set.
> 
> Kernel modules, the kexec image, IMA policy and firmware call the pre
> and post LSM kernel_read_file hooks.  For these LSM hooks, IMA policy
> rules are not written in terms of LSM labels or any other file
> metadata.  File signatures will always be appraised.
> 
> > LSMs are responsible to enforce a security policy at run-time,
> > while
> > IMA/EVM protect data and metadata against offline attacks. However,
> > if
> > IMA/EVM protect only part of the system, the security policy might
> > not
> > be enforced as expected. I give an example.
> > 
> > Suppose that a security policy preserves the integrity of a
> > database by
> > allowing only one application to modify it. Suppose also, that the
> > security policy allows that application to modify files which are
> > not
> > appraised by IMA. Only the database is appraised.
> 
> This use case scenario is really strange.  The IMA policy should be
> verifying the integrity of the application that is allowed to modify
> the database, not the database.
> 
> > From my limited knowledge of databases, databases tend to manage
> > data
> 
> caching themselves at the application level (eg. Direct IO), and
> avoid
> file buffer caching.  Having IMA calculate the file hash, would
> negate
> the performance benefits of doing their own data caching.
> 
> > Then, the integrity of the database cannot be guaranteed anymore.
> > When
> > the system is offline, the database label is swapped with one that
> > is
> > not included in the IMA policy. When the system is online again,
> > LSMs
> > would allow the application to access the database, but its
> > integrity
> > is no longer verified. From the users perspective, the application
> > is
> > working correctly, while unauthorized modifications could have be
> > done
> > on the database.
> > 
> > In my opinion, protecting the integrity of a TCB against offline
> > and
> > online attacks with LSMs and IMA/EVM, can be achieved in two ways:
> 
> I really doubt that anyone's definition of TCB would include
> databases.
> 
> > 
> > - all objects accessed by LSM TCB subjects are a subset of IMA TCB
> >    objects, and LSM prevents accesses to LSM TCB objects by
> > processes
> >    outside LSM TCB
> > 
> > - all objects accessed by IMA TCB subjects are protected by IMA,
> > IMA
> >    prevents accesses to IMA TCB objects by processes outside IMA
> > TCB, and
> >    LSM TCB subjects are a subset of IMA TCB subjects
> > 
> > As you can see, in both cases there is a dependency between the LSM
> > policy and the IMA policy. In the first case, the dependency is on
> > objects and LSM is enforcing integrity. In the second case, the
> > dependency is on subjects, IMA is enforcing integrity and LSM could
> > enforce a more strict integrity policy or a policy with different
> > goals.
> > 
> > I prefer the second option because:
> > 
> > 1) it easier to write a policy in term of subjects rather than
> > objects
> > 
> > 2) LSM does not necessarily enforce an integrity policy; LSM could
> >     enforce a policy for isolation and containment, while IMA could
> >     enforce an integrity policy
> > 
> > 3) an integrity policy can be enforced without LSM, and both LSM
> > and IMA
> >     can enforce their own integrity policy
> > 
> > 4) the effort necessary to enforce an integrity policy with IMA is
> > very
> >     low: if files with valid signature/HMAC are in the IMA TCB and
> > the
> >     IMA policy identifies TCB subjects, the required modification
> > would
> >     be to simply deny access to appraised files if the subject does
> > not
> >     match policy criteria
> > 
> > The first version of the patch set which adds support for the
> > enforcement of the Biba strict policy can be found at the URL:
> > 
> > https://www.spinics.net/lists/linux-integrity/msg00392.html
> 
> I'd be interested in hearing what other people think.

My $0.02, take or leave it as you wish:

First, Biba integrity models don't work well in the real world; that
was one of the motivations for the introduction of Type Enforcement
(c.f. Boebert and Kain 1985, Ross Anderson's Security Engineering, and
many other works in the literature). SELinux TE can be used to enforce
integrity access control goals, and is successfully enforcing such
goals in Android (and to some degree in Fedora/RHEL, modulo the
presence of unconfined domains in the default policy and the
complexities associated with the large and dynamic GNU/Linux TCB). Even
Windows Mandatory Integrity Controls, which are based on Biba, disable
half the Biba model by default to avoid breaking normal system
operation, and are only used in a very constrained manner due to the
limitations of the model.

Second, if you want to protect against offline attacks, use dm-verity
or dm-crypt with an integrity-preserving algorithm.  Trying to keep
extending IMA/EVM to provide a complete solution in this space is a
losing proposition IMHO; you will only end up with something that is
either unusable or insecure - take your pick.  Use IMA for what it was
originally designed to do, i.e. userspace measurement and remote
attestation. 

Third, the integrity framework/modules shouldn't be defining or
enforcing an access control policy; leave that to the security
framework/modules, please.  Some might argue that they started doing
that the day they introduced IMA-appraisal (which itself is an
interesting topic; there is a reason why "remote" is in "remote
attestation", but we'll leave that to another day) but I think it would
be a mistake to extend it to a conventional access control policy like
Biba.  If you truly want a Biba integrity policy, then do it in a small
LSM and use that to motivate extreme stacking.  But think hard whether
Biba is truly the right answer (and if so, what was question that
motivated it), given that it really doesn't work in practice.
Safford, David (GE Global Research, US) Nov. 17, 2017, 8:09 p.m. UTC | #18
> -----Original Message-----

> From: linux-integrity-owner@vger.kernel.org [mailto:linux-integrity-

> owner@vger.kernel.org] On Behalf Of Stephen Smalley

> Sent: Friday, November 17, 2017 10:58 AM

> To: Mimi Zohar <zohar@linux.vnet.ibm.com>; Roberto Sassu

> <roberto.sassu@huawei.com>; Matthew Garrett <mjg59@google.com>;

> James Morris <james.l.morris@oracle.com>

> Cc: Patrick Ohly <patrick.ohly@intel.com>; linux-integrity <linux-

> integrity@vger.kernel.org>

> Subject: EXT: Re: IMA appraisal master plan?

> 

> On Fri, 2017-11-17 at 08:42 -0500, Mimi Zohar wrote:

> > On Fri, 2017-11-17 at 13:20 +0100, Roberto Sassu wrote:

> > > On 11/16/2017 2:06 PM, Mimi Zohar wrote:

> > > > On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:

> > > > > On 11/16/2017 3:13 AM, Mimi Zohar wrote:

> > > > > > On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:

> > > > > > > On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morr

> > > > > > > is@oracle.com> wrote:

> > > > > > > > On Wed, 15 Nov 2017, Patrick Ohly wrote:

> > > > > > > >

> > > > > > > > > I have some experience with SMACK, but not with

> > > > > > > > > Apparmor. At least with SMACK the problem is that the

> > > > > > > > > LSM depends on integrity protection of the xattrs, but

> > > > > > > > > the integrity protection itself depends on the LSM, so

> > > > > > > > > there's a cycle. An attacker can much too easily make

> > > > > > > > > offline changes which then defeat whatever IMA policy

> > > > > > > > > the system might be using.

> > > > > > > >

> > > > > > > > Isn't this what EVM is supposed to mitigate?

> > > > >

> > > > > With the default appraisal policy, it can't. IMA determines if a

> > > > > file must be appraised depending on metadata whose integrity has

> > > > > not been verified yet. A root process is able to load appraised

> > > > > files with i_uid = 0 and files with missing/invalid HMAC and

> > > > > i_uid != 0, at the same time.

> > > >

> > > > The LSMs are responsible for protecting their own labels.

> > > > Theyhave the opportunity to verify and deny access to files based

> > > > on LSM labels, BEFORE IMA-appraisal is called to verify the file's

> > > > integrity.

> > >

> > > Adding in CC the linux-security-module mailing list.

> >

> > We need to first clarify, for those reading this thread, that are not

> > fully aware of the context of this discussion, that the discussion is

> > not relevant to the "lockdown" patch set.

> >

> > Kernel modules, the kexec image, IMA policy and firmware call the pre

> > and post LSM kernel_read_file hooks.  For these LSM hooks, IMA policy

> > rules are not written in terms of LSM labels or any other file

> > metadata.  File signatures will always be appraised.

> >

> > > LSMs are responsible to enforce a security policy at run-time, while

> > > IMA/EVM protect data and metadata against offline attacks. However,

> > > if IMA/EVM protect only part of the system, the security policy

> > > might not be enforced as expected. I give an example.

> > >

... snip
> > >

> > > - all objects accessed by LSM TCB subjects are a subset of IMA TCB

> > >    objects, and LSM prevents accesses to LSM TCB objects by

> > > processes

> > >    outside LSM TCB

> > >

> > > - all objects accessed by IMA TCB subjects are protected by IMA, IMA

> > >    prevents accesses to IMA TCB objects by processes outside IMA

> > > TCB, and

> > >    LSM TCB subjects are a subset of IMA TCB subjects

> > >

> > > As you can see, in both cases there is a dependency between the LSM

> > > policy and the IMA policy. In the first case, the dependency is on

> > > objects and LSM is enforcing integrity. In the second case, the

> > > dependency is on subjects, IMA is enforcing integrity and LSM could

> > > enforce a more strict integrity policy or a policy with different

> > > goals.

> > >

> > > I prefer the second option because:

> > >

> > > 1) it easier to write a policy in term of subjects rather than

> > > objects

> > >

> > > 2) LSM does not necessarily enforce an integrity policy; LSM could

> > >     enforce a policy for isolation and containment, while IMA could

> > >     enforce an integrity policy

> > >

> > > 3) an integrity policy can be enforced without LSM, and both LSM and

> > > IMA

> > >     can enforce their own integrity policy

> > >

> > > 4) the effort necessary to enforce an integrity policy with IMA is

> > > very

> > >     low: if files with valid signature/HMAC are in the IMA TCB and

> > > the

> > >     IMA policy identifies TCB subjects, the required modification

> > > would

> > >     be to simply deny access to appraised files if the subject does

> > > not

> > >     match policy criteria

> > >

> > > The first version of the patch set which adds support for the

> > > enforcement of the Biba strict policy can be found at the URL:

> > >

> > > https://www.spinics.net/lists/linux-integrity/msg00392.html

> >

> > I'd be interested in hearing what other people think.

> 

> My $0.02, take or leave it as you wish:

> 

> First, Biba integrity models don't work well in the real world; that was one of

> the motivations for the introduction of Type Enforcement (c.f. Boebert and

> Kain 1985, Ross Anderson's Security Engineering, and many other works in

> the literature). SELinux TE can be used to enforce integrity access control

> goals, and is successfully enforcing such goals in Android (and to some

> degree in Fedora/RHEL, modulo the presence of unconfined domains in the

> default policy and the complexities associated with the large and dynamic

> GNU/Linux TCB). Even Windows Mandatory Integrity Controls, which are

> based on Biba, disable half the Biba model by default to avoid breaking

> normal system operation, and are only used in a very constrained manner

> due to the limitations of the model.

> 

> Second, if you want to protect against offline attacks, use dm-verity or dm-

> crypt with an integrity-preserving algorithm.  Trying to keep extending

> IMA/EVM to provide a complete solution in this space is a losing proposition

> IMHO; you will only end up with something that is either unusable or

> insecure - take your pick.  Use IMA for what it was originally designed to do,

> i.e. userspace measurement and remote attestation.


Exactly.

I consider it likely that there is _no_ way to provide complete local integrity
guarantees in the presence of off-line (physical) attacks. (Not even with dm-*.)

IMA is about remote attestation,  requiring a specially trusted remote
attestation server. The original goal with IMA appraisal was more along the
lines of "While we are here, and already have hashed the file, why not?", and
"If we can send along a valid signature, it will make the attestation server's job 
easier." For some use cases not involving physical attack, this appraisal can
be useful. 

For EVM we should probably take the same approach. The recent patches
to sign and appraise portable metadata are interesting. But rather than trying 
to make the local appraisal of metadata immune to physical attack (impossible), 
we should simply measure and attest the now portable metadata just like we 
do the data.

> Third, the integrity framework/modules shouldn't be defining or enforcing an

> access control policy; leave that to the security framework/modules, please.

> Some might argue that they started doing that the day they introduced IMA-

> appraisal (which itself is an interesting topic; there is a reason why "remote"

> is in "remote attestation", but we'll leave that to another day) but I think it

> would be a mistake to extend it to a conventional access control policy like

> Biba.  If you truly want a Biba integrity policy, then do it in a small LSM and

> use that to motivate extreme stacking.  But think hard whether Biba is truly

> the right answer (and if so, what was question that motivated it), given that it

> really doesn't work in practice.


Again, exactly. Local appraisal is not a substitute for either remote attestation,
or for a real LSM with a good policy.
Casey Schaufler Nov. 18, 2017, 7:29 p.m. UTC | #19
On 11/17/2017 9:54 AM, Stephen Smalley wrote:
> On Fri, 2017-11-17 at 08:42 -0500, Mimi Zohar wrote:
>> On Fri, 2017-11-17 at 13:20 +0100, Roberto Sassu wrote:
>>> On 11/16/2017 2:06 PM, Mimi Zohar wrote:
>>>> On Thu, 2017-11-16 at 10:23 +0100, Roberto Sassu wrote:
>>>>> On 11/16/2017 3:13 AM, Mimi Zohar wrote:
>>>>>> On Wed, 2017-11-15 at 16:05 -0800, Matthew Garrett wrote:
>>>>>>> On Wed, Nov 15, 2017 at 4:02 PM, James Morris <james.l.morr
>>>>>>> is@oracle.com> wrote:
>>>>>>>> On Wed, 15 Nov 2017, Patrick Ohly wrote:
>>>>>>>>
>>>>>>>>> I have some experience with SMACK, but not with
>>>>>>>>> Apparmor. At least with
>>>>>>>>> SMACK the problem is that the LSM depends on integrity
>>>>>>>>> protection of
>>>>>>>>> the xattrs, but the integrity protection itself depends
>>>>>>>>> on the LSM, so
>>>>>>>>> there's a cycle. An attacker can much too easily make
>>>>>>>>> offline changes
>>>>>>>>> which then defeat whatever IMA policy the system might
>>>>>>>>> be using.
>>>>>>>> Isn't this what EVM is supposed to mitigate?
>>>>> With the default appraisal policy, it can't. IMA determines if
>>>>> a file
>>>>> must be appraised depending on metadata whose integrity has not
>>>>> been
>>>>> verified yet. A root process is able to load appraised files
>>>>> with
>>>>> i_uid = 0 and files with missing/invalid HMAC and i_uid != 0,
>>>>> at the
>>>>> same time.
>>>> The LSMs are responsible for protecting their own
>>>> labels.  Theyhave
>>>> the opportunity to verify and deny access to files based on LSM
>>>> labels, BEFORE IMA-appraisal is called to verify the file's
>>>> integrity.
>>> Adding in CC the linux-security-module mailing list.
>> We need to first clarify, for those reading this thread, that are not
>> fully aware of the context of this discussion, that the discussion is
>> not relevant to the "lockdown" patch set.
>>
>> Kernel modules, the kexec image, IMA policy and firmware call the pre
>> and post LSM kernel_read_file hooks.  For these LSM hooks, IMA policy
>> rules are not written in terms of LSM labels or any other file
>> metadata.  File signatures will always be appraised.
>>
>>> LSMs are responsible to enforce a security policy at run-time,
>>> while
>>> IMA/EVM protect data and metadata against offline attacks. However,
>>> if
>>> IMA/EVM protect only part of the system, the security policy might
>>> not
>>> be enforced as expected. I give an example.
>>>
>>> Suppose that a security policy preserves the integrity of a
>>> database by
>>> allowing only one application to modify it. Suppose also, that the
>>> security policy allows that application to modify files which are
>>> not
>>> appraised by IMA. Only the database is appraised.
>> This use case scenario is really strange.  The IMA policy should be
>> verifying the integrity of the application that is allowed to modify
>> the database, not the database.
>>
>>> From my limited knowledge of databases, databases tend to manage
>>> data
>> caching themselves at the application level (eg. Direct IO), and
>> avoid
>> file buffer caching.  Having IMA calculate the file hash, would
>> negate
>> the performance benefits of doing their own data caching.
>>
>>> Then, the integrity of the database cannot be guaranteed anymore.
>>> When
>>> the system is offline, the database label is swapped with one that
>>> is
>>> not included in the IMA policy. When the system is online again,
>>> LSMs
>>> would allow the application to access the database, but its
>>> integrity
>>> is no longer verified. From the users perspective, the application
>>> is
>>> working correctly, while unauthorized modifications could have be
>>> done
>>> on the database.
>>>
>>> In my opinion, protecting the integrity of a TCB against offline
>>> and
>>> online attacks with LSMs and IMA/EVM, can be achieved in two ways:
>> I really doubt that anyone's definition of TCB would include
>> databases.

Every system I have ever encountered had a database
of some flavor in the TCB. I have an Orange Book B1
and two common criteria certificates in my closet, and
worked with everyone who did TCSEC evaluations back in
the day. I firmly assert that your skepticism is ill
founded.

>>
>>> - all objects accessed by LSM TCB subjects are a subset of IMA TCB
>>>    objects, and LSM prevents accesses to LSM TCB objects by
>>> processes
>>>    outside LSM TCB
>>>
>>> - all objects accessed by IMA TCB subjects are protected by IMA,
>>> IMA
>>>    prevents accesses to IMA TCB objects by processes outside IMA
>>> TCB, and
>>>    LSM TCB subjects are a subset of IMA TCB subjects
>>>
>>> As you can see, in both cases there is a dependency between the LSM
>>> policy and the IMA policy. In the first case, the dependency is on
>>> objects and LSM is enforcing integrity. In the second case, the
>>> dependency is on subjects, IMA is enforcing integrity and LSM could
>>> enforce a more strict integrity policy or a policy with different
>>> goals.
>>>
>>> I prefer the second option because:
>>>
>>> 1) it easier to write a policy in term of subjects rather than
>>> objects
>>>
>>> 2) LSM does not necessarily enforce an integrity policy; LSM could
>>>     enforce a policy for isolation and containment, while IMA could
>>>     enforce an integrity policy
>>>
>>> 3) an integrity policy can be enforced without LSM, and both LSM
>>> and IMA
>>>     can enforce their own integrity policy
>>>
>>> 4) the effort necessary to enforce an integrity policy with IMA is
>>> very
>>>     low: if files with valid signature/HMAC are in the IMA TCB and
>>> the
>>>     IMA policy identifies TCB subjects, the required modification
>>> would
>>>     be to simply deny access to appraised files if the subject does
>>> not
>>>     match policy criteria
>>>
>>> The first version of the patch set which adds support for the
>>> enforcement of the Biba strict policy can be found at the URL:
>>>
>>> https://www.spinics.net/lists/linux-integrity/msg00392.html
>> I'd be interested in hearing what other people think.
> My $0.02, take or leave it as you wish:
>
> First, Biba integrity models don't work well in the real world;

I shipped a Unix system (Trusted Irix) that supported Biba
integrity and the model worked just fine. There are two things
that came up with it that are quite important. We used system
integrity and user integrity for basic operation, and that was
completely understandable and supportable. We supported levels
(which we called grades) and categories (referred to as divisions)
fully, but no one ever wanted to deal with that level of
complexity.

The model works fine, so long as you don't go overboard with
granularity.

>  that
> was one of the motivations for the introduction of Type Enforcement
> (c.f. Boebert and Kain 1985, Ross Anderson's Security Engineering, and
> many other works in the literature). SELinux TE can be used to enforce
> integrity access control goals, and is successfully enforcing such
> goals in Android (and to some degree in Fedora/RHEL, modulo the
> presence of unconfined domains in the default policy and the
> complexities associated with the large and dynamic GNU/Linux TCB). Even
> Windows Mandatory Integrity Controls, which are based on Biba, disable
> half the Biba model by default to avoid breaking normal system
> operation, and are only used in a very constrained manner due to the
> limitations of the model.

Based on my experience in real world deployment I would
argue that it's not a failing in the security model. I suggest
that the problem is the same one we see with capabilities,
which is that the programs are written assuming one security
model and then expected to work unmodified under another.
Security schemes that attempt to accommodate this invariably
end up with excesses in complexity.

> Second, if you want to protect against offline attacks, use dm-verity
> or dm-crypt with an integrity-preserving algorithm.  Trying to keep
> extending IMA/EVM to provide a complete solution in this space is a
> losing proposition IMHO; you will only end up with something that is
> either unusable or insecure - take your pick.  Use IMA for what it was
> originally designed to do, i.e. userspace measurement and remote
> attestation. 
>
> Third, the integrity framework/modules shouldn't be defining or
> enforcing an access control policy; leave that to the security
> framework/modules, please.

I agree. Mostly. Access control systems should be implemented
using the LSM infrastructure. I don't know whether I would call
file corruption detection (by whatever means or to which criteria)
an access control feature. I could argue it either way.

> Some might argue that they started doing
> that the day they introduced IMA-appraisal (which itself is an
> interesting topic; there is a reason why "remote" is in "remote
> attestation", but we'll leave that to another day) but I think it would
> be a mistake to extend it to a conventional access control policy like
> Biba.

Expanding the facilities of a sub-system is usually a bad idea.
I agree here. I will point to the addition of roles and Bell &
LaPadula to the basic type enforcement of SELinux as examples.
Had those been done are separate modules rather than expansions
the development of policy would be significantly simpler.

> If you truly want a Biba integrity policy, then do it in a small
> LSM

That is the right solution to my mind. You can do it with
SELinux policy or Smack rules, but you're bringing in baggage
you may not want or need in either case because those modules
are more general.

> and use that to motivate extreme stacking.

Always a good reason!

> But think hard whether
> Biba is truly the right answer (and if so, what was question that
> motivated it), given that it really doesn't work in practice.

I wouldn't accept that as a given. As with any security scheme,
using Biba as intended works just fine. Trying to stretch it beyond
that is where problems arise.

In Trix we used Biba because it was clear that there were protections
you could wrestle Bell & LaPadula into enforcing that Biba just
naturally took care of.

Excess of granularity is always a problem. You can do that with
SELinux, Smack, B&L or Biba, but you don't have to.
James Morris Nov. 19, 2017, 8:47 p.m. UTC | #20
On Fri, 17 Nov 2017, Roberto Sassu wrote:

> LSMs are responsible to enforce a security policy at run-time, while
> IMA/EVM protect data and metadata against offline attacks.

In my view, IMA can also protect against making an online attack 
persistent across boots, and that would be the most compelling use of it 
for many general purpose applications.
Patrick Ohly Nov. 20, 2017, 10:20 a.m. UTC | #21
On Mon, 2017-11-20 at 07:47 +1100, James Morris wrote:
> On Fri, 17 Nov 2017, Roberto Sassu wrote:
> 
> > LSMs are responsible to enforce a security policy at run-time,
> > while IMA/EVM protect data and metadata against offline attacks.
> 
> In my view, IMA can also protect against making an online attack 
> persistent across boots, and that would be the most compelling use of
> it for many general purpose applications.

I do not quite buy that interpretation. If the online attack succeeds
in bypassing the run-time checks, for example with a full root exploit,
then he has pretty much the same capabilities to make persistent file
changes as during an offline attack.

When allowing local hashing, it's actually worse: during an offline
attack, the attacker might not have access to the TPM and thus cannot
easily update the EVM HMAC. During an online attack, the kernel will
happily update that and the IMA hash for the attacker, resulting in a
file that passes appraisal after a reboot.
Mimi Zohar Nov. 20, 2017, 2:59 p.m. UTC | #22
On Mon, 2017-11-20 at 11:20 +0100, Patrick Ohly wrote:
> On Mon, 2017-11-20 at 07:47 +1100, James Morris wrote:
> > On Fri, 17 Nov 2017, Roberto Sassu wrote:
> > 
> > > LSMs are responsible to enforce a security policy at run-time,
> > > while IMA/EVM protect data and metadata against offline attacks.
> > 
> > In my view, IMA can also protect against making an online attack 
> > persistent across boots, and that would be the most compelling use of
> > it for many general purpose applications.
> 
> I do not quite buy that interpretation. If the online attack succeeds
> in bypassing the run-time checks, for example with a full root exploit,
> then he has pretty much the same capabilities to make persistent file
> changes as during an offline attack.

In the face of a full root exploit, there is not much that one can do,
"other" than to detect it.  This is why remote attestation is so
important.

> When allowing local hashing, it's actually worse: during an offline
> attack, the attacker might not have access to the TPM and thus cannot
> easily update the EVM HMAC. During an online attack, the kernel will
> happily update that and the IMA hash for the attacker, resulting in a
> file that passes appraisal after a reboot.

The assumption is that most files in the TCB are not changing and are
signed.  Custom policies should require file signatures for these
files.

Assuming that the private keys that are used to sign these files, as
well as the private key used for signing other keys added to the IMA
keyring, are stored off line, new files can not be signed.

The number of mutable files in the TCB should be very limited,
probably < 20 files.  Their usage can be constrained by MAC.

That said, IMA/IMA-appraisal is work in progress.  There are still
measurement/appraisal gaps that need to be closed.  One such example
are files read by interpreters and interpreted files.  There have been
some initial proposals in this area.

Mimi
Patrick Ohly Nov. 20, 2017, 4:15 p.m. UTC | #23
On Mon, 2017-11-20 at 09:59 -0500, Mimi Zohar wrote:
> > When allowing local hashing, it's actually worse: during an offline
> > attack, the attacker might not have access to the TPM and thus
> > cannot
> > easily update the EVM HMAC. During an online attack, the kernel
> > will
> > happily update that and the IMA hash for the attacker, resulting in
> > a
> > file that passes appraisal after a reboot.
> 
> The assumption is that most files in the TCB are not changing and are
> signed.  Custom policies should require file signatures for these
> files.
> 
> Assuming that the private keys that are used to sign these files, as
> well as the private key used for signing other keys added to the IMA
> keyring, are stored off line, new files can not be signed.
> 
> The number of mutable files in the TCB should be very limited,
> probably < 20 files.  Their usage can be constrained by MAC.

I'm not sure what exactly "constrained by MAC" implies, but I suspect
that these mutable files will be as important for the integrity of the
TCB as everything else (<insert my systemd configuration file example
again here>). Compromised is compromised, an installation cannot be
"half compromised". So once the policy allows mutable files, a run-time 
exploit that bypasses the MAC can compromise the TCB permanently.

> That said, IMA/IMA-appraisal is work in progress.  There are still
> measurement/appraisal gaps that need to be closed.  One such example
> are files read by interpreters and interpreted files.  There have
> been some initial proposals in this area.

That's what brings us back to my initial question: are the current set
of patches enough to make appraisal useful? Matthew seems to be
optimistic that the answer is yes and I certainly don't want to
discourage him especially as he's doing some actual work while I
couldn't do that, but I remain a bit more skeptical.
Roberto Sassu Nov. 21, 2017, 9:33 a.m. UTC | #24
On 11/20/2017 11:20 AM, Patrick Ohly wrote:
> On Mon, 2017-11-20 at 07:47 +1100, James Morris wrote:
>> On Fri, 17 Nov 2017, Roberto Sassu wrote:
>>
>>> LSMs are responsible to enforce a security policy at run-time,
>>> while IMA/EVM protect data and metadata against offline attacks.
>>
>> In my view, IMA can also protect against making an online attack
>> persistent across boots, and that would be the most compelling use of
>> it for many general purpose applications.

It would be possible, if IMA knows when the system is in the expected
state. For example, if the system is in the expected state after digest
lists have been loaded, IMA could erase the EVM key, sealed to that
state, when a file with unknown digest is measured. The system won't be
able to produce valid HMACs, and files modified after the attack can be
identified at the next boot, due to the invalid HMAC. Also accessing
files with invalid HMAC will cause the EVM key to be zeroed.

Since IMA would erase the EVM key when a new measurement entry is
created, digests of mutable files with valid HMAC should not be added to
the measurement list (the initial digest must be provided with a digest
list, or files must be signed). This requires that the integrity of
mutable files is guaranteed by LSMs or by IMA, with the patch set 'ima:
preserve integrity of dynamic data'.


> I do not quite buy that interpretation. If the online attack succeeds
> in bypassing the run-time checks, for example with a full root exploit,
> then he has pretty much the same capabilities to make persistent file
> changes as during an offline attack.

If the full root exploit modifies the current system state, persistent
changes can be detected, as I explained above. The effectiveness of the
solution depends on which checks are done by the system. For example, in
addition to checking if the digest of measured files is in a digest
list, IMA could check that a specific application is running (e.g.
antivirus) and that the firewall has been started before network
services. More checks increase the likelihood that the full root exploit
causes a system state change.

Roberto


> When allowing local hashing, it's actually worse: during an offline
> attack, the attacker might not have access to the TPM and thus cannot
> easily update the EVM HMAC. During an online attack, the kernel will
> happily update that and the IMA hash for the attacker, resulting in a
> file that passes appraisal after a reboot.
>
James Morris Nov. 21, 2017, 10:05 a.m. UTC | #25
On Mon, 20 Nov 2017, Mimi Zohar wrote:

> On Mon, 2017-11-20 at 11:20 +0100, Patrick Ohly wrote:
> > On Mon, 2017-11-20 at 07:47 +1100, James Morris wrote:
> > > On Fri, 17 Nov 2017, Roberto Sassu wrote:
> > > 
> > > > LSMs are responsible to enforce a security policy at run-time,
> > > > while IMA/EVM protect data and metadata against offline attacks.
> > > 
> > > In my view, IMA can also protect against making an online attack 
> > > persistent across boots, and that would be the most compelling use of
> > > it for many general purpose applications.
> > 
> > I do not quite buy that interpretation. If the online attack succeeds
> > in bypassing the run-time checks, for example with a full root exploit,
> > then he has pretty much the same capabilities to make persistent file
> > changes as during an offline attack.
> 
> In the face of a full root exploit, there is not much that one can do,
> "other" than to detect it.  This is why remote attestation is so
> important.

Right, although the consensus seems to be that RA is essential rather than 
simply important.
Mimi Zohar Nov. 21, 2017, 2:05 p.m. UTC | #26
On Tue, 2017-11-21 at 10:33 +0100, Roberto Sassu wrote:
> On 11/20/2017 11:20 AM, Patrick Ohly wrote:
> > On Mon, 2017-11-20 at 07:47 +1100, James Morris wrote:
> >> On Fri, 17 Nov 2017, Roberto Sassu wrote:
> >>
> >>> LSMs are responsible to enforce a security policy at run-time,
> >>> while IMA/EVM protect data and metadata against offline attacks.
> >>
> >> In my view, IMA can also protect against making an online attack
> >> persistent across boots, and that would be the most compelling use of
> >> it for many general purpose applications.
> 
> It would be possible, if IMA knows when the system is in the expected
> state. For example, if the system is in the expected state after digest
> lists have been loaded, IMA could erase the EVM key, sealed to that
> state, when a file with unknown digest is measured. The system won't be
> able to produce valid HMACs, and files modified after the attack can be
> identified at the next boot, due to the invalid HMAC. Also accessing
> files with invalid HMAC will cause the EVM key to be zeroed.

Roberto, allowing the system to boot with an EVM HMAC key, but then
transition to a point when it can't be used, is a good idea.  The
transitioning, however, shouldn't be tied to white lists.  Please keep
these concepts independent of each other.

Preventing a device from booting is major.  Is there a less drastic
solution that would allow detection, without resealing the EVM HMAC
key so it can't be used?

Years ago Dave and I had a prototype of "locking" mutable files, after
a certain point in the boot process, working.  It allowed the ~20
mutable files to be created/updated, as necessary.  The limitation was
that any package updates or new packages installations needed to be
done during this window, before the transition, as well.

Mimi
Roberto Sassu Nov. 21, 2017, 3:25 p.m. UTC | #27
On 11/21/2017 3:05 PM, Mimi Zohar wrote:
> On Tue, 2017-11-21 at 10:33 +0100, Roberto Sassu wrote:
>> On 11/20/2017 11:20 AM, Patrick Ohly wrote:
>>> On Mon, 2017-11-20 at 07:47 +1100, James Morris wrote:
>>>> On Fri, 17 Nov 2017, Roberto Sassu wrote:
>>>>
>>>>> LSMs are responsible to enforce a security policy at run-time,
>>>>> while IMA/EVM protect data and metadata against offline attacks.
>>>>
>>>> In my view, IMA can also protect against making an online attack
>>>> persistent across boots, and that would be the most compelling use of
>>>> it for many general purpose applications.
>>
>> It would be possible, if IMA knows when the system is in the expected
>> state. For example, if the system is in the expected state after digest
>> lists have been loaded, IMA could erase the EVM key, sealed to that
>> state, when a file with unknown digest is measured. The system won't be
>> able to produce valid HMACs, and files modified after the attack can be
>> identified at the next boot, due to the invalid HMAC. Also accessing
>> files with invalid HMAC will cause the EVM key to be zeroed.
> 
> Roberto, allowing the system to boot with an EVM HMAC key, but then
> transition to a point when it can't be used, is a good idea.  The
> transitioning, however, shouldn't be tied to white lists.  Please keep
> these concepts independent of each other.

A predictable system state can be achieved also with file signatures.
The system works as expected when it uses the provided public key to
verify signatures and grants access to signed files. But also in this
case, IMA should know if mutable files are good or not. With the
enforcement of an integrity policy on appraised files, a mutable file is
good if it has a valid HMAC.

An important remark is that having a predictable state does not prevent
reporting all measurements protected with another PCR. The predictable
state is necessary to determine when the EVM key can be used to
calculate HMACs. Also, the EVM key should be securely generated (e.g. by
setting the sensitiveDataOrigin bit with TPM 2.0) and available only
when the sealing policy is verified.


> Preventing a device from booting is major.  Is there a less drastic
> solution that would allow detection, without resealing the EVM HMAC
> key so it can't be used?

With the enforcement of the Biba strict policy, the EVM key will not be
erased, because IMA prevents corruption of mutable files. I suggest to
not measure files if access will be denied by appraisal.

In the next version of the patch set 'ima: preserve integrity of dynamic
data', I will introduce the policy low watermark for objects. Instead of
denying writing of mutable files by processes outside the TCB, IMA will
allow the operation and demote those files (remove the HMAC).

If appraisal is in enforcing mode, access to demoted files will be
denied. Otherwise, they will be measured (patch 2/2 of the patch set
excludes from measurement only files with appraisal status
INTEGRITY_PASS). The EVM key will be erased before a TCB process reads a
demoted file. At the next boot, the EVM key can be used if demoted files
are not accessed by TCB processes.


> Years ago Dave and I had a prototype of "locking" mutable files, after
> a certain point in the boot process, working.  It allowed the ~20
> mutable files to be created/updated, as necessary.  The limitation was
> that any package updates or new packages installations needed to be
> done during this window, before the transition, as well.

If the TCB contains only processes that don't corrupt mutable files and
those files are protected with the enforcement of an integrity policy,
locking them wouldn't be necessary.

Roberto
Mimi Zohar Nov. 21, 2017, 3:53 p.m. UTC | #28
On Tue, 2017-11-21 at 16:25 +0100, Roberto Sassu wrote:

> In the next version of the patch set 'ima: preserve integrity of dynamic
> data', I will introduce the policy low watermark for objects. Instead of
> denying writing of mutable files by processes outside the TCB, IMA will
> allow the operation and demote those files (remove the HMAC).

There has been no consensus for the existing patch set you've posted.
In fact, everyone who has responded said to make it a separate LSM.
Extending the patch set makes no sense.

Mimi
diff mbox

Patch

diff --git a/include/linux/integrity.h b/include/linux/integrity.h
index c2d6082a1a4c..858d3f4a2241 100644
--- a/include/linux/integrity.h
+++ b/include/linux/integrity.h
@@ -14,6 +14,7 @@ 
 
 enum integrity_status {
 	INTEGRITY_PASS = 0,
+	INTEGRITY_PASS_IMMUTABLE,
 	INTEGRITY_FAIL,
 	INTEGRITY_NOLABEL,
 	INTEGRITY_NOXATTRS,
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index f5f12727771a..2ff02459fcfd 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -48,7 +48,7 @@  int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
 		  size_t req_xattr_value_len, char *digest);
 int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
 		  const char *req_xattr_value,
-		  size_t req_xattr_value_len, char *digest);
+		  size_t req_xattr_value_len, char type, char *digest);
 int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
 		  char *hmac_val);
 int evm_init_secfs(void);
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 1d32cd20009a..e526f0f5aaaf 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -138,7 +138,7 @@  static struct shash_desc *init_desc(char type)
  * protection.)
  */
 static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
-			  char *digest)
+			  char type, char *digest)
 {
 	struct h_misc {
 		unsigned long ino;
@@ -149,8 +149,13 @@  static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
 	} hmac_misc;
 
 	memset(&hmac_misc, 0, sizeof(hmac_misc));
-	hmac_misc.ino = inode->i_ino;
-	hmac_misc.generation = inode->i_generation;
+	/* Don't include the inode or generation number in portable
+	 * signatures
+	 */
+	if (type != EVM_XATTR_PORTABLE_DIGSIG) {
+		hmac_misc.ino = inode->i_ino;
+		hmac_misc.generation = inode->i_generation;
+	}
 	/* The hmac uid and gid must be encoded in the initial user
 	 * namespace (not the filesystems user namespace) as encoding
 	 * them in the filesystems user namespace allows an attack
@@ -163,7 +168,8 @@  static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
 	hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
 	hmac_misc.mode = inode->i_mode;
 	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)
 		crypto_shash_update(desc, &inode->i_sb->s_uuid.b[0],
 				    sizeof(inode->i_sb->s_uuid));
 	crypto_shash_final(desc, digest);
@@ -189,6 +195,7 @@  static int evm_calc_hmac_or_hash(struct dentry *dentry,
 	char *xattr_value = NULL;
 	int error;
 	int size;
+	bool ima_present = false;
 
 	if (!(inode->i_opflags & IOP_XATTR))
 		return -EOPNOTSUPP;
@@ -199,11 +206,18 @@  static int evm_calc_hmac_or_hash(struct dentry *dentry,
 
 	error = -ENODATA;
 	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
+		bool is_ima = false;
+
+		if (strcmp(*xattrname, XATTR_NAME_IMA) == 0)
+			is_ima = true;
+
 		if ((req_xattr_name && req_xattr_value)
 		    && !strcmp(*xattrname, req_xattr_name)) {
 			error = 0;
 			crypto_shash_update(desc, (const u8 *)req_xattr_value,
 					     req_xattr_value_len);
+			if (is_ima)
+				ima_present = true;
 			continue;
 		}
 		size = vfs_getxattr_alloc(dentry, *xattrname,
@@ -218,9 +232,14 @@  static int evm_calc_hmac_or_hash(struct dentry *dentry,
 		error = 0;
 		xattr_size = size;
 		crypto_shash_update(desc, (const u8 *)xattr_value, xattr_size);
+		if (is_ima)
+			ima_present = true;
 	}
-	hmac_add_misc(desc, inode, digest);
+	hmac_add_misc(desc, inode, type, digest);
 
+	/* Portable EVM signatures must include an IMA hash */
+	if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
+		return -EPERM;
 out:
 	kfree(xattr_value);
 	kfree(desc);
@@ -232,17 +251,45 @@  int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
 		  char *digest)
 {
 	return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
-				req_xattr_value_len, EVM_XATTR_HMAC, digest);
+			       req_xattr_value_len, EVM_XATTR_HMAC, digest);
 }
 
 int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
 		  const char *req_xattr_value, size_t req_xattr_value_len,
-		  char *digest)
+		  char type, char *digest)
 {
 	return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
-				req_xattr_value_len, IMA_XATTR_DIGEST, digest);
+				     req_xattr_value_len, type, digest);
+}
+
+static int evm_is_immutable(struct dentry *dentry, struct inode *inode)
+{
+	const struct evm_ima_xattr_data *xattr_data = NULL;
+	struct integrity_iint_cache *iint;
+	int rc = 0;
+
+	iint = integrity_iint_find(inode);
+	if (iint && (iint->flags & EVM_IMMUTABLE_DIGSIG))
+		return 1;
+
+	/* Do this the hard way */
+	rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
+				GFP_NOFS);
+	if (rc <= 0) {
+		if (rc == -ENODATA)
+			return 0;
+		return rc;
+	}
+	if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG)
+		rc = 1;
+	else
+		rc = 0;
+
+	kfree(xattr_data);
+	return rc;
 }
 
+
 /*
  * Calculate the hmac and update security.evm xattr
  *
@@ -255,6 +302,16 @@  int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
 	struct evm_ima_xattr_data xattr_data;
 	int rc = 0;
 
+	/*
+	 * Don't permit any transformation of the EVM xattr if the signature
+	 * is of an immutable type
+	 */
+	rc = evm_is_immutable(dentry, inode);
+	if (rc < 0)
+		return rc;
+	if (rc)
+		return -EPERM;
+
 	rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
 			   xattr_value_len, xattr_data.digest);
 	if (rc == 0) {
@@ -280,7 +337,7 @@  int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
 	}
 
 	crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
-	hmac_add_misc(desc, inode, hmac_val);
+	hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val);
 	kfree(desc);
 	return 0;
 }
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 063d38aef64e..485f235234ab 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -120,7 +120,8 @@  static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 	enum integrity_status evm_status = INTEGRITY_PASS;
 	int rc, xattr_len;
 
-	if (iint && iint->evm_status == INTEGRITY_PASS)
+	if (iint && (iint->evm_status == INTEGRITY_PASS ||
+		     iint->evm_status == INTEGRITY_PASS_IMMUTABLE))
 		return iint->evm_status;
 
 	/* if status is not PASS, try to check again - against -ENOMEM */
@@ -161,22 +162,26 @@  static enum integrity_status evm_verify_hmac(struct dentry *dentry,
 			rc = -EINVAL;
 		break;
 	case EVM_IMA_XATTR_DIGSIG:
+	case EVM_XATTR_PORTABLE_DIGSIG:
 		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
-				xattr_value_len, calc.digest);
+				   xattr_value_len, xattr_data->type,
+				   calc.digest);
 		if (rc)
 			break;
 		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
 					(const char *)xattr_data, xattr_len,
 					calc.digest, sizeof(calc.digest));
 		if (!rc) {
-			/* Replace RSA with HMAC if not mounted readonly and
-			 * not immutable
-			 */
-			if (!IS_RDONLY(d_backing_inode(dentry)) &&
-			    !IS_IMMUTABLE(d_backing_inode(dentry)))
+			if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) {
+				if (iint)
+					iint->flags |= EVM_IMMUTABLE_DIGSIG;
+				evm_status = INTEGRITY_PASS_IMMUTABLE;
+			} else if (!IS_RDONLY(d_backing_inode(dentry)) &&
+				   !IS_IMMUTABLE(d_backing_inode(dentry))) {
 				evm_update_evmxattr(dentry, xattr_name,
 						    xattr_value,
 						    xattr_value_len);
+			}
 		}
 		break;
 	default:
@@ -277,7 +282,7 @@  static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
  * affect security.evm.  An interesting side affect of writing posix xattr
  * acls is their modifying of the i_mode, which is included in security.evm.
  * For posix xattr acls only, permit security.evm, even if it currently
- * doesn't exist, to be updated.
+ * doesn't exist, to be updated unless the EVM signature is immutable.
  */
 static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
 			     const void *xattr_value, size_t xattr_value_len)
@@ -345,7 +350,8 @@  int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
 	if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
 		if (!xattr_value_len)
 			return -EINVAL;
-		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG)
+		if (xattr_data->type != EVM_IMA_XATTR_DIGSIG &&
+		    xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG)
 			return -EPERM;
 	}
 	return evm_protect_xattr(dentry, xattr_name, xattr_value,
@@ -422,6 +428,9 @@  void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
 /**
  * evm_inode_setattr - prevent updating an invalid EVM extended attribute
  * @dentry: pointer to the affected dentry
+ *
+ * Permit update of file attributes when files have a valid EVM signature,
+ * except in the case of them having an immutable portable signature.
  */
 int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 809ba70fbbbf..8336c70dc6bc 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -229,7 +229,9 @@  int ima_appraise_measurement(enum ima_hooks func,
 	}
 
 	status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
-	if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
+	if ((status != INTEGRITY_PASS) &&
+	    (status != INTEGRITY_PASS_IMMUTABLE) &&
+	    (status != INTEGRITY_UNKNOWN)) {
 		if ((status == INTEGRITY_NOLABEL)
 		    || (status == INTEGRITY_NOXATTRS))
 			cause = "missing-HMAC";
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index a53e7e4ab06c..cbc7de33fac7 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -33,6 +33,7 @@ 
 #define IMA_DIGSIG_REQUIRED	0x02000000
 #define IMA_PERMIT_DIRECTIO	0x04000000
 #define IMA_NEW_FILE		0x08000000
+#define EVM_IMMUTABLE_DIGSIG	0x10000000
 
 #define IMA_DO_MASK		(IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
 				 IMA_APPRAISE_SUBMASK)
@@ -58,6 +59,7 @@  enum evm_ima_xattr_type {
 	EVM_XATTR_HMAC,
 	EVM_IMA_XATTR_DIGSIG,
 	IMA_XATTR_DIGEST_NG,
+	EVM_XATTR_PORTABLE_DIGSIG,
 	IMA_XATTR_LAST
 };