diff mbox series

[v5,7/8] ima: support fs-verity file digest based version 3 signatures

Message ID 20220211214310.119257-8-zohar@linux.ibm.com (mailing list archive)
State Superseded
Headers show
Series ima: support fs-verity digests and signatures | expand

Commit Message

Mimi Zohar Feb. 11, 2022, 9:43 p.m. UTC
Instead of calculating a regular file hash and verifying the signature
stored in the 'security.ima' xattr against the calculated file hash, get
fs-verity's file digest and verify the signature (version 3) stored in
'security.ima' against the digest.

The policy rule 'appraise_type=' option is extended to support 'sigv3',
which is initiality limited to fs-verity.

The fs-verity 'appraise' rules are identified by the 'digest-type=verity'
option and require the 'appraise_type=sigv3' option.  The following
'appraise' policy rule requires fsverity file digests.  (The rule may be
constrained, for example based on a fsuuid or LSM label.)

Basic fs-verity policy rule example:
  appraise func=BPRM_CHECK digest_type=verity appraise_type=sigv3

Lastly, for IMA to differentiate between the original IMA signature
from an fs-verity signature a new 'xattr_type' named IMA_VERITY_DIGSIG
is defined.

Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
 Documentation/ABI/testing/ima_policy      | 28 ++++++--
 Documentation/security/IMA-templates.rst  |  4 +-
 security/integrity/ima/ima_appraise.c     | 79 +++++++++++++++++++++--
 security/integrity/ima/ima_policy.c       | 26 ++++++--
 security/integrity/ima/ima_template_lib.c |  3 +-
 security/integrity/integrity.h            |  5 +-
 6 files changed, 127 insertions(+), 18 deletions(-)

Comments

Eric Biggers Feb. 24, 2022, 1:24 a.m. UTC | #1
On Fri, Feb 11, 2022 at 04:43:09PM -0500, Mimi Zohar wrote:
> Instead of calculating a regular file hash and verifying the signature
> stored in the 'security.ima' xattr against the calculated file hash, get
> fs-verity's file digest and verify the signature (version 3) stored in
> 'security.ima' against the digest.
> 
> The policy rule 'appraise_type=' option is extended to support 'sigv3',
> which is initiality limited to fs-verity.
> 
> The fs-verity 'appraise' rules are identified by the 'digest-type=verity'
> option and require the 'appraise_type=sigv3' option.  The following
> 'appraise' policy rule requires fsverity file digests.  (The rule may be
> constrained, for example based on a fsuuid or LSM label.)
> 
> Basic fs-verity policy rule example:
>   appraise func=BPRM_CHECK digest_type=verity appraise_type=sigv3
> 
> Lastly, for IMA to differentiate between the original IMA signature
> from an fs-verity signature a new 'xattr_type' named IMA_VERITY_DIGSIG
> is defined.

I'm having a hard time understanding this patch.  Can you please describe the
motivation for doing things, not just the things themselves, and make sure the
explanation is understandable to someone who isn't an IMA expert?

> diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
> index ff3c906738cb..508053b8dd0a 100644
> --- a/Documentation/ABI/testing/ima_policy
> +++ b/Documentation/ABI/testing/ima_policy
> @@ -47,7 +47,7 @@ Description:
>  			fgroup:= decimal value
>  		  lsm:  are LSM specific
>  		  option:
> -			appraise_type:= [imasig] [imasig|modsig]
> +			appraise_type:= [imasig] | [imasig|modsig] | [sigv3]
>  			appraise_flag:= [check_blacklist]
>  			Currently, blacklist check is only for files signed with appended
>  			signature.
> @@ -153,9 +153,27 @@ Description:
>  
>  			appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512
>  
> -		Example of 'measure' rule requiring fs-verity's digests on a
> -		particular filesystem with indication of type of digest in
> -		the measurement list.
> +		Example of a 'measure' rule requiring fs-verity's digests
> +		with indication of type of digest in the measurement list.
>  
>  			measure func=FILE_CHECK digest_type=verity \
> -				fsuuid=... template=ima-ngv2
> +				template=ima-ngv2
> +
> +		Example of 'measure' and 'appraise' rules requiring fs-verity
> +		signatures (version 3) stored in security.ima xattr.
> +
> +		The 'measure' rule specifies the 'ima-sig' template option,
> +		which includes the file signature in the measurement list.
> +
> +			measure func=BPRM_CHECK digest_type=verity \
> +				template=ima-sig
> +
> +		The 'appraise' rule specifies the type and signature version
> +		(sigv3) required.
> +
> +			appraise func=BPRM_CHECK digest_type=verity \
> +				appraise_type=sigv3
> +
> +		All of these policy rules could, for example, be constrained
> +		either based on a filesystem's UUID (fsuuid) or based on LSM
> +		labels.

