Skip to content

Commit 45d986d

Browse files
committed
Merge tag 'ovl-update-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs
Pull overlayfs updates from Amir Goldstein: - Increase robustness of overlayfs to crashes in the case of underlying filesystems that to not guarantee metadata ordering to persistent storage (problem was reported with ubifs). - Deny mount inside container with features that require root privileges to work properly, instead of failing operations later. - Some clarifications to overlayfs documentation. * tag 'ovl-update-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs: ovl: fail if trusted xattrs are needed but caller lacks permission overlayfs.rst: update metacopy section in overlayfs documentation ovl: fsync after metadata copy-up ovl: don't set the superblock's errseq_t manually
2 parents 4a39ac5 + 6c4a5f9 commit 45d986d

File tree

4 files changed

+79
-19
lines changed

4 files changed

+79
-19
lines changed

Documentation/filesystems/overlayfs.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,11 @@ Metadata only copy up
367367

368368
When the "metacopy" feature is enabled, overlayfs will only copy
369369
up metadata (as opposed to whole file), when a metadata specific operation
370-
like chown/chmod is performed. Full file will be copied up later when
371-
file is opened for WRITE operation.
370+
like chown/chmod is performed. An upper file in this state is marked with
371+
"trusted.overlayfs.metacopy" xattr which indicates that the upper file
372+
contains no data. The data will be copied up later when file is opened for
373+
WRITE operation. After the lower file's data is copied up,
374+
the "trusted.overlayfs.metacopy" xattr is removed from the upper file.
372375

373376
In other words, this is delayed data copy up operation and data is copied
374377
up when there is a need to actually modify data.

fs/overlayfs/copy_up.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,24 @@ static int ovl_verify_area(loff_t pos, loff_t pos2, loff_t len, loff_t totlen)
243243
return 0;
244244
}
245245

246+
static int ovl_sync_file(struct path *path)
247+
{
248+
struct file *new_file;
249+
int err;
250+
251+
new_file = ovl_path_open(path, O_LARGEFILE | O_RDONLY);
252+
if (IS_ERR(new_file))
253+
return PTR_ERR(new_file);
254+
255+
err = vfs_fsync(new_file, 0);
256+
fput(new_file);
257+
258+
return err;
259+
}
260+
246261
static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
247-
struct file *new_file, loff_t len)
262+
struct file *new_file, loff_t len,
263+
bool datasync)
248264
{
249265
struct path datapath;
250266
struct file *old_file;
@@ -342,7 +358,8 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
342358

343359
len -= bytes;
344360
}
345-
if (!error && ovl_should_sync(ofs))
361+
/* call fsync once, either now or later along with metadata */
362+
if (!error && ovl_should_sync(ofs) && datasync)
346363
error = vfs_fsync(new_file, 0);
347364
out_fput:
348365
fput(old_file);
@@ -574,6 +591,7 @@ struct ovl_copy_up_ctx {
574591
bool indexed;
575592
bool metacopy;
576593
bool metacopy_digest;
594+
bool metadata_fsync;
577595
};
578596

579597
static int ovl_link_up(struct ovl_copy_up_ctx *c)
@@ -634,7 +652,8 @@ static int ovl_copy_up_data(struct ovl_copy_up_ctx *c, const struct path *temp)
634652
if (IS_ERR(new_file))
635653
return PTR_ERR(new_file);
636654

637-
err = ovl_copy_up_file(ofs, c->dentry, new_file, c->stat.size);
655+
err = ovl_copy_up_file(ofs, c->dentry, new_file, c->stat.size,
656+
!c->metadata_fsync);
638657
fput(new_file);
639658

640659
return err;
@@ -701,6 +720,10 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp)
701720
err = ovl_set_attr(ofs, temp, &c->stat);
702721
inode_unlock(temp->d_inode);
703722

