Re: [PATCH] ovl: fix NULL pointer dereference in ovl_i_path_real()
From: Amir Goldstein
Date: Mon Aug 10 2026 - 05:20:34 EST
On Fri, Aug 7, 2026 at 9:05 AM Varadarajan Narayanan
<varadarajan.narayanan@xxxxxxxxxxxxxxxx> wrote:
>
> KASAN reported a NULL pointer dereference in ovl_permission() when it
> called mnt_idmap(realpath.mnt):
>
> BUG: KASAN: null-ptr-deref in ovl_permission+0x150/0x190
> Read of size 8 at addr 0000000000000018
>
> ovl_i_path_real() can return a path with a valid dentry but a NULL mnt.
> This happens when the inode has an upper dentry, but ovl_upper_mnt()
> returns NULL, for example on an overlay without an upper layer. The caller
> then dereferences realpath.mnt and crashes.
An overlayfs without an upper layer should not have an inode with an
upper dentry.
>
> Also avoid dereferencing lowerpath when it is NULL.
>
> Fix this by checking lowerpath before using it, and by clearing
> path->dentry when no upper mount is available. This makes ovl_i_path_real()
> return NULL and lets callers use their existing error handling path.
>
> Call trace:
> ...
> __kasan_check_read+0x1c/0x24
> ovl_permission+0x150/0x190
> inode_permission+0x7c/0x204
> may_open+0x84/0x14c
> path_openat+0xdf0/0xf60
> do_filp_open+0xbc/0x148
> do_sys_openat2+0x268/0x2bc
> do_sys_open+0xd4/0x108
>
> Signed-off-by: Varadarajan Narayanan <varadarajan.narayanan@xxxxxxxxxxxxxxxx>
> ---
> fs/overlayfs/util.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
> index b41f4788e4f0..ec423e16cbbd 100644
> --- a/fs/overlayfs/util.c
> +++ b/fs/overlayfs/util.c
> @@ -380,10 +380,16 @@ struct inode *ovl_i_path_real(struct inode *inode, struct path *path)
>
> path->dentry = ovl_i_dentry_upper(inode);
> if (!path->dentry) {
> - path->dentry = lowerpath->dentry;
> - path->mnt = lowerpath->layer->mnt;
> + if (lowerpath) {
> + path->dentry = lowerpath->dentry;
> + path->mnt = lowerpath->layer->mnt;
> + } else {
> + path->mnt = NULL;
> + }
> } else {
> path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb));
> + if (unlikely(!path->mnt))
> + path->dentry = NULL;
> }
>
> return path->dentry ? d_inode_rcu(path->dentry) : NULL;
>
This patch is wrong because it defends against conditions that should
not be possible.
If this is reproducible, then there might be a bug somewhere else that
needs fixing,
use after free or what not.
Thanks,
Amir.