Re: [PATCH 02/12] ima: Create a function to free a rule entry

From: Mimi Zohar
Date: Thu Jun 25 2020 - 15:33:53 EST


On Mon, 2020-06-22 at 19:32 -0500, Tyler Hicks wrote:
> There are several possible pieces of allocated memory in a rule entry.
> Create a function that can free all allocated memory for a given rule
> entry.
>
> This patch introduces no functional changes but sets the groundwork for
> some memory leak fixes.
>
> Signed-off-by: Tyler Hicks <tyhicks@xxxxxxxxxxxxxxxxxxx>

Having a function to release all memory associated with a policy rule
in general is a good idea. ÂHowever, in the case of the shallow copy,
we're not removing any IMA rules, just updating the LSM info.

There is an opportunity to transition from the builtin policy rules to
a custom IMA policy. ÂAfterwards IMA policy rules may only be
appended.

An IMA custom policy based on LSM info may be loaded prior to the LSM
policy. ÂThese LSM based rules are inactive until the corresponding
LSM rule is loaded. ÂIn some environments, LSM policies are loaded and
removed frequently. ÂThe IMA rules themselves are not removed, just
the LSM info is updated to reflect the current LSM info.

> ---
> security/integrity/ima/ima_policy.c | 33 +++++++++++++++++++++++++++--
> 1 file changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 236a731492d1..1320333201c6 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -261,6 +261,27 @@ static void ima_lsm_free_rule(struct ima_rule_entry *entry)
> security_filter_rule_free(entry->lsm[i].rule);
> kfree(entry->lsm[i].args_p);
> }
> +}
> +
> +static void ima_free_rule(struct ima_rule_entry *entry)
> +{
> + if (!entry)
> + return;
> +
> + /*
> + * entry->template->fields may be allocated in ima_parse_rule() but that
> + * reference is owned by the corresponding ima_template_desc element in
> + * the defined_templates list and cannot be freed here
> + */
> +
> + /*
> + * When freeing newly added ima_rule_entry members, consider if you
> + * need to disown any references after the shallow copy in
> + * ima_lsm_copy_rule()
> + */
> + kfree(entry->fsname);
> + kfree(entry->keyrings);
> + ima_lsm_free_rule(entry);
> kfree(entry);
> }
>
> @@ -298,10 +319,18 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
> pr_warn("rule for LSM \'%s\' is undefined\n",
> (char *)entry->lsm[i].args_p);
> }
> +
> + /* Disown all references that were shallow copied */
> + entry->fsname = NULL;
> + entry->keyrings = NULL;
> + entry->template = NULL;
> return nentry;
>
> out_err:
> - ima_lsm_free_rule(nentry);
> + nentry->fsname = NULL;
> + nentry->keyrings = NULL;
> + nentry->template = NULL;
> + ima_free_rule(nentry);

> return NULL;
> }
>
> @@ -315,7 +344,7 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry)
>
> list_replace_rcu(&entry->list, &nentry->list);
> synchronize_rcu();
> - ima_lsm_free_rule(entry);
> + ima_free_rule(entry);

This should only update the LSM info, nothing else.

>
> return 0;
> }