Re: [PATCH] d_path: fall back to init_fs when called after exit_fs()

From: Al Viro

Date: Mon Oct 19 2026 - 11:48:02 EST


On Mon, Oct 19, 2026 at 08:24:19PM +0700, Nguyen Ngoc Thang wrote:
> d_path() dereferences current->fs unconditionally. do_exit() runs
> exit_fs() before exit_task_work(), so a deferred __fput() sees
> current->fs == NULL. If that fput ends up in d_path(), it crashes:
>
> ima_file_free() -> ima_update_xattr() -> ima_calc_file_hash()
> -> dentry_open() -> smack_file_open() -> smack_log()
> -> common_lsm_audit() -> audit_log_d_path() -> d_path()
> -> read_seqbegin(&current->fs->seq)
>
> Any LSM or audit path that formats a path on open can hit this. Fall
> back to init_fs, whose root is always valid, when the task has no fs.
>
> Reported-by: syzbot+975ace299d6ba2eb1cea@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=975ace299d6ba2eb1cea
> Fixes: 4a9d4b024a31 ("switch fput to task_work_add")
> Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@xxxxxxxxx>
> ---
> Reproduced in QEMU (x86_64, KASAN, Smack+IMA+audit) with the syzbot C
> reproducer: without the patch the first exiting child hits a null-ptr-deref
> in d_path(); with it the reproducer runs to completion with no KASAN/Oops.
>
> Alternatives considered: fixing only the IMA->Smack audit path (too narrow,
> any open-time LSM/audit hook can hit this), or reordering exit_fs() and
> exit_task_work() (too invasive). Happy to rework if you prefer another approach.

How about "don't use d_path() in places where current root is not well-defined"?

The reason why it tries to access current->fs is that it tries to produce
a pathname in caller's namespace, relative to whatever the caller happens to
be chrooted into.

Using that on final fput is insane - it might happen in context of completely
unexpected process. So instead of papering over a symptom in d_path() itself,
the right approach would be to ask what do we expect from the data produced
by that call; "garbage string" is less obvious than an oops, but it's still
misleading.