overlayfs updates for 7.0

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE9zuTYTs0RXF+Ke33EVvVyTe/1WoFAmmUaqQACgkQEVvVyTe/
 1WrRVRAAil+jvxM26SR3lPp/EmGdlsvRwflin1wb6laey96Ezfos4KLBFkoz9cgZ
 gW4aZBGx2MDBQy3DNlVbsQZgc4CAnQxrH5HLeR8y5zSbEI3WlcI1vQonzsh61/Cd
 Ajnu0asivUTWnuoFicq7syT4TcDVUJFMNxjNCTBkRDWmQIkQZAA2Dy/0nWpur83s
 QjAOLcCljxp88oqY1YE5Lbt7xyToL8vhxF2vN1cFrIZ6Ec/BN9x5LizAYGRjEQ6o
 qN6o6dAZ4VDyLHms8YQ4KHuj+1psTEPyCNeC3tReek5VKYNS/I9WAwawD4QnmfSu
 DF5CYkErFW3eVczFkaKl3K65CR6YkBFJhcNeEIViDh4TKSTtmdFURZPH+IVsB6KT
 /Z+4LnNMxdN55tleYDMoxBBecurLQSyjVMDoCrMlRB5iWJL+/G5TO2ahDp+wGWCu
 b9FS3DTa6XE/e7xRzDvitRfBX5N8xHNTn8keKRHe4Q7j0DRMYfdltbMz5wyhXfUW
 YOZNINFpwwvn0Hq8NK86/lhctOi0qkBmqRbMIzAYwgYJI8Kdbe3wqcDeo2k7K4fC
 J4O+puL263+vA85jqyXGmk+H4EK8Z3BNX+uFh8ucFtGi/rBGpLHBS1HiFEFBYRoW
 IX6y2EGxgDHvrRbyfVG2EJMjd9XMflOjMYkurJ0r38Cl5Vnreqg=
 =v9Yt
 -----END PGP SIGNATURE-----

Merge tag 'ovl-update-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs

Pull overlayfs update from Amir Goldstein:
 "Relax the semantics of uuid=off to cater to a use case of overlayfs
  lower layers on btrfs clones, whose UUID are ephemeral and an upper
  layer on a different filesystem"

* tag 'ovl-update-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs:
  ovl: relax requirement for uuid=off,index=on
This commit is contained in:
Linus Torvalds 2026-02-17 15:08:24 -08:00
commit 0ba83f0968
4 changed files with 24 additions and 20 deletions

View file

@ -753,9 +753,9 @@ Note: the mount options index=off,nfs_export=on are conflicting for a
read-write mount and will result in an error.
Note: the mount option uuid=off can be used to replace UUID of the underlying
filesystem in file handles with null, and effectively disable UUID checks. This
filesystem in file handles with null, in order to relax the UUID checks. This
can be useful in case the underlying disk is copied and the UUID of this copy
is changed. This is only applicable if all lower/upper/work directories are on
is changed. This is only applicable if all lower directories are on
the same filesystem, otherwise it will fallback to normal behaviour.
@ -769,7 +769,7 @@ controlled by the "uuid" mount option, which supports these values:
UUID of overlayfs is null. fsid is taken from upper most filesystem.
- "off":
UUID of overlayfs is null. fsid is taken from upper most filesystem.
UUID of underlying layers is ignored.
UUID of underlying layers is ignored and null used instead.
- "on":
UUID of overlayfs is generated and used to report a unique fsid.
UUID is stored in xattr "trusted.overlay.uuid", making overlayfs fsid

View file

@ -159,6 +159,18 @@ invalid:
goto out;
}
bool ovl_uuid_match(struct ovl_fs *ofs, const struct super_block *sb,
const uuid_t *uuid)
{
/*
* Make sure that the stored uuid matches the uuid of the lower
* layer where file handle will be decoded.
* In case of uuid=off option just make sure that stored uuid is null.
*/
return ovl_origin_uuid(ofs) ? uuid_equal(uuid, &sb->s_uuid) :
uuid_is_null(uuid);
}
struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
struct vfsmount *mnt, bool connected)
{
@ -168,14 +180,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
if (!capable(CAP_DAC_READ_SEARCH))
return NULL;
/*
* Make sure that the stored uuid matches the uuid of the lower
* layer where file handle will be decoded.
* In case of uuid=off option just make sure that stored uuid is null.
*/
if (ovl_origin_uuid(ofs) ?
!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid) :
!uuid_is_null(&fh->fb.uuid))
if (!ovl_uuid_match(ofs, mnt->mnt_sb, &fh->fb.uuid))
return NULL;
bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));

View file

@ -710,6 +710,8 @@ static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
return ovl_check_fb_len(&fh->fb, fh_len - OVL_FH_WIRE_OFFSET);
}
bool ovl_uuid_match(struct ovl_fs *ofs, const struct super_block *sb,
const uuid_t *uuid);
struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
struct vfsmount *mnt, bool connected);
int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,

View file

@ -940,7 +940,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
* disable lower file handle decoding on all of them.
*/
if (ofs->fs[i].is_lower &&
uuid_equal(&ofs->fs[i].sb->s_uuid, uuid)) {
ovl_uuid_match(ofs, ofs->fs[i].sb, uuid)) {
ofs->fs[i].bad_uuid = true;
return false;
}
@ -952,6 +952,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
{
struct super_block *sb = path->mnt->mnt_sb;
const uuid_t *uuid = ovl_origin_uuid(ofs) ? &sb->s_uuid : &uuid_null;
unsigned int i;
dev_t dev;
int err;
@ -963,7 +964,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
return i;
}
if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) {
if (!ovl_lower_uuid_ok(ofs, uuid)) {
bad_uuid = true;
if (ofs->config.xino == OVL_XINO_AUTO) {
ofs->config.xino = OVL_XINO_OFF;
@ -975,9 +976,8 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
warn = true;
}
if (warn) {
pr_warn("%s uuid detected in lower fs '%pd2', falling back to xino=%s,index=off,nfs_export=off.\n",
uuid_is_null(&sb->s_uuid) ? "null" :
"conflicting",
pr_warn("%s uuid in non-single lower fs '%pd2', falling back to xino=%s,index=off,nfs_export=off.\n",
uuid_is_null(uuid) ? "null" : "conflicting",
path->dentry, ovl_xino_mode(&ofs->config));
}
}
@ -1469,10 +1469,7 @@ static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb)
if (!ovl_upper_mnt(ofs))
sb->s_flags |= SB_RDONLY;
if (!ovl_origin_uuid(ofs) && ofs->numfs > 1) {
pr_warn("The uuid=off requires a single fs for lower and upper, falling back to uuid=null.\n");
ofs->config.uuid = OVL_UUID_NULL;
} else if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
if (ovl_has_fsid(ofs) && ovl_upper_mnt(ofs)) {
/* Use per instance persistent uuid/fsid */
ovl_init_uuid_xattr(sb, ofs, &ctx->upper);
}