Is there documentation for what the appraise_type argument means, or does it
just need to be reverse engineered from the above example?

> + - 'sig': the file signature, based on either the file's/fsverity's digest[1],
> +   or the EVM portable signature if the file signature is not found;

This sentence doesn't make sense.  How can it be the file signature if the
"file signature is not found"?

> @@ -303,6 +321,12 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
>  	case EVM_IMA_XATTR_DIGSIG:
>  		set_bit(IMA_DIGSIG, &iint->atomic_flags);
>  
> +		if (iint->flags & (IMA_DIGSIG_REQUIRED | IMA_VERITY_REQUIRED)) {
> +			*cause = "verity-signature-required";
> +			*status = INTEGRITY_FAIL;
> +			break;
> +		}

Shouldn't this check whether *both* of these flags are set?

> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 28aca1f9633b..d3006cc22ab1 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -1311,6 +1311,12 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  	    !(entry->flags & IMA_MODSIG_ALLOWED))
>  		return false;
>  
> +	/* Ensure APPRAISE verity file implies a v3 signature */
> +	if (entry->action == APPRAISE &&
> +	    (entry->flags & IMA_VERITY_REQUIRED) &&
> +	    !(entry->flags & IMA_DIGSIG_REQUIRED))
> +		return false;

This comment doesn't seem to match the code.

> diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
> index d370fca04de4..ecbe61c53d40 100644
> --- a/security/integrity/ima/ima_template_lib.c
> +++ b/security/integrity/ima/ima_template_lib.c
> @@ -495,7 +495,8 @@ int ima_eventsig_init(struct ima_event_data *event_data,
>  {
>  	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
>  
> -	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
> +	if (!xattr_value ||
> +	    !(xattr_value->type & (EVM_IMA_XATTR_DIGSIG | IMA_VERITY_DIGSIG)))
>  		return ima_eventevmsig_init(event_data, field_data);

This is OR-ing together values that aren't bit flags.

- Eric
Mimi Zohar March 17, 2022, 3:46 p.m. UTC | #2
On Wed, 2022-02-23 at 17:24 -0800, Eric Biggers wrote:
> On Fri, Feb 11, 2022 at 04:43:09PM -0500, Mimi Zohar wrote:
> > Instead of calculating a regular file hash and verifying the signature
> > stored in the 'security.ima' xattr against the calculated file hash, get
> > fs-verity's file digest and verify the signature (version 3) stored in
> > 'security.ima' against the digest.
> > 
> > The policy rule 'appraise_type=' option is extended to support 'sigv3',
> > which is initiality limited to fs-verity.
> > 
> > The fs-verity 'appraise' rules are identified by the 'digest-type=verity'
> > option and require the 'appraise_type=sigv3' option.  The following
> > 'appraise' policy rule requires fsverity file digests.  (The rule may be
> > constrained, for example based on a fsuuid or LSM label.)
> > 
> > Basic fs-verity policy rule example:
> >   appraise func=BPRM_CHECK digest_type=verity appraise_type=sigv3
> > 
> > Lastly, for IMA to differentiate between the original IMA signature
> > from an fs-verity signature a new 'xattr_type' named IMA_VERITY_DIGSIG
> > is defined.
> 
> I'm having a hard time understanding this patch.  Can you please describe the
> motivation for doing things, not just the things themselves, and make sure the
> explanation is understandable to someone who isn't an IMA expert?

Ok, will be updated in the next version.

> 
> > diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
> > index ff3c906738cb..508053b8dd0a 100644
> > --- a/Documentation/ABI/testing/ima_policy
> > +++ b/Documentation/ABI/testing/ima_policy
> > @@ -47,7 +47,7 @@ Description:
> >  			fgroup:= decimal value
> >  		  lsm:  are LSM specific
> >  		  option:
> > -			appraise_type:= [imasig] [imasig|modsig]
> > +			appraise_type:= [imasig] | [imasig|modsig] | [sigv3]
> >  			appraise_flag:= [check_blacklist]
> >  			Currently, blacklist check is only for files signed with appended
> >  			signature.
> > @@ -153,9 +153,27 @@ Description:
> >  
> >  			appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512
> >  
> > -		Example of 'measure' rule requiring fs-verity's digests on a
> > -		particular filesystem with indication of type of digest in
> > -		the measurement list.
> > +		Example of a 'measure' rule requiring fs-verity's digests
> > +		with indication of type of digest in the measurement list.
> >  
> >  			measure func=FILE_CHECK digest_type=verity \
> > -				fsuuid=... template=ima-ngv2
> > +				template=ima-ngv2
> > +
> > +		Example of 'measure' and 'appraise' rules requiring fs-verity
> > +		signatures (version 3) stored in security.ima xattr.
> > +
> > +		The 'measure' rule specifies the 'ima-sig' template option,
> > +		which includes the file signature in the measurement list.
> > +
> > +			measure func=BPRM_CHECK digest_type=verity \
> > +				template=ima-sig
> > +
> > +		The 'appraise' rule specifies the type and signature version
> > +		(sigv3) required.
> > +
> > +			appraise func=BPRM_CHECK digest_type=verity \
> > +				appraise_type=sigv3
> > +
> > +		All of these policy rules could, for example, be constrained
> > +		either based on a filesystem's UUID (fsuuid) or based on LSM
> > +		labels.
> 
> Is there documentation for what the appraise_type argument means, or does it
> just need to be reverse engineered from the above example?

The original definition was defined in Backus–Naur form.  Other
information was subsequently included which resulted in making it less
readable.  Perhaps for now, the explanation could be indented:

                        appraise_type:= [imasig] | [imasig|modsig] | [sigv3]
                            where 'imasig' is the original or v2 signature,
                            where 'modsig' is an appended signature,
                            where 'sigv3' is the IMA v3 signature.

> 
> > + - 'sig': the file signature, based on either the file's/fsverity's digest[1],
> > +   or the EVM portable signature if the file signature is not found;
> 
> This sentence doesn't make sense.  How can it be the file signature if the
> "file signature is not found"?

EVM protects file metadata including security xattrs.  In order to make
EVM signatures portable, the i_ino and i_generation, which are
filesystem specific, couldn't be included.  Instead EVM portable
signature requires including 'security.ima', which may be a file hash
or signature.  Requiring both EVM and IMA signatures was considered
unnecessary, maybe even redundant.  When 'security.ima' is a file hash,
the 'sig' field may contain the EVM signature.

I've updated to be:
 - 'sig': the file signature, based on either the file's/fsverity's
digest[1],
   or the EVM portable signature, if 'security.ima' contains a file
hash.

> 
> > @@ -303,6 +321,12 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
> >  	case EVM_IMA_XATTR_DIGSIG:
> >  		set_bit(IMA_DIGSIG, &iint->atomic_flags);
> >  
> > +		if (iint->flags & (IMA_DIGSIG_REQUIRED | IMA_VERITY_REQUIRED)) {
> > +			*cause = "verity-signature-required";
> > +			*status = INTEGRITY_FAIL;
> > +			break;
> > +		}
> 
> Shouldn't this check whether *both* of these flags are set?

Yes, thank you.

> 
> > diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> > index 28aca1f9633b..d3006cc22ab1 100644
> > --- a/security/integrity/ima/ima_policy.c
> > +++ b/security/integrity/ima/ima_policy.c
> > @@ -1311,6 +1311,12 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
> >  	    !(entry->flags & IMA_MODSIG_ALLOWED))
> >  		return false;
> >  
> > +	/* Ensure APPRAISE verity file implies a v3 signature */
> > +	if (entry->action == APPRAISE &&
> > +	    (entry->flags & IMA_VERITY_REQUIRED) &&
> > +	    !(entry->flags & IMA_DIGSIG_REQUIRED))
> > +		return false;
> 
> This comment doesn't seem to match the code.h

Agreed, the comment will be updated in the next version.

> > diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
> > index d370fca04de4..ecbe61c53d40 100644
> > --- a/security/integrity/ima/ima_template_lib.c
> > +++ b/security/integrity/ima/ima_template_lib.c
> > @@ -495,7 +495,8 @@ int ima_eventsig_init(struct ima_event_data *event_data,
> >  {
> >  	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
> >  
> > -	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
> > +	if (!xattr_value ||
> > +	    !(xattr_value->type & (EVM_IMA_XATTR_DIGSIG | IMA_VERITY_DIGSIG)))
> >  		return ima_eventevmsig_init(event_data, field_data);
> 
> This is OR-ing together values that aren't bit flags.

Updated.

thanks,

Mimi
diff mbox series

Patch

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index ff3c906738cb..508053b8dd0a 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -47,7 +47,7 @@  Description:
 			fgroup:= decimal value
 		  lsm:  are LSM specific
 		  option:
-			appraise_type:= [imasig] [imasig|modsig]
+			appraise_type:= [imasig] | [imasig|modsig] | [sigv3]
 			appraise_flag:= [check_blacklist]
 			Currently, blacklist check is only for files signed with appended
 			signature.
@@ -153,9 +153,27 @@  Description:
 
 			appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512
 
-		Example of 'measure' rule requiring fs-verity's digests on a
-		particular filesystem with indication of type of digest in
-		the measurement list.
+		Example of a 'measure' rule requiring fs-verity's digests
+		with indication of type of digest in the measurement list.
 
 			measure func=FILE_CHECK digest_type=verity \
-				fsuuid=... template=ima-ngv2
+				template=ima-ngv2
+
+		Example of 'measure' and 'appraise' rules requiring fs-verity
+		signatures (version 3) stored in security.ima xattr.
+
+		The 'measure' rule specifies the 'ima-sig' template option,
+		which includes the file signature in the measurement list.
+
+			measure func=BPRM_CHECK digest_type=verity \
+				template=ima-sig
+
+		The 'appraise' rule specifies the type and signature version
+		(sigv3) required.
+
+			appraise func=BPRM_CHECK digest_type=verity \
+				appraise_type=sigv3
+
+		All of these policy rules could, for example, be constrained
+		either based on a filesystem's UUID (fsuuid) or based on LSM
+		labels.
diff --git a/Documentation/security/IMA-templates.rst b/Documentation/security/IMA-templates.rst
index 1e3fe986764e..fe9bc2595fa2 100644
--- a/Documentation/security/IMA-templates.rst
+++ b/Documentation/security/IMA-templates.rst
@@ -72,8 +72,8 @@  descriptors by adding their identifier to the format string
  - 'd-type': differentiate between fs-verity's Merkle tree based file hash
    from a regular IMA file hash measurement.
  - 'n-ng': the name of the event, without size limitations;
- - 'sig': the file signature, or the EVM portable signature if the file
-   signature is not found;
+ - 'sig': the file signature, based on either the file's/fsverity's digest[1],
+   or the EVM portable signature if the file signature is not found;
  - 'modsig' the appended file signature;
  - 'buf': the buffer data that was used to generate the hash without size limitations;
  - 'evmsig': the EVM portable signature;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index c2b429c141a7..71e27dba01ab 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -13,7 +13,9 @@ 
 #include <linux/magic.h>
 #include <linux/ima.h>
 #include <linux/evm.h>
+#include <linux/fsverity.h>
 #include <keys/system_keyring.h>
+#include <uapi/linux/fsverity.h>
 
 #include "ima.h"
 
@@ -183,13 +185,18 @@  enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
 		return ima_hash_algo;
 
 	switch (xattr_value->type) {
+	case IMA_VERITY_DIGSIG:
+		sig = (typeof(sig))xattr_value;
+		if (sig->version != 3 || xattr_len <= sizeof(*sig) ||
+		    sig->hash_algo >= HASH_ALGO__LAST)
+			return ima_hash_algo;
+		return sig->hash_algo;
 	case EVM_IMA_XATTR_DIGSIG:
 		sig = (typeof(sig))xattr_value;
 		if (sig->version != 2 || xattr_len <= sizeof(*sig)
 		    || sig->hash_algo >= HASH_ALGO__LAST)
 			return ima_hash_algo;
 		return sig->hash_algo;
-		break;
 	case IMA_XATTR_DIGEST_NG:
 		/* first byte contains algorithm id */
 		ret = xattr_value->data[0];
@@ -235,15 +242,22 @@  int ima_read_xattr(struct dentry *dentry,
  * IMA signature version 3 disambiguates the data that is signed by
  * indirectly signing the hash of the ima_file_id structure data.
  *
+ * Signing the ima_file_id struct is currently only supported for
+ * IMA_VERITY_DIGSIG type xattrs.
+ *
  * Return 0 on success, error code otherwise.
  */
 static int calc_file_id_hash(enum evm_ima_xattr_type type,
 			     enum hash_algo algo, const u8 *digest,
 			     struct ima_digest_data *hash)
 {
-	struct ima_file_id file_id = {.hash_algorithm = algo};
+	struct ima_file_id file_id = {
+		.hash_type = IMA_VERITY_DIGSIG, .hash_algorithm = algo};
 	uint unused = HASH_MAX_DIGESTSIZE - hash_digest_size[algo];
 
+	if (type != IMA_VERITY_DIGSIG)
+		return -EINVAL;
+
 	memcpy(file_id.hash, digest, hash_digest_size[algo]);
 
 	hash->algo = algo;
@@ -263,6 +277,7 @@  static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
 			struct evm_ima_xattr_data *xattr_value, int xattr_len,
 			enum integrity_status *status, const char **cause)
 {
+	struct ima_max_digest_data hash;
 	struct signature_v2_hdr *sig;
 	int rc = -EINVAL, hash_start = 0;
 
@@ -274,7 +289,10 @@  static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
 	case IMA_XATTR_DIGEST:
 		if (*status != INTEGRITY_PASS_IMMUTABLE) {
 			if (iint->flags & IMA_DIGSIG_REQUIRED) {
-				*cause = "IMA-signature-required";
+				if (iint->flags & IMA_VERITY_REQUIRED)
+					*cause = "verity-signature-required";
+				else
+					*cause = "IMA-signature-required";
 				*status = INTEGRITY_FAIL;
 				break;
 			}
@@ -303,6 +321,12 @@  static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
 	case EVM_IMA_XATTR_DIGSIG:
 		set_bit(IMA_DIGSIG, &iint->atomic_flags);
 
+		if (iint->flags & (IMA_DIGSIG_REQUIRED | IMA_VERITY_REQUIRED)) {
+			*cause = "verity-signature-required";
+			*status = INTEGRITY_FAIL;
+			break;
+		}
+
 		sig = (typeof(sig))xattr_value;
 		if (sig->version != 2) {
 			*cause = "invalid-signature-version";
@@ -331,6 +355,44 @@  static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
 		} else {
 			*status = INTEGRITY_PASS;
 		}
+		break;
+	case IMA_VERITY_DIGSIG:
+		set_bit(IMA_DIGSIG, &iint->atomic_flags);
+
+		if (iint->flags & IMA_DIGSIG_REQUIRED) {
+			if (!(iint->flags & IMA_VERITY_REQUIRED)) {
+				*cause = "IMA-signature-required";
+				*status = INTEGRITY_FAIL;
+				break;
+			}
+		}
+
+		sig = (typeof(sig))xattr_value;
+		if (sig->version != 3) {
+			*cause = "invalid-signature-version";
+			*status = INTEGRITY_FAIL;
+			break;
+		}
+
+		rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo,
+				       iint->ima_hash->digest, &hash.hdr);
+		if (rc) {
+			*cause = "sigv3-hashing-error";
+			*status = INTEGRITY_FAIL;
+			break;
+		}
+
+		rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
+					     (const char *)xattr_value,
+					     xattr_len, hash.digest,
+					     hash.hdr.length);
+		if (rc) {
+			*cause = "invalid-verity-signature";
+			*status = INTEGRITY_FAIL;
+		} else {
+			*status = INTEGRITY_PASS;
+		}
+
 		break;
 	default:
 		*status = INTEGRITY_UNKNOWN;
@@ -431,8 +493,15 @@  int ima_appraise_measurement(enum ima_hooks func,
 		if (rc && rc != -ENODATA)
 			goto out;
 
-		cause = iint->flags & IMA_DIGSIG_REQUIRED ?
-				"IMA-signature-required" : "missing-hash";
+		if (iint->flags & IMA_DIGSIG_REQUIRED) {
+			if (iint->flags & IMA_VERITY_REQUIRED)
+				cause = "verity-signature-required";
+			else
+				cause = "IMA-signature-required";
+		} else {
+			cause = "missing-hash";
+		}
+
 		status = INTEGRITY_NOLABEL;
 		if (file->f_mode & FMODE_CREATED)
 			iint->flags |= IMA_NEW_FILE;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 28aca1f9633b..d3006cc22ab1 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -1311,6 +1311,12 @@  static bool ima_validate_rule(struct ima_rule_entry *entry)
 	    !(entry->flags & IMA_MODSIG_ALLOWED))
 		return false;
 
+	/* Ensure APPRAISE verity file implies a v3 signature */
+	if (entry->action == APPRAISE &&
+	    (entry->flags & IMA_VERITY_REQUIRED) &&
+	    !(entry->flags & IMA_DIGSIG_REQUIRED))
+		return false;
+
 	return true;
 }
 
@@ -1735,14 +1741,24 @@  static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 			break;
 		case Opt_appraise_type:
 			ima_log_string(ab, "appraise_type", args[0].from);
-			if ((strcmp(args[0].from, "imasig")) == 0)
+			if ((strcmp(args[0].from, "imasig")) == 0) {
 				entry->flags |= IMA_DIGSIG_REQUIRED;
-			else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) &&
-				 strcmp(args[0].from, "imasig|modsig") == 0)
+			} else if (strcmp(args[0].from, "sigv3") == 0) {
+				/*
+				 * Only fsverity supports sigv3 for now.
+				 * No need to define a new flag.
+				 */
+				if (entry->flags & IMA_VERITY_REQUIRED)
+					entry->flags |= IMA_DIGSIG_REQUIRED;
+				else
+					result = -EINVAL;
+			} else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) &&
+				 strcmp(args[0].from, "imasig|modsig") == 0) {
 				entry->flags |= IMA_DIGSIG_REQUIRED |
 						IMA_MODSIG_ALLOWED;
-			else
+			} else {
 				result = -EINVAL;
+			}
 			break;
 		case Opt_appraise_flag:
 			ima_log_string(ab, "appraise_flag", args[0].from);
