Re: [PATCH] ovl: fix NULL pointer dereference in ovl_i_path_real()

Amir Goldstein <[email protected]>
Newsgroups org.kernel.vger.linux-unionfs,org.kernel.vger.linux-kernel
Message-ID <CAOQ4uxjKzqH6g41_Gtx_WWE8y69cUrzg8VVsVhg-4PgkOLxLoA@mail.gmail.com>
On Fri, Aug 7, 2026 at 9:05 AM Varadarajan Narayanan
<[email protected]> 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 <[email protected]>
> ---
>  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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.