--- /dev/null
+From 974e3fe0ac61de85015bbe5a4990cf4127b304b2 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Thu, 19 Dec 2024 12:53:01 +0100
+Subject: fs: relax assertions on failure to encode file handles
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+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 <dima@arista.com>
+Closes: https://lore.kernel.org/linux-fsdevel/CAGrbwDTLt6drB9eaUagnQVgdPBmhLfqqxAf3F+Juqy_o6oP8uw@mail.gmail.com/
+Cc: stable@vger.kernel.org
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Link: https://lore.kernel.org/r/20241219115301.465396-1-amir73il@gmail.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
--- /dev/null
+From 07aeefae7ff44d80524375253980b1bdee2396b0 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Sun, 5 Jan 2025 17:24:03 +0100
+Subject: ovl: pass realinode to ovl_encode_real_fh() instead of realdentry
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+commit 07aeefae7ff44d80524375253980b1bdee2396b0 upstream.
+
+We want to be able to encode an fid from an inode with no alias.
+
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Link: https://lore.kernel.org/r/20250105162404.357058-2-amir73il@gmail.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Stable-dep-of: c45beebfde34 ("ovl: support encoding fid from inode with no alias")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+[re-applied over v6.6.71 with conflict resolved]
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
--- /dev/null
+From c45beebfde34aa71afbc48b2c54cdda623515037 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Sun, 5 Jan 2025 17:24:04 +0100
+Subject: ovl: support encoding fid from inode with no alias
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+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 <dima@arista.com>
+Closes: https://lore.kernel.org/linux-fsdevel/CAOQ4uxiie81voLZZi2zXS1BziXZCM24nXqPAxbu8kxXCUWdwOg@mail.gmail.com/
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Link: https://lore.kernel.org/r/20250105162404.357058-3-amir73il@gmail.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+
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