]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jan 2025 11:35:20 +0000 (12:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Jan 2025 11:35:20 +0000 (12:35 +0100)
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

queue-6.6/fs-relax-assertions-on-failure-to-encode-file-handles.patch [new file with mode: 0644]
queue-6.6/ovl-pass-realinode-to-ovl_encode_real_fh-instead-of-realdentry.patch [new file with mode: 0644]
queue-6.6/ovl-support-encoding-fid-from-inode-with-no-alias.patch [new file with mode: 0644]
queue-6.6/series

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 (file)
index 0000000..23b2244
--- /dev/null
@@ -0,0 +1,81 @@
+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;
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 (file)
index 0000000..e551c7e
--- /dev/null
@@ -0,0 +1,124 @@
+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);
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 (file)
index 0000000..bc69414
--- /dev/null
@@ -0,0 +1,161 @@
+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;
index 2e39acf5e2fc3b930db91f10d84108dcb7d05f3f..84ee32a113f7841404dd7cbeb3b6c9738e9b381d 100644 (file)
@@ -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