overlayfs updates for 6.12

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE9zuTYTs0RXF+Ke33EVvVyTe/1WoFAmbodTUACgkQEVvVyTe/
 1Wp5Jw/+LN99lGoKXKZ7zB8gta4hMm2O+wd3//IdfTi6u59uff0QvVNbczC6SRlJ
 sW6czIgjKpR1xt6Orp0Rof0VZK09PMqq3Iw7Tt3xEkJtjKxppfMCQHeoi03CH9kF
 gOHPW+Ad4jlCk+TYFEuHk5lQIgVtJ11JDtGjr5tNa03MbrLIa0pFpTdz65bg9uTn
 JdPqA+fiJ/mVoXlFQEZkQPeT8CgMfTbKtQDGfcmKzrNo0ZyQdW30u5lP3MGROptn
 X/QX5n77UrE9Du+UHPSaVDRUd8iA/ZcZe/7RAlKXWElHpKvAiqv84Sz0Mc1fczHx
 nQHaUfQixGs/vakkPXxVqKn/Xvnj4GDwUqyM9mG8kN1x4QpdyFRqM66zZxtWsSi5
 /PL0zwAY950a5fY4VsyRsSf6Zl/SlDdB+PVVajk6BKqMxWgvxyuVbFRUqfesHsfA
 V5GHil7F03sPzO12SvAJg8HuresCiafLdAPJgGXuGoeprmeSP9eYx0EqcUzLpHd7
 ORUF4qEylYFp8vZBJdBnZpSGRUv/mmjDDowsKeKyfgKyVR99lLKLCtqMJ0e0eGaE
 mpGNg+eq//snJldvBUHrMYQvyVm18/bbOzT0ZdGPp2bMUxLjSbiab7D3S9GKRxRt
 8GRg/bJfZw5tz2i1bxbe5IWfNij5pDilLeAQUsoO8pUwu/SrCy8=
 =wnbj
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2024-09-19 06:33:18 +02:00
commit 45d986d113
4 changed files with 79 additions and 19 deletions

View File

@ -367,8 +367,11 @@ Metadata only copy up
When the "metacopy" feature is enabled, overlayfs will only copy
up metadata (as opposed to whole file), when a metadata specific operation
like chown/chmod is performed. Full file will be copied up later when
file is opened for WRITE operation.
like chown/chmod is performed. An upper file in this state is marked with
"trusted.overlayfs.metacopy" xattr which indicates that the upper file
contains no data. The data will be copied up later when file is opened for
WRITE operation. After the lower file's data is copied up,
the "trusted.overlayfs.metacopy" xattr is removed from the upper file.
In other words, this is delayed data copy up operation and data is copied
up when there is a need to actually modify data.

View File

@ -243,8 +243,24 @@ static int ovl_verify_area(loff_t pos, loff_t pos2, loff_t len, loff_t totlen)
return 0;
}
static int ovl_sync_file(struct path *path)
{
struct file *new_file;
int err;
new_file = ovl_path_open(path, O_LARGEFILE | O_RDONLY);
if (IS_ERR(new_file))
return PTR_ERR(new_file);
err = vfs_fsync(new_file, 0);
fput(new_file);
return err;
}
static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
struct file *new_file, loff_t len)
struct file *new_file, loff_t len,
bool datasync)
{
struct path datapath;
struct file *old_file;
@ -342,7 +358,8 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
len -= bytes;
}
if (!error && ovl_should_sync(ofs))
/* call fsync once, either now or later along with metadata */
if (!error && ovl_should_sync(ofs) && datasync)
error = vfs_fsync(new_file, 0);
out_fput:
fput(old_file);
@ -574,6 +591,7 @@ struct ovl_copy_up_ctx {
bool indexed;
bool metacopy;
bool metacopy_digest;
bool metadata_fsync;
};
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)
if (IS_ERR(new_file))
return PTR_ERR(new_file);
err = ovl_copy_up_file(ofs, c->dentry, new_file, c->stat.size);
err = ovl_copy_up_file(ofs, c->dentry, new_file, c->stat.size,
!c->metadata_fsync);
fput(new_file);
return err;
@ -701,6 +720,10 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp)
err = ovl_set_attr(ofs, temp, &c->stat);
inode_unlock(temp->d_inode);
/* fsync metadata before moving it into upper dir */
if (!err && ovl_should_sync(ofs) && c->metadata_fsync)
err = ovl_sync_file(&upperpath);
return err;
}
@ -860,7 +883,8 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
temp = tmpfile->f_path.dentry;
if (!c->metacopy && c->stat.size) {
err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size);
err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size,
!c->metadata_fsync);
if (err)
goto out_fput;
}
@ -1135,6 +1159,17 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
!kgid_has_mapping(current_user_ns(), ctx.stat.gid))
return -EOVERFLOW;
/*
* With metacopy disabled, we fsync after final metadata copyup, for
* both regular files and directories to get atomic copyup semantics
* on filesystems that do not use strict metadata ordering (e.g. ubifs).
*
* With metacopy enabled we want to avoid fsync on all meta copyup
* that will hurt performance of workloads such as chown -R, so we
* only fsync on data copyup as legacy behavior.
*/
ctx.metadata_fsync = !OVL_FS(dentry->d_sb)->config.metacopy &&
(S_ISREG(ctx.stat.mode) || S_ISDIR(ctx.stat.mode));
ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
if (parent) {

View File

@ -755,11 +755,6 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
{
struct ovl_opt_set set = ctx->set;
if (ctx->nr_data > 0 && !config->metacopy) {
pr_err("lower data-only dirs require metacopy support.\n");
return -EINVAL;
}
/* Workdir/index are useless in non-upper mount */
if (!config->upperdir) {
if (config->workdir) {
@ -911,6 +906,39 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
config->metacopy = false;
}
/*
* Fail if we don't have trusted xattr capability and a feature was
* explicitly requested that requires them.
*/
if (!config->userxattr && !capable(CAP_SYS_ADMIN)) {
if (set.redirect &&
config->redirect_mode != OVL_REDIRECT_NOFOLLOW) {
pr_err("redirect_dir requires permission to access trusted xattrs\n");
return -EPERM;
}
if (config->metacopy && set.metacopy) {
pr_err("metacopy requires permission to access trusted xattrs\n");
return -EPERM;
}
if (config->verity_mode) {
pr_err("verity requires permission to access trusted xattrs\n");
return -EPERM;
}
if (ctx->nr_data > 0) {
pr_err("lower data-only dirs require permission to access trusted xattrs\n");
return -EPERM;
}
/*
* Other xattr-dependent features should be disabled without
* great disturbance to the user in ovl_make_workdir().
*/
}
if (ctx->nr_data > 0 && !config->metacopy) {
pr_err("lower data-only dirs require metacopy support.\n");
return -EINVAL;
}
return 0;
}

View File

@ -202,15 +202,9 @@ static int ovl_sync_fs(struct super_block *sb, int wait)
int ret;
ret = ovl_sync_status(ofs);
/*
* We have to always set the err, because the return value isn't
* checked in syncfs, and instead indirectly return an error via
* the sb's writeback errseq, which VFS inspects after this call.
*/
if (ret < 0) {
errseq_set(&sb->s_wb_err, -EIO);
if (ret < 0)
return -EIO;
}
if (!ret)
return ret;