I'm announcing the release of the 6.6.73 kernel.
Only users of overlayfs need to upgrade, this release reverts some changes that were reported to be causing problems. Thanks to Ignat and Amir for the quick reporting on the issue.
The updated 6.6.y git tree can be found at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-6.6.y and can be browsed at the normal kernel.org git web browser: https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git%3Ba=summa...
thanks,
greg k-h
------------
Makefile | 2 - fs/overlayfs/copy_up.c | 62 ++++++++++++++++++----------------------------- fs/overlayfs/export.c | 49 ++++++++++++++++--------------------- fs/overlayfs/namei.c | 41 ++++++++----------------------- fs/overlayfs/overlayfs.h | 28 ++++++--------------- fs/overlayfs/super.c | 20 ++++----------- fs/overlayfs/util.c | 10 ------- 7 files changed, 72 insertions(+), 140 deletions(-)
Greg Kroah-Hartman (4): Revert "ovl: support encoding fid from inode with no alias" Revert "ovl: pass realinode to ovl_encode_real_fh() instead of realdentry" Revert "ovl: do not encode lower fh with upper sb_writers held" Linux 6.6.73
diff --git a/Makefile b/Makefile index fb4949cac6ff..2ba627f54590 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 PATCHLEVEL = 6 -SUBLEVEL = 72 +SUBLEVEL = 73 EXTRAVERSION = NAME = Pinguïn Aangedreven
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index f14c412c5609..ada3fcc9c6d5 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -371,13 +371,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry, return err; }
-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, +struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, bool is_upper) { struct ovl_fh *fh; int fh_type, dwords; int buflen = MAX_HANDLE_SZ; - uuid_t *uuid = &realinode->i_sb->s_uuid; + uuid_t *uuid = &real->d_sb->s_uuid; int err;
/* Make sure the real fid stays 32bit aligned */ @@ -394,8 +394,7 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, * the price or reconnecting the dentry. */ dwords = buflen >> 2; - fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid, - &dwords, NULL, 0); + fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0); buflen = (dwords << 2);
err = -EIO; @@ -427,29 +426,29 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, return ERR_PTR(err); }
-struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin) +int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, + struct dentry *upper) { + const struct ovl_fh *fh = NULL; + int err; + /* * When lower layer doesn't support export operations store a 'null' fh, * so we can use the overlay.origin xattr to distignuish between a copy * up and a pure upper inode. */ - if (!ovl_can_decode_fh(origin->d_sb)) - return NULL; - - return ovl_encode_real_fh(ofs, d_inode(origin), false); -} - -int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh, - struct dentry *upper) -{ - int err; + if (ovl_can_decode_fh(lower->d_sb)) { + fh = ovl_encode_real_fh(ofs, lower, false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + }
/* * Do not fail when upper doesn't support xattrs. */ err = ovl_check_setxattr(ofs, upper, OVL_XATTR_ORIGIN, fh->buf, fh ? fh->fb.len : 0, 0); + kfree(fh);
/* Ignore -EPERM from setting "user.*" on symlink/special */ return err == -EPERM ? 0 : err; @@ -462,7 +461,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, const struct ovl_fh *fh; int err;
- fh = ovl_encode_real_fh(ofs, d_inode(upper), true); + fh = ovl_encode_real_fh(ofs, upper, true); if (IS_ERR(fh)) return PTR_ERR(fh);
@@ -477,7 +476,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, * * Caller must hold i_mutex on indexdir. */ -static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh, +static int ovl_create_index(struct dentry *dentry, struct dentry *origin, struct dentry *upper) { struct ovl_fs *ofs = OVL_FS(dentry->d_sb); @@ -503,7 +502,7 @@ static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh, if (WARN_ON(ovl_test_flag(OVL_INDEX, d_inode(dentry)))) return -EIO;
- err = ovl_get_index_name_fh(fh, &name); + err = ovl_get_index_name(ofs, origin, &name); if (err) return err;
@@ -542,7 +541,6 @@ struct ovl_copy_up_ctx { struct dentry *destdir; struct qstr destname; struct dentry *workdir; - const struct ovl_fh *origin_fh; bool origin; bool indexed; bool metacopy; @@ -639,7 +637,7 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp) * hard link. */ if (c->origin) { - err = ovl_set_origin_fh(ofs, c->origin_fh, temp); + err = ovl_set_origin(ofs, c->lowerpath.dentry, temp); if (err) return err; } @@ -751,7 +749,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) goto cleanup;
if (S_ISDIR(c->stat.mode) && c->indexed) { - err = ovl_create_index(c->dentry, c->origin_fh, temp); + err = ovl_create_index(c->dentry, c->lowerpath.dentry, temp); if (err) goto cleanup; } @@ -863,8 +861,6 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) { int err; struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); - struct dentry *origin = c->lowerpath.dentry; - struct ovl_fh *fh = NULL; bool to_index = false;
/* @@ -881,25 +877,17 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) to_index = true; }
- if (S_ISDIR(c->stat.mode) || c->stat.nlink == 1 || to_index) { - fh = ovl_get_origin_fh(ofs, origin); - if (IS_ERR(fh)) - return PTR_ERR(fh); - - /* origin_fh may be NULL */ - c->origin_fh = fh; + if (S_ISDIR(c->stat.mode) || c->stat.nlink == 1 || to_index) c->origin = true; - }
if (to_index) { c->destdir = ovl_indexdir(c->dentry->d_sb); - err = ovl_get_index_name(ofs, origin, &c->destname); + err = ovl_get_index_name(ofs, c->lowerpath.dentry, &c->destname); if (err) - goto out_free_fh; + return err; } else if (WARN_ON(!c->parent)) { /* Disconnected dentry must be copied up to index dir */ - err = -EIO; - goto out_free_fh; + return -EIO; } else { /* * Mark parent "impure" because it may now contain non-pure @@ -907,7 +895,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) */ err = ovl_set_impure(c->parent, c->destdir); if (err) - goto out_free_fh; + return err; }
/* Should we copyup with O_TMPFILE or with workdir? */ @@ -939,8 +927,6 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) out: if (to_index) kfree(c->destname.name); -out_free_fh: - kfree(fh); return err; }
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index 3a17e4366f28..611ff567a1aa 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c @@ -181,37 +181,35 @@ static int ovl_connect_layer(struct dentry *dentry) * * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. */ -static int ovl_check_encode_origin(struct inode *inode) +static int ovl_check_encode_origin(struct dentry *dentry) { - struct ovl_fs *ofs = OVL_FS(inode->i_sb); + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); bool decodable = ofs->config.nfs_export; - struct dentry *dentry; - int err;
/* No upper layer? */ if (!ovl_upper_mnt(ofs)) return 1;
/* Lower file handle for non-upper non-decodable */ - if (!ovl_inode_upper(inode) && !decodable) + if (!ovl_dentry_upper(dentry) && !decodable) return 1;
/* Upper file handle for pure upper */ - if (!ovl_inode_lower(inode)) + if (!ovl_dentry_lower(dentry)) return 0;
/* * Root is never indexed, so if there's an upper layer, encode upper for * root. */ - if (inode == d_inode(inode->i_sb->s_root)) + if (dentry == dentry->d_sb->s_root) return 0;
/* * Upper decodable file handle for non-indexed upper. */ - if (ovl_inode_upper(inode) && decodable && - !ovl_test_flag(OVL_INDEX, inode)) + if (ovl_dentry_upper(dentry) && decodable && + !ovl_test_flag(OVL_INDEX, d_inode(dentry))) return 0;
/* @@ -220,23 +218,14 @@ static int ovl_check_encode_origin(struct inode *inode) * ovl_connect_layer() will try to make origin's layer "connected" by * copying up a "connectable" ancestor. */ - if (!decodable || !S_ISDIR(inode->i_mode)) - return 1; - - dentry = d_find_any_alias(inode); - if (!dentry) - return -ENOENT; - - err = ovl_connect_layer(dentry); - dput(dentry); - if (err < 0) - return err; + if (d_is_dir(dentry) && decodable) + return ovl_connect_layer(dentry);
/* Lower file handle for indexed and non-upper dir/non-dir */ return 1; }
-static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, +static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, u32 *fid, int buflen) { struct ovl_fh *fh = NULL; @@ -247,13 +236,13 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, * Check if we should encode a lower or upper file handle and maybe * copy up an ancestor to make lower file handle connectable. */ - err = enc_lower = ovl_check_encode_origin(inode); + err = enc_lower = ovl_check_encode_origin(dentry); if (enc_lower < 0) goto fail;
/* Encode an upper or lower file handle */ - fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) : - ovl_inode_upper(inode), !enc_lower); + fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) : + ovl_dentry_upper(dentry), !enc_lower); if (IS_ERR(fh)) return PTR_ERR(fh);
@@ -267,8 +256,8 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, return err;
fail: - pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n", - inode->i_ino, err); + pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n", + dentry, err); goto out; }
@@ -276,13 +265,19 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len, struct inode *parent) { struct ovl_fs *ofs = OVL_FS(inode->i_sb); + struct dentry *dentry; int bytes, buflen = *max_len << 2;
/* TODO: encode connectable file handles */ if (parent) return FILEID_INVALID;
- bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen); + dentry = d_find_any_alias(inode); + if (!dentry) + return FILEID_INVALID; + + bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); + dput(dentry); if (bytes <= 0) return FILEID_INVALID;
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 2d2ef671b36b..80391c687c2a 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -507,19 +507,6 @@ static int ovl_verify_fh(struct ovl_fs *ofs, struct dentry *dentry, return err; }
-int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox, const struct ovl_fh *fh, - bool is_upper, bool set) -{ - int err; - - err = ovl_verify_fh(ofs, dentry, ox, fh); - if (set && err == -ENODATA) - err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); - - return err; -} - /* * Verify that @real dentry matches the file handle stored in xattr @name. * @@ -528,22 +515,24 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, * * Return 0 on match, -ESTALE on mismatch, -ENODATA on no xattr, < 0 on error. */ -int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox, struct dentry *real, - bool is_upper, bool set) +int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, + enum ovl_xattr ox, struct dentry *real, bool is_upper, + bool set) { struct inode *inode; struct ovl_fh *fh; int err;
- fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper); + fh = ovl_encode_real_fh(ofs, real, is_upper); err = PTR_ERR(fh); if (IS_ERR(fh)) { fh = NULL; goto fail; }
- err = ovl_verify_set_fh(ofs, dentry, ox, fh, is_upper, set); + err = ovl_verify_fh(ofs, dentry, ox, fh); + if (set && err == -ENODATA) + err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); if (err) goto fail;
@@ -559,7 +548,6 @@ int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, goto out; }
- /* Get upper dentry from index */ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index, bool connected) @@ -696,7 +684,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index) goto out; }
-int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name) +static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name) { char *n, *s;
@@ -732,7 +720,7 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, struct ovl_fh *fh; int err;
- fh = ovl_encode_real_fh(ofs, d_inode(origin), false); + fh = ovl_encode_real_fh(ofs, origin, false); if (IS_ERR(fh)) return PTR_ERR(fh);
@@ -885,27 +873,20 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path) static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry, struct dentry *lower, struct dentry *upper) { - const struct ovl_fh *fh; int err;
if (ovl_check_origin_xattr(ofs, upper)) return 0;
- fh = ovl_get_origin_fh(ofs, lower); - if (IS_ERR(fh)) - return PTR_ERR(fh); - err = ovl_want_write(dentry); if (err) - goto out; + return err;
- err = ovl_set_origin_fh(ofs, fh, upper); + err = ovl_set_origin(ofs, lower, upper); if (!err) err = ovl_set_impure(dentry->d_parent, upper->d_parent);
ovl_drop_write(dentry); -out: - kfree(fh); return err; }
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index ca63a26a6170..09ca82ed0f8c 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -632,15 +632,11 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh, int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, struct dentry *upperdentry, struct ovl_path **stackp); int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox, const struct ovl_fh *fh, - bool is_upper, bool set); -int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox, struct dentry *real, - bool is_upper, bool set); + enum ovl_xattr ox, struct dentry *real, bool is_upper, + bool set); struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index, bool connected); int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); -int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name); int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, struct qstr *name); struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh); @@ -652,24 +648,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); bool ovl_lower_positive(struct dentry *dentry);
-static inline int ovl_verify_origin_fh(struct ovl_fs *ofs, struct dentry *upper, - const struct ovl_fh *fh, bool set) -{ - return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, fh, false, set); -} - static inline int ovl_verify_origin(struct ovl_fs *ofs, struct dentry *upper, struct dentry *origin, bool set) { - return ovl_verify_origin_xattr(ofs, upper, OVL_XATTR_ORIGIN, origin, - false, set); + return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, origin, + false, set); }
static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index, struct dentry *upper, bool set) { - return ovl_verify_origin_xattr(ofs, index, OVL_XATTR_UPPER, upper, - true, set); + return ovl_verify_set_fh(ofs, index, OVL_XATTR_UPPER, upper, true, set); }
/* readdir.c */ @@ -832,11 +821,10 @@ int ovl_copy_up_with_data(struct dentry *dentry); int ovl_maybe_copy_up(struct dentry *dentry, int flags); int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new); int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat); -struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, +struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, bool is_upper); -struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin); -int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh, - struct dentry *upper); +int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, + struct dentry *upper);
/* export.c */ extern const struct export_operations ovl_export_operations; diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index e2574034c3fa..2c056d737c27 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -879,20 +879,15 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, { struct vfsmount *mnt = ovl_upper_mnt(ofs); struct dentry *indexdir; - struct dentry *origin = ovl_lowerstack(oe)->dentry; - const struct ovl_fh *fh; int err;
- fh = ovl_get_origin_fh(ofs, origin); - if (IS_ERR(fh)) - return PTR_ERR(fh); - err = mnt_want_write(mnt); if (err) - goto out_free_fh; + return err;
/* Verify lower root is upper root origin */ - err = ovl_verify_origin_fh(ofs, upperpath->dentry, fh, true); + err = ovl_verify_origin(ofs, upperpath->dentry, + ovl_lowerstack(oe)->dentry, true); if (err) { pr_err("failed to verify upper root origin\n"); goto out; @@ -924,10 +919,9 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, * directory entries. */ if (ovl_check_origin_xattr(ofs, ofs->indexdir)) { - err = ovl_verify_origin_xattr(ofs, ofs->indexdir, - OVL_XATTR_ORIGIN, - upperpath->dentry, true, - false); + err = ovl_verify_set_fh(ofs, ofs->indexdir, + OVL_XATTR_ORIGIN, + upperpath->dentry, true, false); if (err) pr_err("failed to verify index dir 'origin' xattr\n"); } @@ -945,8 +939,6 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
out: mnt_drop_write(mnt); -out_free_fh: - kfree(fh); return err; }
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 4e6b747e0f2e..0bf3ffcd072f 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -976,18 +976,12 @@ static void ovl_cleanup_index(struct dentry *dentry) struct dentry *index = NULL; struct inode *inode; struct qstr name = { }; - bool got_write = false; int err;
err = ovl_get_index_name(ofs, lowerdentry, &name); if (err) goto fail;
- err = ovl_want_write(dentry); - if (err) - goto fail; - - got_write = true; inode = d_inode(upperdentry); if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) { pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", @@ -1025,8 +1019,6 @@ static void ovl_cleanup_index(struct dentry *dentry) goto fail;
out: - if (got_write) - ovl_drop_write(dentry); kfree(name.name); dput(index); return; @@ -1097,8 +1089,6 @@ void ovl_nlink_end(struct dentry *dentry) { struct inode *inode = d_inode(dentry);
- ovl_drop_write(dentry); - if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { const struct cred *old_cred;
linux-stable-mirror@lists.linaro.org