@@ -2186,6 +2202,8 @@  int ima_policy_show(struct seq_file *m, void *v)
 	if (entry->flags & IMA_DIGSIG_REQUIRED) {
 		if (entry->flags & IMA_MODSIG_ALLOWED)
 			seq_puts(m, "appraise_type=imasig|modsig ");
+		else if (entry->flags & IMA_VERITY_REQUIRED)
+			seq_puts(m, "appraise_type=sigv3 ");
 		else
 			seq_puts(m, "appraise_type=imasig ");
 	}
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index d370fca04de4..ecbe61c53d40 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -495,7 +495,8 @@  int ima_eventsig_init(struct ima_event_data *event_data,
 {
 	struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
 
-	if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
+	if (!xattr_value ||
+	    !(xattr_value->type & (EVM_IMA_XATTR_DIGSIG | IMA_VERITY_DIGSIG)))
 		return ima_eventevmsig_init(event_data, field_data);
 
 	return ima_write_template_field_data(xattr_value, event_data->xattr_len,
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index bd38bd451b19..b3267384c028 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -80,6 +80,7 @@  enum evm_ima_xattr_type {
 	EVM_IMA_XATTR_DIGSIG,
 	IMA_XATTR_DIGEST_NG,
 	EVM_XATTR_PORTABLE_DIGSIG,
+	IMA_VERITY_DIGSIG,
 	IMA_XATTR_LAST
 };
 
@@ -140,7 +141,9 @@  struct signature_v2_hdr {
 
 /*
  * IMA signature version 3 disambiguates the data that is signed, by
- * indirectly signing the hash of the ima_file_id structure data.
+ * indirectly signing the hash of the ima_file_id structure data,
+ * containing either the fsverity_descriptor struct digest or, in the
+ * future, the regular IMA file hash.
  *
  * (The hash of the ima_file_id structure is only of the portion used.)
  */