summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-06-15 15:19:52 +0200
committerChristian Brauner <brauner@kernel.org>2026-06-29 10:32:31 +0200
commit10a16f5b9111da6e553f8533605f7216e13a37b8 (patch)
treefe5707bac2b260cf86159e7fbdf79ad751e0b052 /fs
parent21b9aa3b8025445a71d5715458ea88457ca9e43f (diff)
ovl: handle idmapped mounts in ovl_setattr()
Pass the mount's struct mnt_idmap to setattr_prepare() so that the permission checks for a chown/chmod performed through an idmapped overlay mount are evaluated in the mount's id space. The ownership requested in @attr is expressed relative to the overlay mount idmap. Before forwarding the change to the upper layer via ovl_do_notify_change() - whose notify_change() applies the upper layer idmap in turn - rebase ia_vfsuid/ia_vfsgid into the overlay's own id space, i.e. the same space as the overlay inode's i_{u,g}id established by ovl_copyattr(). Without this rebase the upper layer would interpret the caller's mount-relative id as an upper-relative one and store the wrong owner on disk, or reject it with -EOVERFLOW. from_vfsuid() returns INVALID_UID for an id that the overlay mount idmap does not map; that invalid id is carried faithfully into the forwarded iattr and rejected by the upper notify_change() via vfsuid_has_fsmapping(), so no bogus owner can be written. No functional change until FS_ALLOW_IDMAP is set on ovl_fs_type; until then the overlay mount idmap is &nop_mnt_idmap and from_vfsuid() is the identity. Link: https://patch.msgid.link/20260615-work-idmapped-overlayfs-v1-3-7381632aa402@kernel.org Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/inode.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index f59db57dfd55..33734ca971e1 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -26,10 +26,18 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
bool full_copy_up = false;
struct dentry *upperdentry;
- err = setattr_prepare(&nop_mnt_idmap, dentry, attr);
+ err = setattr_prepare(idmap, dentry, attr);
if (err)
return err;
+ /* Rebase ownership from the mount idmap into overlay id space. */
+ if (attr->ia_valid & ATTR_UID)
+ attr->ia_vfsuid = VFSUIDT_INIT(from_vfsuid(idmap,
+ i_user_ns(d_inode(dentry)), attr->ia_vfsuid));
+ if (attr->ia_valid & ATTR_GID)
+ attr->ia_vfsgid = VFSGIDT_INIT(from_vfsgid(idmap,
+ i_user_ns(d_inode(dentry)), attr->ia_vfsgid));
+
if (attr->ia_valid & ATTR_SIZE) {
/* Truncate should trigger data copy up as well */
full_copy_up = true;