On 2026-08-11 22:01, Jérémy Jean wrote:
> audit_del_rule() is used for both netlink deletion templates and internal
> fsnotify autoremove.  The former passes a parsed template which owns a
> temporary tree reference; the latter passes the installed entry itself.
> 
> The unconditional audit_put_tree() at the end of audit_del_rule() assumes
> the template case.  For mixed AUDIT_DIR plus AUDIT_EXE rules, an fsnotify
> autoremove event therefore drops the installed rule's live tree reference.
> Repeating this across rules sharing the same tree can free the tree while
> another rule still references it, and a later autoremove dereferences the
> freed pathname while comparing rules.
> 
> Move the temporary-tree put to audit_rule_change(), the caller that owns
> deletion templates.  Keep it in the AUDIT_DEL_RULE cleanup so both
> successful deletion and -ENOENT still release the parser-owned tree.
> 
> Fixes: 34d99af52ad4 ("audit: implement audit by executable")
> Assisted-by: Codex:gpt-5
> Signed-off-by: Jérémy Jean <[email protected]>

Thanks for finding this!

Reviewed-by: Richard Guy Briggs <[email protected]>

> ---
>  kernel/auditfilter.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index 7f791afe5791..666c2091b9e4 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -1023,7 +1023,6 @@ static inline int audit_add_rule(struct audit_entry 
> *entry)
>  int audit_del_rule(struct audit_entry *entry)
>  {
>       struct audit_entry  *e;
> -     struct audit_tree *tree = entry->rule.tree;
>       struct list_head *list;
>       int ret = 0;
>  #ifdef CONFIG_AUDITSYSCALL
> @@ -1071,9 +1070,6 @@ int audit_del_rule(struct audit_entry *entry)
>  out:
>       mutex_unlock(&audit_filter_mutex);
>  
> -     if (tree)
> -             audit_put_tree(tree);   /* that's the temporary one */
> -
>       return ret;
>  }
>  
> @@ -1158,6 +1154,8 @@ int audit_rule_change(int type, int seq, void *data, 
> size_t datasz)
>       }
>  
>       if (err || type == AUDIT_DEL_RULE) {
> +             if (type == AUDIT_DEL_RULE && entry->rule.tree)
> +                     audit_put_tree(entry->rule.tree); /* that's the 
> template one */
>               if (entry->rule.exe)
>                       audit_remove_mark(entry->rule.exe);
>               audit_free_rule(entry);
> -- 
> 2.47.3
> 
> 

- RGB

--
Richard Guy Briggs <[email protected]>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
Upstream IRC: SunRaycer
Voice: +1.613.860 2354 SMS: +1.613.518.6570


Reply via email to