Skip to content

Commit 2878dff

Browse files
braunerMiklos Szeredi
authored andcommitted
ovl: use ovl_copy_{real,upper}attr() wrappers
When copying inode attributes from the upper or lower layer to ovl inodes we need to take the upper or lower layer's mount's idmapping into account. In a lot of places we call ovl_copyattr() only on upper inodes and in some we call it on either upper or lower inodes. Split this into two separate helpers. The first one should only be called on upper inodes and is thus called ovl_copy_upperattr(). The second one can be called on upper or lower inodes. We add ovl_copy_realattr() for this task. The new helper makes use of the previously added ovl_i_path_real() helper. This is needed to support idmapped base layers with overlay. When overlay copies the inode information from an upper or lower layer to the relevant overlay inode it will apply the idmapping of the upper or lower layer when doing so. The ovl inode ownership will thus always correctly reflect the ownership of the idmapped upper or lower layer. 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 ffa5723 commit 2878dff

5 files changed

Lines changed: 47 additions & 29 deletions

File tree

fs/overlayfs/dir.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,6 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
884884
{
885885
int err;
886886
const struct cred *old_cred;
887-
struct dentry *upperdentry;
888887
bool lower_positive = ovl_lower_positive(dentry);
889888
LIST_HEAD(list);
890889

@@ -927,9 +926,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
927926
* Note: we fail to update ctime if there was no copy-up, only a
928927
* whiteout
929928
*/
930-
upperdentry = ovl_dentry_upper(dentry);
931-
if (upperdentry)
932-
ovl_copyattr(d_inode(upperdentry), d_inode(dentry));
929+
if (ovl_dentry_upper(dentry))
930+
ovl_copyattr(d_inode(dentry));
933931

934932
out_drop_write:
935933
ovl_drop_write(dentry);
@@ -1277,9 +1275,9 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir,
12771275
(d_inode(new) && ovl_type_origin(new)));
12781276

12791277
/* copy ctime: */
1280-
ovl_copyattr(d_inode(olddentry), d_inode(old));
1278+
ovl_copyattr(d_inode(old));
12811279
if (d_inode(new) && ovl_dentry_upper(new))
1282-
ovl_copyattr(d_inode(newdentry), d_inode(new));
1280+
ovl_copyattr(d_inode(new));
12831281

12841282
out_dput:
12851283
dput(newdentry);

fs/overlayfs/file.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
277277
__sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb,
278278
SB_FREEZE_WRITE);
279279
file_end_write(iocb->ki_filp);
280-
ovl_copyattr(ovl_inode_real(inode), inode);
280+
ovl_copyattr(inode);
281281
}
282282

283283
orig_iocb->ki_pos = iocb->ki_pos;
@@ -360,7 +360,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
360360

361361
inode_lock(inode);
362362
/* Update mode */
363-
ovl_copyattr(ovl_inode_real(inode), inode);
363+
ovl_copyattr(inode);
364364
ret = file_remove_privs(file);
365365
if (ret)
366366
goto out_unlock;
@@ -385,7 +385,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
385385
ovl_iocb_to_rwf(ifl));
386386
file_end_write(real.file);
387387
/* Update size */
388-
ovl_copyattr(ovl_inode_real(inode), inode);
388+
ovl_copyattr(inode);
389389
} else {
390390
struct ovl_aio_req *aio_req;
391391

@@ -435,12 +435,11 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
435435
struct fd real;
436436
const struct cred *old_cred;
437437
struct inode *inode = file_inode(out);
438-
struct inode *realinode = ovl_inode_real(inode);
439438
ssize_t ret;
440439

441440
inode_lock(inode);
442441
/* Update mode */
443-
ovl_copyattr(realinode, inode);
442+
ovl_copyattr(inode);
444443
ret = file_remove_privs(out);
445444
if (ret)
446445
goto out_unlock;
@@ -456,7 +455,7 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
456455

457456
file_end_write(real.file);
458457
/* Update size */
459-
ovl_copyattr(realinode, inode);
458+
ovl_copyattr(inode);
460459
revert_creds(old_cred);
461460
fdput(real);
462461

@@ -530,7 +529,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
530529
revert_creds(old_cred);
531530

532531
/* Update size */
533-
ovl_copyattr(ovl_inode_real(inode), inode);
532+
ovl_copyattr(inode);
534533

535534
fdput(real);
536535

@@ -602,7 +601,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
602601
revert_creds(old_cred);
603602

604603
/* Update size */
605-
ovl_copyattr(ovl_inode_real(inode_out), inode_out);
604+
ovl_copyattr(inode_out);
606605

607606
fdput(real_in);
608607
fdput(real_out);

fs/overlayfs/inode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
8181
err = ovl_do_notify_change(ofs, upperdentry, attr);
8282
revert_creds(old_cred);
8383
if (!err)
84-
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
84+
ovl_copyattr(dentry->d_inode);
8585
inode_unlock(upperdentry->d_inode);
8686

8787
if (winode)
@@ -379,7 +379,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
379379
revert_creds(old_cred);
380380

381381
/* copy c/mtime */
382-
ovl_copyattr(d_inode(realdentry), inode);
382+
ovl_copyattr(inode);
383383

384384
out_drop_write:
385385
ovl_drop_write(dentry);
@@ -581,7 +581,7 @@ int ovl_fileattr_set(struct user_namespace *mnt_userns,
581581
inode_set_flags(inode, flags, OVL_COPY_I_FLAGS_MASK);
582582

583583
/* Update ctime */
584-
ovl_copyattr(ovl_inode_real(inode), inode);
584+
ovl_copyattr(inode);
585585
}
586586
ovl_drop_write(dentry);
587587
out:
@@ -791,7 +791,7 @@ void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip,
791791
oi->lowerdata = igrab(d_inode(oip->lowerdata));
792792

793793
realinode = ovl_inode_real(inode);
794-
ovl_copyattr(realinode, inode);
794+
ovl_copyattr(inode);
795795
ovl_copyflags(realinode, inode);
796796
ovl_map_ino(inode, ino, fsid);
797797
}

