Re: [PATCH v2 1/3] ovl: disable nfs_export for same-sb lower layers with different idmaps
From: Amir Goldstein
Date: Mon Sep 21 2026 - 04:14:15 EST
On Sun, Sep 20, 2026 at 10:33 PM Jérémy Jean
<Jeremy.Jean@xxxxxxxxxxxxxxxxx> wrote:
>
> Overlay file handles identify a backing filesystem, but not the lower
> mount used to decode it. If lower layers share a superblock and use
> different idmaps, a file handle can decode through the wrong layer and
> initialize the overlay inode with the wrong owner.
>
> Track the first lower idmap seen for each ovl_sb and disable nfs_export
> when another lower layer on the same backing superblock uses a different
> idmap. Keep index enabled: copy up starts from the overlay dentry selected
> by lookup and does not need to decode a lower file handle through another
> layer.
>
> Fixes: bc70682a497c ("ovl: support idmapped layers")
> Assisted-by: Codex:gpt-5
> Signed-off-by: Jérémy Jean <Jeremy.Jean@xxxxxxxxxxxxxxxxx>
> ---
> fs/overlayfs/ovl_entry.h | 2 ++
> fs/overlayfs/super.c | 28 +++++++++++++++++++++++++++-
> 2 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index 80cad4ea96a3..2a6e12a0d4dd 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -24,6 +24,8 @@ struct ovl_config {
> struct ovl_sb {
> struct super_block *sb;
> dev_t pseudo_dev;
> + /* Idmap of the first lower layer on this fs */
> + struct mnt_idmap *lower_idmap;
> /* Unusable (conflicting) uuid */
> bool bad_uuid;
> /* Used as a lower layer (but maybe also as upper) */
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index bd0a3f9039d2..8e78da420b75 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -944,6 +944,24 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
> return true;
> }
>
> +/*
> + * Lower file handles identify a lower fs, but not the mount whose idmap was
> + * used to decode them. Remember the first lower idmap seen for each fs so
> + * decodable export handles can be disabled if another one appears.
> + */
> +static bool ovl_lower_mnt_idmap_mismatch(struct ovl_sb *fs,
> + const struct path *path)
> +{
> + struct mnt_idmap *idmap = mnt_idmap(path->mnt);
> +
> + if (!fs->lower_idmap) {
> + fs->lower_idmap = idmap;
> + return false;
> + }
> +
> + return fs->lower_idmap != idmap;
> +}
> +
> /* Get a unique fsid for the layer */
> static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
> {
> @@ -956,8 +974,15 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
> bool warn = false;
>
> for (i = 0; i < ofs->numfs; i++) {
> - if (ofs->fs[i].sb == sb)
> + if (ofs->fs[i].sb == sb) {
> + if (ofs->config.nfs_export &&
> + ovl_lower_mnt_idmap_mismatch(&ofs->fs[i], path)) {
> + ofs->config.nfs_export = false;
> + pr_warn("different idmaps in same lower fs '%pd2', falling back to nfs_export=off.\n",
> + path->dentry);
> + }
> return i;
> + }
> }
>
> if (!ovl_lower_uuid_ok(ofs, uuid)) {
> @@ -987,6 +1012,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
> ofs->fs[ofs->numfs].sb = sb;
> ofs->fs[ofs->numfs].pseudo_dev = dev;
> ofs->fs[ofs->numfs].bad_uuid = bad_uuid;
> + ovl_lower_mnt_idmap_mismatch(&ofs->fs[ofs->numfs], path);
This helper name spells weird here.
Better just assign lower_idmap directly.
With that fixed, you may add:
Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx>
>
> return ofs->numfs++;
> }
> --
> 2.47.3
>