Skip to content

Commit a15506e

Browse files
braunerMiklos Szeredi
authored andcommitted
ovl: use ovl_do_notify_change() wrapper
Introduce ovl_do_notify_change() as a simple wrapper around notify_change() to support idmapped layers. The helper mirrors other ovl_do_*() helpers that operate on the upper layers. When changing ownership of an upper object the intended ownership needs to be mapped according to the upper layer's idmapping. This mapping is the inverse to the mapping applied when copying inode information from an upper layer to the corresponding overlay inode. So e.g., when an upper mount maps files that are stored on-disk as owned by id 1001 to 1000 this means that calling stat on this object from an idmapped mount will report the file as being owned by id 1000. Consequently in order to change ownership of an object in this filesystem so it appears as being owned by id 1000 in the upper idmapped layer it needs to store id 1001 on disk. The mnt mapping helpers take care of this. All idmapping helpers are nops when no idmapped base layers are used. Cc: <linux-unionfs@vger.kernel.org> Tested-by: Giuseppe Scrivano <gscrivan@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent 1248ea4 commit a15506e

5 files changed

Lines changed: 37 additions & 7 deletions

File tree

fs/overlayfs/copy_up.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ static int ovl_set_size(struct ovl_fs *ofs,
300300
.ia_size = stat->size,
301301
};
302302

303-
return notify_change(&init_user_ns, upperdentry, &attr, NULL);
303+
return ovl_do_notify_change(ofs, upperdentry, &attr);
304304
}
305305

306306
static int ovl_set_timestamps(struct ovl_fs *ofs, struct dentry *upperdentry,
@@ -313,7 +313,7 @@ static int ovl_set_timestamps(struct ovl_fs *ofs, struct dentry *upperdentry,
313313
.ia_mtime = stat->mtime,
314314
};
315315

316-
return notify_change(&init_user_ns, upperdentry, &attr, NULL);
316+
return ovl_do_notify_change(ofs, upperdentry, &attr);
317317
}
318318

319319
int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
@@ -326,15 +326,15 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
326326
.ia_valid = ATTR_MODE,
327327
.ia_mode = stat->mode,
328328
};
329-
err = notify_change(&init_user_ns, upperdentry, &attr, NULL);
329+
err = ovl_do_notify_change(ofs, upperdentry, &attr);
330330
}
331331
if (!err) {
332332
struct iattr attr = {
333333
.ia_valid = ATTR_UID | ATTR_GID,
334334
.ia_uid = stat->uid,
335335
.ia_gid = stat->gid,
336336
};
337-
err = notify_change(&init_user_ns, upperdentry, &attr, NULL);
337+
err = ovl_do_notify_change(ofs, upperdentry, &attr);
338338
}
339339
if (!err)
340340
ovl_set_timestamps(ofs, upperdentry, stat);

fs/overlayfs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
514514
.ia_mode = cattr->mode,
515515
};
516516
inode_lock(newdentry->d_inode);
517-
err = notify_change(&init_user_ns, newdentry, &attr, NULL);
517+
err = ovl_do_notify_change(ofs, newdentry, &attr);
518518
inode_unlock(newdentry->d_inode);
519519
if (err)
520520
goto out_cleanup;

fs/overlayfs/inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
2121
struct iattr *attr)
2222
{
2323
int err;
24+
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
2425
bool full_copy_up = false;
2526
struct dentry *upperdentry;
2627
const struct cred *old_cred;
@@ -77,7 +78,7 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
7778

7879
inode_lock(upperdentry->d_inode);
7980
old_cred = ovl_override_creds(dentry->d_sb);
80-
err = notify_change(&init_user_ns, upperdentry, attr, NULL);
81+
err = ovl_do_notify_change(ofs, upperdentry, attr);
8182
revert_creds(old_cred);
8283
if (!err)
8384
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);

fs/overlayfs/overlayfs.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,35 @@ static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox)
122122
return ovl_xattr_table[ox][ofs->config.userxattr];
123123
}
124124

125+
/*
126+
* When changing ownership of an upper object map the intended ownership
127+
* according to the upper layer's idmapping. When an upper mount idmaps files
128+
* that are stored on-disk as owned by id 1001 to id 1000 this means stat on
129+
* this object will report it as being owned by id 1000 when calling stat via
130+
* the upper mount.
131+
* In order to change ownership of an object so stat reports id 1000 when
132+
* called on an idmapped upper mount the value written to disk - i.e., the
133+
* value stored in ia_*id - must 1001. The mount mapping helper will thus take
134+
* care to map 1000 to 1001.
135+
* The mnt idmapping helpers are nops if the upper layer isn't idmapped.
136+
*/
137+
static inline int ovl_do_notify_change(struct ovl_fs *ofs,
138+
struct dentry *upperdentry,
139+
struct iattr *attr)
140+
{
141+
struct user_namespace *upper_mnt_userns = ovl_upper_mnt_userns(ofs);
142+
struct user_namespace *fs_userns = i_user_ns(d_inode(upperdentry));
143+
144+
if (attr->ia_valid & ATTR_UID)
145+
attr->ia_uid = mapped_kuid_user(upper_mnt_userns,
146+
fs_userns, attr->ia_uid);
147+
if (attr->ia_valid & ATTR_GID)
148+
attr->ia_gid = mapped_kgid_user(upper_mnt_userns,
149+
fs_userns, attr->ia_gid);
150+
151+
return notify_change(upper_mnt_userns, upperdentry, attr, NULL);
152+
}
153+
125154
static inline int ovl_do_rmdir(struct ovl_fs *ofs,
126155
struct inode *dir, struct dentry *dentry)
127156
{

fs/overlayfs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
821821

822822
/* Clear any inherited mode bits */
823823
inode_lock(work->d_inode);
824-
err = notify_change(&init_user_ns, work, &attr, NULL);
824+
err = ovl_do_notify_change(ofs, work, &attr);
825825
inode_unlock(work->d_inode);
826826
if (err)
827827
goto out_dput;

0 commit comments

Comments
 (0)