]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Aug 2026 09:58:58 +0000 (11:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Aug 2026 09:58:58 +0000 (11:58 +0200)
added patches:
binfmt_misc-don-t-leak-the-user-namespace-when-the-mount-fails.patch
binfmt_misc-don-t-let-an-f-entry-pin-its-own-instance.patch
binfmt_misc-reject-a-flag-character-as-the-field-delimiter.patch
binfmt_misc-restore-write-access-when-removing-an-entry.patch
binfmt_misc-use-exe_file_deny_write_access-for-the-interpreter-clone.patch

queue-7.1/binfmt_misc-don-t-leak-the-user-namespace-when-the-mount-fails.patch [new file with mode: 0644]
queue-7.1/binfmt_misc-don-t-let-an-f-entry-pin-its-own-instance.patch [new file with mode: 0644]
queue-7.1/binfmt_misc-reject-a-flag-character-as-the-field-delimiter.patch [new file with mode: 0644]
queue-7.1/binfmt_misc-restore-write-access-when-removing-an-entry.patch [new file with mode: 0644]
queue-7.1/binfmt_misc-use-exe_file_deny_write_access-for-the-interpreter-clone.patch [new file with mode: 0644]
queue-7.1/series

diff --git a/queue-7.1/binfmt_misc-don-t-leak-the-user-namespace-when-the-mount-fails.patch b/queue-7.1/binfmt_misc-don-t-leak-the-user-namespace-when-the-mount-fails.patch
new file mode 100644 (file)
index 0000000..6b1373a
--- /dev/null
@@ -0,0 +1,118 @@
+From b8206f516fe7cbe785cf44bf09c17c438d7c3cad Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Tue, 28 Jul 2026 15:48:10 +0200
+Subject: binfmt_misc: don't leak the user namespace when the mount fails
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit b8206f516fe7cbe785cf44bf09c17c438d7c3cad upstream.
+
+bm_get_tree() takes a reference to the user namespace and hands it to
+get_tree_keyed() as the sget key. sget_fc() moves that reference into
+sb->s_fs_info and clears fc->s_fs_info, so from that point on the
+superblock owns it and bm_free() doesn't see it anymore.
+
+The superblock drops it in ->put_super(). But generic_shutdown_super()
+only calls ->put_super() from inside the if (sb->s_root) branch, so
+nothing releases it when bm_fill_super() fails:
+
+- The kzalloc_obj() failure leaves s_root NULL and the whole branch is
+  skipped.
+
+- A simple_fill_super() failure in the file loop leaves s_root set, but
+  s_op still points at simple_super_operations, which has no
+  ->put_super(). bm_fill_super() installs s_ops only once
+  simple_fill_super() returned success, and installing it earlier
+  wouldn't help either because simple_fill_super() overwrites s_op.
+
+Either way vfs_get_super() calls deactivate_locked_super() and the
+reference is gone for good. binfmt_misc mounts are available in a user
+namespace and both the inode and the dentry cache are SLAB_ACCOUNT, so
+an unprivileged caller under a tight memory cgroup can fail
+simple_fill_super() on demand and leak one user namespace per attempt.
+
+Drop the reference in ->kill_sb() instead, which runs unconditionally,
+the same way nfsd and rpc_pipefs release their keyed s_fs_info.
+
+That also stops ->put_super() from clearing s_fs_info while the
+superblock is still on @fs_supers. generic_shutdown_super() leaves it
+there on purpose so that sget_fc() keeps finding it until kill_sb() has
+run, but a NULL s_fs_info makes test_keyed_super() miss it, so a
+concurrent mount for the same user namespace skips the grab_super()
+wait and creates a second superblock for a namespace that is still
+being torn down.
+
+Link: https://patch.msgid.link/20260728-work-binfmt_misc-usernsleak-v1-1-dbd8d5e626e7@kernel.org
+Fixes: 21ca59b365c0 ("binfmt_misc: enable sandboxed mounts")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_misc.c |   32 +++++++++++++++-----------------
+ 1 file changed, 15 insertions(+), 17 deletions(-)
+
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -921,18 +921,9 @@ static const struct file_operations bm_s
+ /* Superblock handling */
+-static void bm_put_super(struct super_block *sb)
+-{
+-      struct user_namespace *user_ns = sb->s_fs_info;
+-
+-      sb->s_fs_info = NULL;
+-      put_user_ns(user_ns);
+-}
+-
+ static const struct super_operations s_ops = {
+       .statfs         = simple_statfs,
+       .evict_inode    = bm_evict_inode,
+-      .put_super      = bm_put_super,
+ };
+ static int bm_fill_super(struct super_block *sb, struct fs_context *fc)
+@@ -990,13 +981,12 @@ static int bm_fill_super(struct super_bl
+       /*
+        * When the binfmt_misc superblock for this userns is shutdown
+        * ->enabled might have been set to false and we don't reinitialize
+-       * ->enabled again in put_super() as someone might already be mounting
+-       * binfmt_misc again. It also would be pointless since by the time
+-       * ->put_super() is called we know that the binary type list for this
+-       * bintfmt_misc mount is empty making load_misc_binary() return
+-       * -ENOEXEC independent of whether ->enabled is true. Instead, if
+-       * someone mounts binfmt_misc for the first time or again we simply
+-       * reset ->enabled to true.
++       * ->enabled again during shutdown as someone might already be mounting
++       * binfmt_misc again. It also would be pointless since by then we know
++       * that the binary type list for this binfmt_misc mount is empty making
++       * load_misc_binary() return -ENOEXEC independent of whether ->enabled
++       * is true. Instead, if someone mounts binfmt_misc for the first time or
++       * again we simply reset ->enabled to true.
+        */
+       misc->enabled = true;
+@@ -1022,6 +1012,14 @@ static const struct fs_context_operation
+       .get_tree       = bm_get_tree,
+ };
++static void bm_kill_sb(struct super_block *sb)
++{
++      struct user_namespace *user_ns = sb->s_fs_info;
++
++      kill_anon_super(sb);
++      put_user_ns(user_ns);
++}
++
+ static int bm_init_fs_context(struct fs_context *fc)
+ {
+       fc->ops = &bm_context_ops;
+@@ -1038,7 +1036,7 @@ static struct file_system_type bm_fs_typ
+       .name           = "binfmt_misc",
+       .init_fs_context = bm_init_fs_context,
+       .fs_flags       = FS_USERNS_MOUNT,
+-      .kill_sb        = kill_anon_super,
++      .kill_sb        = bm_kill_sb,
+ };
+ MODULE_ALIAS_FS("binfmt_misc");
diff --git a/queue-7.1/binfmt_misc-don-t-let-an-f-entry-pin-its-own-instance.patch b/queue-7.1/binfmt_misc-don-t-let-an-f-entry-pin-its-own-instance.patch
new file mode 100644 (file)
index 0000000..c3ded23
--- /dev/null
@@ -0,0 +1,71 @@
+From 79055d82772b9584f259b747fe40ff56a076678d Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Tue, 28 Jul 2026 14:26:32 +0200
+Subject: binfmt_misc: don't let an 'F' entry pin its own instance
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit 79055d82772b9584f259b747fe40ff56a076678d upstream.
+
+An entry registered with 'F' opens its interpreter at registration time
+and holds that file until the entry is freed. Any entry nobody removes
+by hand only gets closed once the binfmt_misc superblock is shut down.
+If the interpreter lives on a mount that keeps that superblock alive the
+two pin each other:
+
+    binfmt_misc sb -> inode -> entry -> interp_file -> vfsmount -> binfmt_misc sb
+
+TL;DR the file is never closed. Once the mount namespace is gone there
+is nothing left to unregister through either.
+
+There are two ways to trigger this bug:
+
+- Point the interpreter at the instance itself. Its files are regular
+  files owned by the mounter and both bm_get_inode() and
+  simple_fill_super() leave i_op at empty_iops. So notify_change() falls
+  back to simple_setattr() and chmod +x works. We never set SB_I_NOEXEC
+  and so open_exec() accepts it.
+
+- Use the instance as an overlayfs lower layer. The overlay superblock
+  holds a clone_private_mount() of every layer until it is destroyed and
+  that clone is in no namespace. So umount_tree() never reaches it.
+
+That's a DoS. And it isn't only the superblock that leaks. It pins the
+user namespace it was mounted in, so every iteration permanently eats
+one of the caller's user namespace charges.
+
+So let's just do the sane thing. SB_I_NOEXEC makes open_exec() fail on
+the instance's own files and s_stack_depth makes overlayfs reject the
+layer before it ever takes a clone. That also covers the ecryptfs and
+fuse passthrough variants. What 'F' promises is unchanged.
+
+The stable tag is narrower than the Fixes tags on purpose. Before
+sandboxed mounts this needed global root against the single instance
+everyone shares, and the change doesn't apply to those trees anyway.
+
+Note that SB_I_NODEV is implicitly raised for userns mounts but raise it
+explicitly here as well.
+
+Link: https://patch.msgid.link/20260728-work-binfmt_misc-selfpin-v1-1-74df5daeca5b@kernel.org
+Fixes: 948b701a607f ("binfmt_misc: add persistent opened binary handler for containers")
+Fixes: 21ca59b365c0 ("binfmt_misc: enable sandboxed mounts")
+Cc: stable@vger.kernel.org # v6.7+
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_misc.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -949,6 +949,10 @@ static int bm_fill_super(struct super_bl
+       if (WARN_ON(user_ns != current_user_ns()))
+               return -EINVAL;
++      /* Never exec off this instance and never let anything stack on it. */
++      sb->s_iflags |= SB_I_NOEXEC | SB_I_NODEV;
++      sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
++
+       /*
+        * Lazily allocate a new binfmt_misc instance for this namespace, i.e.
+        * do it here during the first mount of binfmt_misc. We don't need to
diff --git a/queue-7.1/binfmt_misc-reject-a-flag-character-as-the-field-delimiter.patch b/queue-7.1/binfmt_misc-reject-a-flag-character-as-the-field-delimiter.patch
new file mode 100644 (file)
index 0000000..a0665ab
--- /dev/null
@@ -0,0 +1,65 @@
+From 8e85d50ba1117fd446bf9a250bd8a97d48384bdc Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Fri, 10 Jul 2026 11:33:04 +0200
+Subject: binfmt_misc: reject a flag character as the field delimiter
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit 8e85d50ba1117fd446bf9a250bd8a97d48384bdc upstream.
+
+The registration string starts with a user chosen delimiter that
+separates the individual fields. So that the field parsers terminate
+even on a truncated string create_entry() pads the buffer with that
+same delimiter:
+
+       memset(buf + count, del, 8);
+
+Most fields are scanned for the delimiter with strchr()/scanarg() and
+happily stop on the padding. The flags field is different: instead of
+scanning for the delimiter check_special_flags() consumes the flag
+characters 'P', 'O', 'C' and 'F' and stops at the first byte that is
+none of them, relying on the trailing delimiter to end the scan.
+
+If the delimiter is itself a flag character the padding no longer acts
+as a terminator. The scan swallows all eight padding bytes and keeps
+reading past the end of the allocation until it hits a byte that is
+not a flag character. For example registering
+
+       PaPEPPxPPiP
+
+with 'P' as the delimiter (name "a", type extension, magic "x",
+interpreter "i", empty flags) leaves the flag scan running off the end
+of the buffer. The registration is rejected in the end because the
+parser does not stop exactly at buf + count, but only after the out of
+bounds read has already happened. With an unlucky allocation layout the
+scan can walk into an unmapped page; under KASAN it is reported as a
+slab out of bounds read. binfmt_misc mounts are available to
+unprivileged users in a user namespace so the read is reachable without
+privileges.
+
+Reject a delimiter that is one of the flag characters up front. Such a
+registration was always rejected anyway, only after the out of bounds
+read, so no valid registration string changes meaning.
+
+Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-3-a162f7cb58d6@kernel.org
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_misc.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -384,6 +384,10 @@ static Node *create_entry(const char __u
+       pr_debug("register: delim: %#x {%c}\n", del, del);
++      /* A flag-char delimiter runs the flag scan off the buffer. */
++      if (del == 'P' || del == 'O' || del == 'C' || del == 'F')
++              goto einval;
++
+       /* Pad the buffer with the delim to simplify parsing below. */
+       memset(buf + count, del, 8);
diff --git a/queue-7.1/binfmt_misc-restore-write-access-when-removing-an-entry.patch b/queue-7.1/binfmt_misc-restore-write-access-when-removing-an-entry.patch
new file mode 100644 (file)
index 0000000..e88d0a0
--- /dev/null
@@ -0,0 +1,48 @@
+From db1856ea9196cf6e015d12199a34c0b9313c7bfa Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Fri, 10 Jul 2026 11:33:02 +0200
+Subject: binfmt_misc: restore write access when removing an entry
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit db1856ea9196cf6e015d12199a34c0b9313c7bfa upstream.
+
+Registering an entry with the MISC_FMT_OPEN_FILE flag opens the
+interpreter via open_exec() which denies write access to it for as
+long as the entry exists. Removing the entry closes the interpreter
+file via filp_close() but never restores write access, leaving the
+inode's i_writecount permanently negative. Opening the interpreter
+for writing keeps failing with ETXTBSY long after the entry is gone
+until the inode is evicted from the inode cache.
+
+Commit 90f601b497d7 ("binfmt_misc: restore write access before
+closing files opened by open_exec()") fixed the same imbalance in the
+error path of bm_register_write() but the actual removal path has
+been leaking the write denial since the introduction of the flag.
+
+Restore write access in put_binfmt_handler() before closing the
+interpreter file.
+
+Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-1-a162f7cb58d6@kernel.org
+Fixes: 948b701a607f ("binfmt_misc: add persistent opened binary handler for containers")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_misc.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -162,8 +162,10 @@ static Node *get_binfmt_handler(struct b
+ static void put_binfmt_handler(Node *e)
+ {
+       if (refcount_dec_and_test(&e->users)) {
+-              if (e->flags & MISC_FMT_OPEN_FILE)
++              if (e->flags & MISC_FMT_OPEN_FILE) {
++                      exe_file_allow_write_access(e->interp_file);
+                       filp_close(e->interp_file, NULL);
++              }
+               kfree(e);
+       }
+ }
diff --git a/queue-7.1/binfmt_misc-use-exe_file_deny_write_access-for-the-interpreter-clone.patch b/queue-7.1/binfmt_misc-use-exe_file_deny_write_access-for-the-interpreter-clone.patch
new file mode 100644 (file)
index 0000000..40b029e
--- /dev/null
@@ -0,0 +1,59 @@
+From fa5990ca8fd917003e526036bcc50413edb9722c Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Fri, 10 Jul 2026 11:33:03 +0200
+Subject: binfmt_misc: use exe_file_deny_write_access() for the interpreter clone
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit fa5990ca8fd917003e526036bcc50413edb9722c upstream.
+
+For MISC_FMT_OPEN_FILE entries load_misc_binary() clones the
+registered interpreter file and denies write access to the clone via
+plain deny_write_access(). The clone is installed as
+bprm->interpreter and later released by the exec machinery through
+exe_file_allow_write_access() which skips the i_writecount increment
+for files with FMODE_FSNOTIFY_HSM set.
+
+The deny and allow side can therefore come to different conclusions
+when pre-content watches are in play: if a pre-content watch is added
+to the interpreter after registration every subsequent exec through
+that entry takes a write denial on the clone that is never paired
+with a write allowance, driving the interpreter inode's i_writecount
+further down with each exec and leaving the interpreter unwritable
+even after the entry and all its users are gone.
+
+Take the write denial via exe_file_deny_write_access() so both sides
+of the pairing base their decision on the same file mode, and
+propagate failure instead of silently ignoring it: an interpreter
+that is concurrently open for writing now fails the exec with
+ETXTBSY, exactly like an interpreter freshly opened via open_exec()
+would.
+
+Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-2-a162f7cb58d6@kernel.org
+Fixes: 0357ef03c94e ("fs: don't block write during exec on pre-content watched files")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/binfmt_misc.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -249,8 +249,14 @@ static int load_misc_binary(struct linux
+       if (fmt->flags & MISC_FMT_OPEN_FILE) {
+               interp_file = file_clone_open(fmt->interp_file);
+-              if (!IS_ERR(interp_file))
+-                      deny_write_access(interp_file);
++              if (!IS_ERR(interp_file)) {
++                      int err = exe_file_deny_write_access(interp_file);
++
++                      if (err) {
++                              fput(interp_file);
++                              interp_file = ERR_PTR(err);
++                      }
++              }
+       } else {
+               interp_file = open_exec(fmt->interpreter);
+       }
index 9cc1cfa6211ba29c8637a095d257ffc4932ca5a7..a7e10e7f06aeebbf07534104dbdbe51ff6c37fe3 100644 (file)
@@ -285,3 +285,8 @@ tipc-avoid-use-after-free-in-poll-trace-queue-dumps.patch
 x86-cpu-amd-carve-out-a-zen5-models-range.patch
 wifi-mac80211-fix-tid_tx-use-after-free-on-ba-session-stop.patch
 wifi-mwifiex-use-the-subframe-length-when-parsing-a-msdu-tdls-frames.patch
+binfmt_misc-restore-write-access-when-removing-an-entry.patch
+binfmt_misc-use-exe_file_deny_write_access-for-the-interpreter-clone.patch
+binfmt_misc-reject-a-flag-character-as-the-field-delimiter.patch
+binfmt_misc-don-t-let-an-f-entry-pin-its-own-instance.patch
+binfmt_misc-don-t-leak-the-user-namespace-when-the-mount-fails.patch