Re: [PATCH RFC v11 16/19] ipe: enable support for fs-verity as a trust provider

From: Paul Moore
Date: Mon Oct 23 2023 - 23:54:05 EST


On Oct 4, 2023 Fan Wu <wufan@xxxxxxxxxxxxxxxxxxx> wrote:
>
> Enable IPE policy authors to indicate trust for a singular fsverity
> file, identified by the digest information, through "fsverity_digest"
> and all files using fsverity's builtin signatures via
> "fsverity_signature".
>
> This enables file-level integrity claims to be expressed in IPE,
> allowing individual files to be authorized, giving some flexibility
> for policy authors. Such file-level claims are important to be expressed
> for enforcing the integrity of packages, as well as address some of the
> scalability issues in a sole dm-verity based solution (# of loop back
> devices, etc).
>
> This solution cannot be done in userspace as the minimum threat that
> IPE should mitigate is an attacker downloads malicious payload with
> all required dependencies. These dependencies can lack the userspace
> check, bypassing the protection entirely. A similar attack succeeds if
> the userspace component is replaced with a version that does not
> perform the check. As a result, this can only be done in the common
> entry point - the kernel.
>
> Signed-off-by: Deven Bowers <deven.desai@xxxxxxxxxxxxxxxxxxx>
> Signed-off-by: Fan Wu <wufan@xxxxxxxxxxxxxxxxxxx>
> ---
> v1-v6:
> + Not present
>
> v7:
> Introduced
>
> v8:
> * Undo squash of 08/12, 10/12 - separating drivers/md/ from security/
> * Use common-audit function for fsverity_signature.
> + Change fsverity implementation to use fsverity_get_digest
> + prevent unnecessary copy of fs-verity signature data, instead
> just check for presence of signature data.
> + Remove free_inode_security hook, as the digest is now acquired
> at runtime instead of via LSM blob.
>
> v9:
> + Adapt to the new parser
>
> v10:
> + Update the fsverity get digest call
>
> v11:
> + No changes
> ---
> security/ipe/Kconfig | 13 +++++
> security/ipe/audit.c | 23 ++++++++
> security/ipe/eval.c | 110 +++++++++++++++++++++++++++++++++++
> security/ipe/eval.h | 10 ++++
> security/ipe/hooks.c | 30 ++++++++++
> security/ipe/hooks.h | 7 +++
> security/ipe/ipe.c | 13 +++++
> security/ipe/ipe.h | 3 +
> security/ipe/policy.h | 3 +
> security/ipe/policy_parser.c | 8 +++
> 10 files changed, 220 insertions(+)

...

> diff --git a/security/ipe/audit.c b/security/ipe/audit.c
> index b5c58655ac74..e3a8552a76a4 100644
> --- a/security/ipe/audit.c
> +++ b/security/ipe/audit.c
> @@ -79,6 +100,8 @@ static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r)
> audit_log_format(ab, "%s", audit_prop_names[ptr->type]);
> if (ptr->type == IPE_PROP_DMV_ROOTHASH)
> audit_dmv_roothash(ab, ptr->value);
> + if (ptr->type == IPE_PROP_FSV_DIGEST)
> + audit_fsv_digest(ab, ptr->value);

My comments on audit_dmv_roothash() also apply here.

> audit_log_format(ab, " ");
> }
> diff --git a/security/ipe/eval.c b/security/ipe/eval.c
> index 82ad48d7aa3d..f0194b0ca2ff 100644
> --- a/security/ipe/eval.c
> +++ b/security/ipe/eval.c
> @@ -172,6 +191,91 @@ static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx,
> }
> #endif /* CONFIG_IPE_PROP_DM_VERITY */
>
> +#ifdef CONFIG_IPE_PROP_FS_VERITY
> +/**
> + * evaluate_fsv_digest - Analyze @ctx against a fsv digest property.
> + * @ctx: Supplies a pointer to the context being evaluated.
> + * @p: Supplies a pointer to the property being evaluated.
> + *
> + * Return:
> + * * true - The current @ctx match the @p
> + * * false - The current @ctx doesn't match the @p
> + */
> +static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
> + struct ipe_prop *p)
> +{
> + enum hash_algo alg;
> + u8 digest[FS_VERITY_MAX_DIGEST_SIZE];
> +
> + if (!ctx->ino)
> + return false;
> + if (!fsverity_get_digest((struct inode *)ctx->ino,
> + digest,
> + NULL,
> + &alg))
> + return false;
> +
> + return ipe_digest_eval(p->value,
> + digest,
> + hash_digest_size[alg],
> + hash_algo_name[alg]);
> +}
> +
> +/**
> + * evaluate_fsv_sig_false - Analyze @ctx against a fsv sig false property.
> + * @ctx: Supplies a pointer to the context being evaluated.
> + * @p: Supplies a pointer to the property being evaluated.
> + *
> + * Return:
> + * * true - The current @ctx match the @p
> + * * false - The current @ctx doesn't match the @p
> + */
> +static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx,
> + struct ipe_prop *p)
> +{
> + return !ctx->ino ||
> + !IS_VERITY(ctx->ino) ||
> + !ctx->ipe_inode ||
> + !ctx->ipe_inode->fs_verity_signed;
> +}
> +
> +/**
> + * evaluate_fsv_sig_true - Analyze @ctx against a fsv sig true property.
> + * @ctx: Supplies a pointer to the context being evaluated.
> + * @p: Supplies a pointer to the property being evaluated.
> + *
> + * Return:
> + * * true - The current @ctx match the @p
> + * * false - The current @ctx doesn't match the @p
> + */
> +static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx,
> + struct ipe_prop *p)
> +{
> + return ctx->ino &&
> + IS_VERITY(ctx->ino) &&
> + ctx->ipe_inode &&
> + ctx->ipe_inode->fs_verity_signed;
> +}

See my previous comments about the false/true functions.

> +#else

--
paul-moore.com