723+
/* fsync metadata before moving it into upper dir */
724+
if (!err && ovl_should_sync(ofs) && c->metadata_fsync)
725+
err = ovl_sync_file(&upperpath);
726+
704727
return err;
705728
}
706729

@@ -860,7 +883,8 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
860883

861884
temp = tmpfile->f_path.dentry;
862885
if (!c->metacopy && c->stat.size) {
863-
err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size);
886+
err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size,
887+
!c->metadata_fsync);
864888
if (err)
865889
goto out_fput;
866890
}
@@ -1135,6 +1159,17 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
11351159
!kgid_has_mapping(current_user_ns(), ctx.stat.gid))
11361160
return -EOVERFLOW;
11371161

1162+
/*
1163+
* With metacopy disabled, we fsync after final metadata copyup, for
1164+
* both regular files and directories to get atomic copyup semantics
1165+
* on filesystems that do not use strict metadata ordering (e.g. ubifs).
1166+
*
1167+
* With metacopy enabled we want to avoid fsync on all meta copyup
1168+
* that will hurt performance of workloads such as chown -R, so we
1169+
* only fsync on data copyup as legacy behavior.
1170+
*/
1171+
ctx.metadata_fsync = !OVL_FS(dentry->d_sb)->config.metacopy &&
1172+
(S_ISREG(ctx.stat.mode) || S_ISDIR(ctx.stat.mode));
11381173
ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
11391174

11401175
if (parent) {

fs/overlayfs/params.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -755,11 +755,6 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
755755
{
756756
struct ovl_opt_set set = ctx->set;
757757

758-
if (ctx->nr_data > 0 && !config->metacopy) {
759-
pr_err("lower data-only dirs require metacopy support.\n");
760-
return -EINVAL;
761-
}
762-
763758
/* Workdir/index are useless in non-upper mount */
764759
if (!config->upperdir) {
765760
if (config->workdir) {
@@ -911,6 +906,39 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
911906
config->metacopy = false;
912907
}
913908

909+
/*
910+
* Fail if we don't have trusted xattr capability and a feature was
911+
* explicitly requested that requires them.
912+
*/
913+
if (!config->userxattr && !capable(CAP_SYS_ADMIN)) {
914+
if (set.redirect &&
915+
config->redirect_mode != OVL_REDIRECT_NOFOLLOW) {
916+
pr_err("redirect_dir requires permission to access trusted xattrs\n");
917+
return -EPERM;
918+
}
919+
if (config->metacopy && set.metacopy) {
920+
pr_err("metacopy requires permission to access trusted xattrs\n");
921+
return -EPERM;
922+
}
923+
if (config->verity_mode) {
924+
pr_err("verity requires permission to access trusted xattrs\n");
925+
return -EPERM;
926+
}
927+
if (ctx->nr_data > 0) {
928+
pr_err("lower data-only dirs require permission to access trusted xattrs\n");
929+
return -EPERM;
930+
}
931+
/*
932+
* Other xattr-dependent features should be disabled without
933+
* great disturbance to the user in ovl_make_workdir().
934+
*/
935+
}
936+
937+
if (ctx->nr_data > 0 && !config->metacopy) {
938+
pr_err("lower data-only dirs require metacopy support.\n");
939+
return -EINVAL;
940+
}
941+
914942
return 0;
915943
}
916944

fs/overlayfs/super.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,9 @@ static int ovl_sync_fs(struct super_block *sb, int wait)
202202
int ret;
203203

204204
ret = ovl_sync_status(ofs);
205-
/*
206-
* We have to always set the err, because the return value isn't
207-
* checked in syncfs, and instead indirectly return an error via
208-
* the sb's writeback errseq, which VFS inspects after this call.
209-
*/
210-
if (ret < 0) {
211-
errseq_set(&sb->s_wb_err, -EIO);
205+
206+
if (ret < 0)
212207
return -EIO;
213-
}
214208

215209
if (!ret)
216210
return ret;

0 commit comments

Comments
 (0)