]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Feb 2026 10:08:15 +0000 (11:08 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Feb 2026 10:08:15 +0000 (11:08 +0100)
added patches:
driver-core-enforce-device_lock-for-driver_match_device.patch
ksmbd-fix-infinite-loop-caused-by-next_smb2_rcv_hdr_off-reset-in-error-paths.patch
series
smb-client-split-cached_fid-bitfields-to-avoid-shared-byte-rmw-races.patch
smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch

queue-6.12/driver-core-enforce-device_lock-for-driver_match_device.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-infinite-loop-caused-by-next_smb2_rcv_hdr_off-reset-in-error-paths.patch [new file with mode: 0644]
queue-6.12/series [new file with mode: 0644]
queue-6.12/smb-client-split-cached_fid-bitfields-to-avoid-shared-byte-rmw-races.patch [new file with mode: 0644]
queue-6.12/smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch [new file with mode: 0644]

diff --git a/queue-6.12/driver-core-enforce-device_lock-for-driver_match_device.patch b/queue-6.12/driver-core-enforce-device_lock-for-driver_match_device.patch
new file mode 100644 (file)
index 0000000..02694ef
--- /dev/null
@@ -0,0 +1,88 @@
+From dc23806a7c47ec5f1293aba407fb69519f976ee0 Mon Sep 17 00:00:00 2001
+From: Gui-Dong Han <hanguidong02@gmail.com>
+Date: Wed, 14 Jan 2026 00:28:43 +0800
+Subject: driver core: enforce device_lock for driver_match_device()
+
+From: Gui-Dong Han <hanguidong02@gmail.com>
+
+commit dc23806a7c47ec5f1293aba407fb69519f976ee0 upstream.
+
+Currently, driver_match_device() is called from three sites. One site
+(__device_attach_driver) holds device_lock(dev), but the other two
+(bind_store and __driver_attach) do not. This inconsistency means that
+bus match() callbacks are not guaranteed to be called with the lock
+held.
+
+Fix this by introducing driver_match_device_locked(), which guarantees
+holding the device lock using a scoped guard. Replace the unlocked calls
+in bind_store() and __driver_attach() with this new helper. Also add a
+lock assertion to driver_match_device() to enforce this guarantee.
+
+This consistency also fixes a known race condition. The driver_override
+implementation relies on the device_lock, so the missing lock led to the
+use-after-free (UAF) reported in Bugzilla for buses using this field.
+
+Stress testing the two newly locked paths for 24 hours with
+CONFIG_PROVE_LOCKING and CONFIG_LOCKDEP enabled showed no UAF recurrence
+and no lockdep warnings.
+
+Cc: stable@vger.kernel.org
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789
+Suggested-by: Qiu-ji Chen <chenqiuji666@gmail.com>
+Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com>
+Fixes: 49b420a13ff9 ("driver core: check bus->match without holding device lock")
+Reviewed-by: Danilo Krummrich <dakr@kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
+Link: https://patch.msgid.link/20260113162843.12712-1-hanguidong02@gmail.com
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/base.h |    9 +++++++++
+ drivers/base/bus.c  |    2 +-
+ drivers/base/dd.c   |    2 +-
+ 3 files changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -165,9 +165,18 @@ void device_set_deferred_probe_reason(co
+ static inline int driver_match_device(const struct device_driver *drv,
+                                     struct device *dev)
+ {
++      device_lock_assert(dev);
++
+       return drv->bus->match ? drv->bus->match(dev, drv) : 1;
+ }
++static inline int driver_match_device_locked(const struct device_driver *drv,
++                                           struct device *dev)
++{
++      guard(device)(dev);
++      return driver_match_device(drv, dev);
++}
++
+ static inline void dev_sync_state(struct device *dev)
+ {
+       if (dev->bus->sync_state)
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -263,7 +263,7 @@ static ssize_t bind_store(struct device_
+       int err = -ENODEV;
+       dev = bus_find_device_by_name(bus, NULL, buf);
+-      if (dev && driver_match_device(drv, dev)) {
++      if (dev && driver_match_device_locked(drv, dev)) {
+               err = device_driver_attach(drv, dev);
+               if (!err) {
+                       /* success */
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -1168,7 +1168,7 @@ static int __driver_attach(struct device
+        * is an error.
+        */
+-      ret = driver_match_device(drv, dev);
++      ret = driver_match_device_locked(drv, dev);
+       if (ret == 0) {
+               /* no match */
+               return 0;
diff --git a/queue-6.12/ksmbd-fix-infinite-loop-caused-by-next_smb2_rcv_hdr_off-reset-in-error-paths.patch b/queue-6.12/ksmbd-fix-infinite-loop-caused-by-next_smb2_rcv_hdr_off-reset-in-error-paths.patch
new file mode 100644 (file)
index 0000000..10d4439
--- /dev/null
@@ -0,0 +1,62 @@
+From 010eb01ce23b34b50531448b0da391c7f05a72af Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Sat, 24 Jan 2026 10:55:46 +0900
+Subject: ksmbd: fix infinite loop caused by next_smb2_rcv_hdr_off reset in error paths
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 010eb01ce23b34b50531448b0da391c7f05a72af upstream.
+
+The problem occurs when a signed request fails smb2 signature verification
+check. In __process_request(), if check_sign_req() returns an error,
+set_smb2_rsp_status(work, STATUS_ACCESS_DENIED) is called.
+set_smb2_rsp_status() set work->next_smb2_rcv_hdr_off as zero. By resetting
+next_smb2_rcv_hdr_off to zero, the pointer to the next command in the chain
+is lost. Consequently, is_chained_smb2_message() continues to point to
+the same request header instead of advancing. If the header's NextCommand
+field is non-zero, the function returns true, causing __handle_ksmbd_work()
+to repeatedly process the same failed request in an infinite loop.
+This results in the kernel log being flooded with "bad smb2 signature"
+messages and high CPU usage.
+
+This patch fixes the issue by changing the return value from
+SERVER_HANDLER_CONTINUE to SERVER_HANDLER_ABORT. This ensures that
+the processing loop terminates immediately rather than attempting to
+continue from an invalidated offset.
+
+Reported-by: tianshuo han <hantianshuo233@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/server.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/smb/server/server.c
++++ b/fs/smb/server/server.c
+@@ -126,21 +126,21 @@ static int __process_request(struct ksmb
+ andx_again:
+       if (command >= conn->max_cmds) {
+               conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
+-              return SERVER_HANDLER_CONTINUE;
++              return SERVER_HANDLER_ABORT;
+       }
+       cmds = &conn->cmds[command];
+       if (!cmds->proc) {
+               ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
+               conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
+-              return SERVER_HANDLER_CONTINUE;
++              return SERVER_HANDLER_ABORT;
+       }
+       if (work->sess && conn->ops->is_sign_req(work, command)) {
+               ret = conn->ops->check_sign_req(work);
+               if (!ret) {
+                       conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
+-                      return SERVER_HANDLER_CONTINUE;
++                      return SERVER_HANDLER_ABORT;
+               }
+       }
diff --git a/queue-6.12/series b/queue-6.12/series
new file mode 100644 (file)
index 0000000..1f1a145
--- /dev/null
@@ -0,0 +1,4 @@
+smb-client-split-cached_fid-bitfields-to-avoid-shared-byte-rmw-races.patch
+ksmbd-fix-infinite-loop-caused-by-next_smb2_rcv_hdr_off-reset-in-error-paths.patch
+smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch
+driver-core-enforce-device_lock-for-driver_match_device.patch
diff --git a/queue-6.12/smb-client-split-cached_fid-bitfields-to-avoid-shared-byte-rmw-races.patch b/queue-6.12/smb-client-split-cached_fid-bitfields-to-avoid-shared-byte-rmw-races.patch
new file mode 100644 (file)
index 0000000..5f0dd97
--- /dev/null
@@ -0,0 +1,52 @@
+From ec306600d5ba7148c9dbf8f5a8f1f5c1a044a241 Mon Sep 17 00:00:00 2001
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+Date: Tue, 27 Jan 2026 13:01:28 -0300
+Subject: smb: client: split cached_fid bitfields to avoid shared-byte RMW races
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+
+commit ec306600d5ba7148c9dbf8f5a8f1f5c1a044a241 upstream.
+
+is_open, has_lease and on_list are stored in the same bitfield byte in
+struct cached_fid but are updated in different code paths that may run
+concurrently. Bitfield assignments generate byte read–modify–write
+operations (e.g. `orb $mask, addr` on x86_64), so updating one flag can
+restore stale values of the others.
+
+A possible interleaving is:
+    CPU1: load old byte (has_lease=1, on_list=1)
+    CPU2: clear both flags (store 0)
+    CPU1: RMW store (old | IS_OPEN) -> reintroduces cleared bits
+
+To avoid this class of races, convert these flags to separate bool
+fields.
+
+Cc: stable@vger.kernel.org
+Fixes: ebe98f1447bbc ("cifs: enable caching of directories for which a lease is held")
+Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/cached_dir.h |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/smb/client/cached_dir.h
++++ b/fs/smb/client/cached_dir.h
+@@ -34,10 +34,10 @@ struct cached_fid {
+       struct list_head entry;
+       struct cached_fids *cfids;
+       const char *path;
+-      bool has_lease:1;
+-      bool is_open:1;
+-      bool on_list:1;
+-      bool file_all_info_is_valid:1;
++      bool has_lease;
++      bool is_open;
++      bool on_list;
++      bool file_all_info_is_valid;
+       unsigned long time; /* jiffies of when lease was taken */
+       struct kref refcount;
+       struct cifs_fid fid;
diff --git a/queue-6.12/smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch b/queue-6.12/smb-server-fix-leak-of-active_num_conn-in-ksmbd_tcp_new_connection.patch
new file mode 100644 (file)
index 0000000..1fb8632
--- /dev/null
@@ -0,0 +1,44 @@
+From 77ffbcac4e569566d0092d5f22627dfc0896b553 Mon Sep 17 00:00:00 2001
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+Date: Wed, 4 Feb 2026 20:06:43 -0300
+Subject: smb: server: fix leak of active_num_conn in ksmbd_tcp_new_connection()
+
+From: Henrique Carvalho <henrique.carvalho@suse.com>
+
+commit 77ffbcac4e569566d0092d5f22627dfc0896b553 upstream.
+
+On kthread_run() failure in ksmbd_tcp_new_connection(), the transport is
+freed via free_transport(), which does not decrement active_num_conn,
+leaking this counter.
+
+Replace free_transport() with ksmbd_tcp_disconnect().
+
+Fixes: 0d0d4680db22e ("ksmbd: add max connections parameter")
+Cc: stable@vger.kernel.org
+Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/transport_tcp.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/smb/server/transport_tcp.c
++++ b/fs/smb/server/transport_tcp.c
+@@ -41,6 +41,7 @@ static const struct ksmbd_transport_ops
+ static void tcp_stop_kthread(struct task_struct *kthread);
+ static struct interface *alloc_iface(char *ifname);
++static void ksmbd_tcp_disconnect(struct ksmbd_transport *t);
+ #define KSMBD_TRANS(t)        (&(t)->transport)
+ #define TCP_TRANS(t)  ((struct tcp_transport *)container_of(t, \
+@@ -219,7 +220,7 @@ static int ksmbd_tcp_new_connection(stru
+       if (IS_ERR(handler)) {
+               pr_err("cannot start conn thread\n");
+               rc = PTR_ERR(handler);
+-              free_transport(t);
++              ksmbd_tcp_disconnect(KSMBD_TRANS(t));
+       }
+       return rc;