mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
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:
commit
45d986d113
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user