All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
Cc: linux-security-module@vger.kernel.org
Subject: Re: [PATCH v4 1/2] ima: discard modsig when detached data cannot be supplied
Date: Sat, 24 Oct 2026 09:58:42 +0000	[thread overview]
Message-ID: <sashiko-outbox-183637@kernel.org> (raw)
In-Reply-To: <20261024093918.2929374-2-Jeremy.Jean@oss.cyber.gouv.fr>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] ima: ignored pkcs7_get_digest() failure in ima_collect_modsig()
- [Medium] ima: unintended measurement in process_measurement() when modsig is discarded
--

commit 6ba08dabf06dd0a8dc8646bcd331980059e5a114
Author: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>

ima: discard modsig when detached data cannot be supplied

This commit updates ima_collect_modsig() to return a boolean indicating
whether detached file data was supplied to the PKCS#7 message, and
discards the modsig in ima_collect_measurement() if supplying the
detached data fails.

> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index 45701f04ba62f..7859c9d1a27f5 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -235,6 +235,8 @@ static bool ima_get_verity_digest(struct ima_iint_cache *iint,
>   *
>   * Calculate the file hash, if it doesn't already exist,
>   * storing the measurement and i_version in the iint.
> + * If modsig is provided, discard it when detached data cannot be supplied
> + * so ordinary measurement and xattr appraisal can proceed.
>   *
>   * Must be called with iint->mutex held.
>   *
> @@ -242,7 +244,7 @@ static bool ima_get_verity_digest(struct ima_iint_cache *iint,
>   */
>  int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
>  			    void *buf, loff_t size, enum hash_algo algo,
> -			    struct modsig *modsig)
> +			    struct modsig **modsig)
>  {
>  	const char *audit_cause = "failed";
>  	struct inode *inode = file_inode(file);
> @@ -262,8 +264,10 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
>  	 * the file digest without collecting the modsig in a previous
>  	 * measurement rule.
>  	 */
> -	if (modsig)
> -		ima_collect_modsig(modsig, buf, size);
> +	if (modsig && *modsig && !ima_collect_modsig(*modsig, buf, size)) {
> +		ima_free_modsig(*modsig);
> +		*modsig = NULL;
> +	}
>  
>  	if (iint->flags & IMA_COLLECTED)
>  		goto out;
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index fed80da3ee096..336e17ec4f7a3 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -422,7 +422,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
>  
>  	hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
>  
> -	rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig);
> +	rc = ima_collect_measurement(iint, file, buf, size, hash_algo, &modsig);

[Severity: Medium]
Can discarding modsig in ima_collect_measurement() leave IMA_MEASURE set
in action when the measurement was only requested to record the modsig?

Earlier in process_measurement(), if IMA_MODSIG_ALLOWED is set and
ima_read_modsig() succeeds on an already-measured file, IMA_MEASURE is
added to action:

	if (iint->flags & IMA_MODSIG_ALLOWED) {
		rc = ima_read_modsig(func, buf, size, &modsig);

		if (!rc && ima_template_has_modsig(template_desc) &&
		    iint->flags & IMA_MEASURED)
			action |= IMA_MEASURE;
	}

When ima_collect_measurement() subsequently discards modsig and sets it
to NULL because pkcs7_supply_detached_data() fails, action still has
IMA_MEASURE set.

If the earlier measurement that set IMA_MEASURED used a non-default PCR
and the current hook only matched an appraise rule (leaving pcr at
CONFIG_IMA_MEASURE_PCR_IDX), ima_store_measurement() will see modsig ==
NULL, find that the default PCR bit is not set in iint->measured_pcrs:

	if (iint->measured_pcrs & (0x1 << pcr) && !modsig)
		return;

and record an extra measurement with no modsig into the default PCR.
Should IMA_MEASURE only be added to action after modsig collection has
succeeded?

[ ... ]

> diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c
> index 632c746fd81e4..e640a9a53508e 100644
> --- a/security/integrity/ima/ima_modsig.c
> +++ b/security/integrity/ima/ima_modsig.c
> @@ -96,8 +96,12 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
>   * Since the modsig is part of the file contents, the hash used in its signature
>   * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code
>   * calculates a separate one for signature verification.
> + *
> + * Digest export is best-effort; not all signatures expose a single digest.
> + *
> + * Return: true if the file data was supplied, false otherwise.
>   */
> -void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size)
> +bool ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size)
>  {
>  	int rc;
>  
> @@ -109,11 +113,13 @@ void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size)
>  		sizeof(struct module_signature);
>  	rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size);
>  	if (rc)
> -		return;
> +		return false;
>  
>  	/* Ask the PKCS7 code to calculate the file hash. */
>  	rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest,
>  			      &modsig->digest_size, &modsig->hash_algo);
> +
> +	return true;
>  }
>  
>  int ima_modsig_verify(struct key *keyring, const struct modsig *modsig)
> diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
> index 9bd80ca1159a2..585cd59f00a2e 100644
> --- a/security/integrity/ima/ima_template_lib.c
> +++ b/security/integrity/ima/ima_template_lib.c
> @@ -478,8 +478,8 @@ int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
>  		if (rc)
>  			return rc;
>  		else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0)
> -			/* There was some error collecting the digest. */
> -			return -EINVAL;
> +			/* Keep the ordinary measurement without an exported digest. */
> +			return 0;
>  	}

[Severity: High]
What happens in ima_check_blacklist() and ima_store_measurement() when
pkcs7_get_digest() fails in ima_collect_modsig() (note that the return
value of pkcs7_get_digest() also remains unchecked in the follow-up commit
"ima: audit failure to supply detached data for modsig")?

When pkcs7_get_digest() fails (for example, returning -EBADMSG when
sinfo->next != NULL, or -EINVAL when !sinfo->sig->m_free for algorithms
such as ML-DSA) or leaves modsig->hash_algo as HASH_ALGO__LAST,
ima_collect_modsig() still returns true. That leaves modsig non-NULL in
process_measurement() with modsig->digest == NULL, modsig->digest_size ==
0, and modsig->hash_algo == HASH_ALGO__LAST.

In security/integrity/ima/ima_appraise.c:ima_check_blacklist(), a
non-NULL modsig takes the first branch and skips checking iint->ima_hash:

	if (iint->flags & IMA_MODSIG_ALLOWED && modsig) {
		ima_get_modsig_digest(modsig, &hash_algo, &digest, &digestsize);

		rc = is_binary_blacklisted(digest, digestsize);
	} else if (iint->flags & IMA_DIGSIG_REQUIRED && iint->ima_hash)
		rc = is_binary_blacklisted(iint->ima_hash->digest, iint->ima_hash->length);

Because digest is NULL and digestsize is 0, is_binary_blacklisted(NULL, 0)
returns 0. Since pkcs7_get_digest() rejects messages with multiple
SignerInfos (sinfo->next != NULL) while ima_modsig_verify() ->
verify_pkcs7_message_sig() succeeds as long as at least one SignerInfo is
valid and trusted (and similarly for ML-DSA signatures where
!sinfo->sig->m_free), wouldn't a blacklisted binary bypass
ima_check_blacklist()?

In addition, because ima_eventdigest_modsig_init() now returns 0 instead
of -EINVAL when hash_algo == HASH_ALGO__LAST || cur_digestsize == 0 while
event_data->modsig is still non-NULL:

1. For templates like ima-modsig (d-ng|n-ng|sig|d-modsig|modsig),
   ima_eventdigest_modsig_init() leaves the d-modsig field empty while
   ima_eventmodsig_init() still populates the modsig field with the raw
   PKCS#7 signature, breaking the requirement in check_template_modsig()
   that modsig be paired with d-modsig.

2. If the file was already measured (iint->flags & IMA_MEASURED),
   process_measurement() and ima_store_measurement() will record a second
   measurement entry and extend the PCR again even though no modsig digest
   could be exported.

Should ima_collect_modsig() fail and discard the modsig when
pkcs7_get_digest() fails or leaves modsig->hash_algo == HASH_ALGO__LAST?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261024093918.2929374-1-Jeremy.Jean@oss.cyber.gouv.fr?part=1

  reply	other threads:[~2026-10-24  9:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-24  9:39 [PATCH v4 0/2] ima: reject modsig when detached data cannot be supplied Jérémy Jean
2026-10-24  9:39 ` [PATCH v4 1/2] ima: discard " Jérémy Jean
2026-10-24  9:58   ` sashiko-bot [this message]
2026-10-24 13:47   ` Jérémy Jean
2026-10-24  9:39 ` [PATCH v4 2/2] ima: audit failure to supply detached data for modsig Jérémy Jean
2026-10-24  9:55   ` sashiko-bot

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=sashiko-outbox-183637@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

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

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