fs/overlayfs/overlayfs.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -621,16 +621,7 @@ bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir);
621621
struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir);
622622
struct inode *ovl_get_inode(struct super_block *sb,
623623
struct ovl_inode_params *oip);
624-
static inline void ovl_copyattr(struct inode *from, struct inode *to)
625-
{
626-
to->i_uid = from->i_uid;
627-
to->i_gid = from->i_gid;
628-
to->i_mode = from->i_mode;
629-
to->i_atime = from->i_atime;
630-
to->i_mtime = from->i_mtime;
631-
to->i_ctime = from->i_ctime;
632-
i_size_write(to, i_size_read(from));
633-
}
624+
void ovl_copyattr(struct inode *to);
634625

635626
/* vfs inode flags copied from real to ovl inode */
636627
#define OVL_COPY_I_FLAGS_MASK (S_SYNC | S_NOATIME | S_APPEND | S_IMMUTABLE)

fs/overlayfs/util.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ static void ovl_dir_version_inc(struct dentry *dentry, bool impurity)
470470
void ovl_dir_modified(struct dentry *dentry, bool impurity)
471471
{
472472
/* Copy mtime/ctime */
473-
ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry));
473+
ovl_copyattr(d_inode(dentry));
474474

475475
ovl_dir_version_inc(dentry, impurity);
476476
}
@@ -1086,3 +1086,33 @@ int ovl_sync_status(struct ovl_fs *ofs)
10861086

10871087
return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq);
10881088
}
1089+
1090+
/*
1091+
* ovl_copyattr() - copy inode attributes from layer to ovl inode
1092+
*
1093+
* When overlay copies inode information from an upper or lower layer to the
1094+
* relevant overlay inode it will apply the idmapping of the upper or lower
1095+
* layer when doing so ensuring that the ovl inode ownership will correctly
1096+
* reflect the ownership of the idmapped upper or lower layer. For example, an
1097+
* idmapped upper or lower layer mapping id 1001 to id 1000 will take care to
1098+
* map any lower or upper inode owned by id 1001 to id 1000. These mapping
1099+
* helpers are nops when the relevant layer isn't idmapped.
1100+
*/
1101+
void ovl_copyattr(struct inode *inode)
1102+
{
1103+
struct path realpath;
1104+
struct inode *realinode;
1105+
struct user_namespace *real_mnt_userns;
1106+
1107+
ovl_i_path_real(inode, &realpath);
1108+
realinode = d_inode(realpath.dentry);
1109+
real_mnt_userns = mnt_user_ns(realpath.mnt);
1110+
1111+
inode->i_uid = i_uid_into_mnt(real_mnt_userns, realinode);
1112+
inode->i_gid = i_gid_into_mnt(real_mnt_userns, realinode);
1113+
inode->i_mode = realinode->i_mode;
1114+
inode->i_atime = realinode->i_atime;
1115+
inode->i_mtime = realinode->i_mtime;
1116+
inode->i_ctime = realinode->i_ctime;
1117+
i_size_write(inode, i_size_read(realinode));
1118+
}

0 commit comments

Comments
 (0)