From: Greg Kroah-Hartman Date: Tue, 21 Jan 2025 11:35:20 +0000 (+0100) Subject: 6.6-stable patches X-Git-Tag: v5.15.177~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=241e4ea6da3b39b8703d1a71059fae9ac1eb6aa7;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: fs-relax-assertions-on-failure-to-encode-file-handles.patch ovl-pass-realinode-to-ovl_encode_real_fh-instead-of-realdentry.patch ovl-support-encoding-fid-from-inode-with-no-alias.patch --- diff --git a/queue-6.6/fs-relax-assertions-on-failure-to-encode-file-handles.patch b/queue-6.6/fs-relax-assertions-on-failure-to-encode-file-handles.patch new file mode 100644 index 0000000000..23b2244c7a --- /dev/null +++ b/queue-6.6/fs-relax-assertions-on-failure-to-encode-file-handles.patch @@ -0,0 +1,81 @@ +From 974e3fe0ac61de85015bbe5a4990cf4127b304b2 Mon Sep 17 00:00:00 2001 +From: Amir Goldstein +Date: Thu, 19 Dec 2024 12:53:01 +0100 +Subject: fs: relax assertions on failure to encode file handles + +From: Amir Goldstein + +commit 974e3fe0ac61de85015bbe5a4990cf4127b304b2 upstream. + +Encoding file handles is usually performed by a filesystem >encode_fh() +method that may fail for various reasons. + +The legacy users of exportfs_encode_fh(), namely, nfsd and +name_to_handle_at(2) syscall are ready to cope with the possibility +of failure to encode a file handle. + +There are a few other users of exportfs_encode_{fh,fid}() that +currently have a WARN_ON() assertion when ->encode_fh() fails. +Relax those assertions because they are wrong. + +The second linked bug report states commit 16aac5ad1fa9 ("ovl: support +encoding non-decodable file handles") in v6.6 as the regressing commit, +but this is not accurate. + +The aforementioned commit only increases the chances of the assertion +and allows triggering the assertion with the reproducer using overlayfs, +inotify and drop_caches. + +Triggering this assertion was always possible with other filesystems and +other reasons of ->encode_fh() failures and more particularly, it was +also possible with the exact same reproducer using overlayfs that is +mounted with options index=on,nfs_export=on also on kernels < v6.6. +Therefore, I am not listing the aforementioned commit as a Fixes commit. + +Backport hint: this patch will have a trivial conflict applying to +v6.6.y, and other trivial conflicts applying to stable kernels < v6.6. + +Reported-by: syzbot+ec07f6f5ce62b858579f@syzkaller.appspotmail.com +Tested-by: syzbot+ec07f6f5ce62b858579f@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-unionfs/671fd40c.050a0220.4735a.024f.GAE@google.com/ +Reported-by: Dmitry Safonov +Closes: https://lore.kernel.org/linux-fsdevel/CAGrbwDTLt6drB9eaUagnQVgdPBmhLfqqxAf3F+Juqy_o6oP8uw@mail.gmail.com/ +Cc: stable@vger.kernel.org +Signed-off-by: Amir Goldstein +Link: https://lore.kernel.org/r/20241219115301.465396-1-amir73il@gmail.com +Signed-off-by: Christian Brauner +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +--- + fs/notify/fdinfo.c | 4 +--- + fs/overlayfs/copy_up.c | 5 ++--- + 2 files changed, 3 insertions(+), 6 deletions(-) + +--- a/fs/notify/fdinfo.c ++++ b/fs/notify/fdinfo.c +@@ -51,10 +51,8 @@ static void show_mark_fhandle(struct seq + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_fid(inode, (struct fid *)f.handle.f_handle, &size); +- if ((ret == FILEID_INVALID) || (ret < 0)) { +- WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); ++ if ((ret == FILEID_INVALID) || (ret < 0)) + return; +- } + + f.handle.handle_type = ret; + f.handle.handle_bytes = size * sizeof(u32); +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -399,9 +399,8 @@ struct ovl_fh *ovl_encode_real_fh(struct + buflen = (dwords << 2); + + err = -EIO; +- if (WARN_ON(fh_type < 0) || +- WARN_ON(buflen > MAX_HANDLE_SZ) || +- WARN_ON(fh_type == FILEID_INVALID)) ++ if (fh_type < 0 || fh_type == FILEID_INVALID || ++ WARN_ON(buflen > MAX_HANDLE_SZ)) + goto out_err; + + fh->fb.version = OVL_FH_VERSION; diff --git a/queue-6.6/ovl-pass-realinode-to-ovl_encode_real_fh-instead-of-realdentry.patch b/queue-6.6/ovl-pass-realinode-to-ovl_encode_real_fh-instead-of-realdentry.patch new file mode 100644 index 0000000000..e551c7e666 --- /dev/null +++ b/queue-6.6/ovl-pass-realinode-to-ovl_encode_real_fh-instead-of-realdentry.patch @@ -0,0 +1,124 @@ +From 07aeefae7ff44d80524375253980b1bdee2396b0 Mon Sep 17 00:00:00 2001 +From: Amir Goldstein +Date: Sun, 5 Jan 2025 17:24:03 +0100 +Subject: ovl: pass realinode to ovl_encode_real_fh() instead of realdentry + +From: Amir Goldstein + +commit 07aeefae7ff44d80524375253980b1bdee2396b0 upstream. + +We want to be able to encode an fid from an inode with no alias. + +Signed-off-by: Amir Goldstein +Link: https://lore.kernel.org/r/20250105162404.357058-2-amir73il@gmail.com +Signed-off-by: Christian Brauner +Stable-dep-of: c45beebfde34 ("ovl: support encoding fid from inode with no alias") +Signed-off-by: Sasha Levin +[re-applied over v6.6.71 with conflict resolved] +Signed-off-by: Amir Goldstein +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/copy_up.c | 11 ++++++----- + fs/overlayfs/export.c | 5 +++-- + fs/overlayfs/namei.c | 4 ++-- + fs/overlayfs/overlayfs.h | 2 +- + 4 files changed, 12 insertions(+), 10 deletions(-) + +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -371,13 +371,13 @@ int ovl_set_attr(struct ovl_fs *ofs, str + return err; + } + +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + bool is_upper) + { + struct ovl_fh *fh; + int fh_type, dwords; + int buflen = MAX_HANDLE_SZ; +- uuid_t *uuid = &real->d_sb->s_uuid; ++ uuid_t *uuid = &realinode->i_sb->s_uuid; + int err; + + /* Make sure the real fid stays 32bit aligned */ +@@ -394,7 +394,8 @@ struct ovl_fh *ovl_encode_real_fh(struct + * the price or reconnecting the dentry. + */ + dwords = buflen >> 2; +- fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0); ++ fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid, ++ &dwords, NULL, 0); + buflen = (dwords << 2); + + err = -EIO; +@@ -438,7 +439,7 @@ int ovl_set_origin(struct ovl_fs *ofs, s + * up and a pure upper inode. + */ + if (ovl_can_decode_fh(lower->d_sb)) { +- fh = ovl_encode_real_fh(ofs, lower, false); ++ fh = ovl_encode_real_fh(ofs, d_inode(lower), false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + } +@@ -461,7 +462,7 @@ static int ovl_set_upper_fh(struct ovl_f + const struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, upper, true); ++ fh = ovl_encode_real_fh(ofs, d_inode(upper), true); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -228,6 +228,7 @@ static int ovl_check_encode_origin(struc + static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, + u32 *fid, int buflen) + { ++ struct inode *inode = d_inode(dentry); + struct ovl_fh *fh = NULL; + int err, enc_lower; + int len; +@@ -241,8 +242,8 @@ static int ovl_dentry_to_fid(struct ovl_ + goto fail; + + /* Encode an upper or lower file handle */ +- fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) : +- ovl_dentry_upper(dentry), !enc_lower); ++ fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) : ++ ovl_inode_upper(inode), !enc_lower); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +--- a/fs/overlayfs/namei.c ++++ b/fs/overlayfs/namei.c +@@ -523,7 +523,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, real, is_upper); ++ fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper); + err = PTR_ERR(fh); + if (IS_ERR(fh)) { + fh = NULL; +@@ -720,7 +720,7 @@ int ovl_get_index_name(struct ovl_fs *of + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, origin, false); ++ fh = ovl_encode_real_fh(ofs, d_inode(origin), false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -821,7 +821,7 @@ int ovl_copy_up_with_data(struct 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 dentry *real, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + bool is_upper); + int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, + struct dentry *upper); diff --git a/queue-6.6/ovl-support-encoding-fid-from-inode-with-no-alias.patch b/queue-6.6/ovl-support-encoding-fid-from-inode-with-no-alias.patch new file mode 100644 index 0000000000..bc6941466d --- /dev/null +++ b/queue-6.6/ovl-support-encoding-fid-from-inode-with-no-alias.patch @@ -0,0 +1,161 @@ +From c45beebfde34aa71afbc48b2c54cdda623515037 Mon Sep 17 00:00:00 2001 +From: Amir Goldstein +Date: Sun, 5 Jan 2025 17:24:04 +0100 +Subject: ovl: support encoding fid from inode with no alias + +From: Amir Goldstein + +commit c45beebfde34aa71afbc48b2c54cdda623515037 upstream. + +Dmitry Safonov reported that a WARN_ON() assertion can be trigered by +userspace when calling inotify_show_fdinfo() for an overlayfs watched +inode, whose dentry aliases were discarded with drop_caches. + +The WARN_ON() assertion in inotify_show_fdinfo() was removed, because +it is possible for encoding file handle to fail for other reason, but +the impact of failing to encode an overlayfs file handle goes beyond +this assertion. + +As shown in the LTP test case mentioned in the link below, failure to +encode an overlayfs file handle from a non-aliased inode also leads to +failure to report an fid with FAN_DELETE_SELF fanotify events. + +As Dmitry notes in his analyzis of the problem, ovl_encode_fh() fails +if it cannot find an alias for the inode, but this failure can be fixed. +ovl_encode_fh() seldom uses the alias and in the case of non-decodable +file handles, as is often the case with fanotify fid info, +ovl_encode_fh() never needs to use the alias to encode a file handle. + +Defer finding an alias until it is actually needed so ovl_encode_fh() +will not fail in the common case of FAN_DELETE_SELF fanotify events. + +Fixes: 16aac5ad1fa9 ("ovl: support encoding non-decodable file handles") +Reported-by: Dmitry Safonov +Closes: https://lore.kernel.org/linux-fsdevel/CAOQ4uxiie81voLZZi2zXS1BziXZCM24nXqPAxbu8kxXCUWdwOg@mail.gmail.com/ +Signed-off-by: Amir Goldstein +Link: https://lore.kernel.org/r/20250105162404.357058-3-amir73il@gmail.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/export.c | 46 +++++++++++++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 21 deletions(-) + +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -181,35 +181,37 @@ static int ovl_connect_layer(struct dent + * + * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. + */ +-static int ovl_check_encode_origin(struct dentry *dentry) ++static int ovl_check_encode_origin(struct inode *inode) + { +- struct ovl_fs *ofs = OVL_FS(dentry->d_sb); ++ struct ovl_fs *ofs = OVL_FS(inode->i_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_dentry_upper(dentry) && !decodable) ++ if (!ovl_inode_upper(inode) && !decodable) + return 1; + + /* Upper file handle for pure upper */ +- if (!ovl_dentry_lower(dentry)) ++ if (!ovl_inode_lower(inode)) + return 0; + + /* + * Root is never indexed, so if there's an upper layer, encode upper for + * root. + */ +- if (dentry == dentry->d_sb->s_root) ++ if (inode == d_inode(inode->i_sb->s_root)) + return 0; + + /* + * Upper decodable file handle for non-indexed upper. + */ +- if (ovl_dentry_upper(dentry) && decodable && +- !ovl_test_flag(OVL_INDEX, d_inode(dentry))) ++ if (ovl_inode_upper(inode) && decodable && ++ !ovl_test_flag(OVL_INDEX, inode)) + return 0; + + /* +@@ -218,17 +220,25 @@ static int ovl_check_encode_origin(struc + * ovl_connect_layer() will try to make origin's layer "connected" by + * copying up a "connectable" ancestor. + */ +- if (d_is_dir(dentry) && decodable) +- return ovl_connect_layer(dentry); ++ 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; + + /* Lower file handle for indexed and non-upper dir/non-dir */ + return 1; + } + +-static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, ++static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, + u32 *fid, int buflen) + { +- struct inode *inode = d_inode(dentry); + struct ovl_fh *fh = NULL; + int err, enc_lower; + int len; +@@ -237,7 +247,7 @@ static int ovl_dentry_to_fid(struct ovl_ + * 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(dentry); ++ err = enc_lower = ovl_check_encode_origin(inode); + if (enc_lower < 0) + goto fail; + +@@ -257,8 +267,8 @@ out: + return err; + + fail: +- pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n", +- dentry, err); ++ pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n", ++ inode->i_ino, err); + goto out; + } + +@@ -266,19 +276,13 @@ static int ovl_encode_fh(struct inode *i + 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; + +- dentry = d_find_any_alias(inode); +- if (!dentry) +- return FILEID_INVALID; +- +- bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); +- dput(dentry); ++ bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen); + if (bytes <= 0) + return FILEID_INVALID; + diff --git a/queue-6.6/series b/queue-6.6/series index 2e39acf5e2..84ee32a113 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -63,3 +63,6 @@ iio-imu-inv_icm42600-fix-spi-burst-write-not-supported.patch drm-amd-display-fix-out-of-bounds-access-in-dcn21_link_encoder_create.patch block-fix-uaf-for-flush-rq-while-iterating-tags.patch ocfs2-fix-deadlock-in-ocfs2_get_system_file_inode.patch +ovl-pass-realinode-to-ovl_encode_real_fh-instead-of-realdentry.patch +ovl-support-encoding-fid-from-inode-with-no-alias.patch +fs-relax-assertions-on-failure-to-encode-file-handles.patch