]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Oct 2025 09:17:36 +0000 (11:17 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Oct 2025 09:17:36 +0000 (11:17 +0200)
added patches:
dm-fix-null-pointer-dereference-in-__dm_suspend.patch
dm-fix-queue-start-stop-imbalance-under-suspend-load-resume-races.patch
ext4-fix-checks-for-orphan-inodes.patch
ksmbd-add-max-ip-connections-parameter.patch
ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch
ksmbd-fix-race-condition-in-rpc-handle-list-access.patch
loongarch-automatically-disable-kaslr-if-boot-from-kexec_file.patch

queue-6.12/dm-fix-null-pointer-dereference-in-__dm_suspend.patch [new file with mode: 0644]
queue-6.12/dm-fix-queue-start-stop-imbalance-under-suspend-load-resume-races.patch [new file with mode: 0644]
queue-6.12/ext4-fix-checks-for-orphan-inodes.patch [new file with mode: 0644]
queue-6.12/ksmbd-add-max-ip-connections-parameter.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch [new file with mode: 0644]
queue-6.12/ksmbd-fix-race-condition-in-rpc-handle-list-access.patch [new file with mode: 0644]
queue-6.12/loongarch-automatically-disable-kaslr-if-boot-from-kexec_file.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/dm-fix-null-pointer-dereference-in-__dm_suspend.patch b/queue-6.12/dm-fix-null-pointer-dereference-in-__dm_suspend.patch
new file mode 100644 (file)
index 0000000..c32871f
--- /dev/null
@@ -0,0 +1,93 @@
+From 8d33a030c566e1f105cd5bf27f37940b6367f3be Mon Sep 17 00:00:00 2001
+From: Zheng Qixing <zhengqixing@huawei.com>
+Date: Tue, 26 Aug 2025 15:42:04 +0800
+Subject: dm: fix NULL pointer dereference in __dm_suspend()
+
+From: Zheng Qixing <zhengqixing@huawei.com>
+
+commit 8d33a030c566e1f105cd5bf27f37940b6367f3be upstream.
+
+There is a race condition between dm device suspend and table load that
+can lead to null pointer dereference. The issue occurs when suspend is
+invoked before table load completes:
+
+BUG: kernel NULL pointer dereference, address: 0000000000000054
+Oops: 0000 [#1] PREEMPT SMP PTI
+CPU: 6 PID: 6798 Comm: dmsetup Not tainted 6.6.0-g7e52f5f0ca9b #62
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014
+RIP: 0010:blk_mq_wait_quiesce_done+0x0/0x50
+Call Trace:
+  <TASK>
+  blk_mq_quiesce_queue+0x2c/0x50
+  dm_stop_queue+0xd/0x20
+  __dm_suspend+0x130/0x330
+  dm_suspend+0x11a/0x180
+  dev_suspend+0x27e/0x560
+  ctl_ioctl+0x4cf/0x850
+  dm_ctl_ioctl+0xd/0x20
+  vfs_ioctl+0x1d/0x50
+  __se_sys_ioctl+0x9b/0xc0
+  __x64_sys_ioctl+0x19/0x30
+  x64_sys_call+0x2c4a/0x4620
+  do_syscall_64+0x9e/0x1b0
+
+The issue can be triggered as below:
+
+T1                                             T2
+dm_suspend                                     table_load
+__dm_suspend                                   dm_setup_md_queue
+                                               dm_mq_init_request_queue
+                                               blk_mq_init_allocated_queue
+                                               => q->mq_ops = set->ops; (1)
+dm_stop_queue / dm_wait_for_completion
+=> q->tag_set NULL pointer!    (2)
+                                               => q->tag_set = set; (3)
+
+Fix this by checking if a valid table (map) exists before performing
+request-based suspend and waiting for target I/O. When map is NULL,
+skip these table-dependent suspend steps.
+
+Even when map is NULL, no I/O can reach any target because there is
+no table loaded; I/O submitted in this state will fail early in the
+DM layer. Skipping the table-dependent suspend logic in this case
+is safe and avoids NULL pointer dereferences.
+
+Fixes: c4576aed8d85 ("dm: fix request-based dm's use of dm_wait_for_completion")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -2918,7 +2918,7 @@ static int __dm_suspend(struct mapped_de
+ {
+       bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
+       bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
+-      int r;
++      int r = 0;
+       lockdep_assert_held(&md->suspend_lock);
+@@ -2970,7 +2970,7 @@ static int __dm_suspend(struct mapped_de
+        * Stop md->queue before flushing md->wq in case request-based
+        * dm defers requests to md->wq from md->queue.
+        */
+-      if (dm_request_based(md)) {
++      if (map && dm_request_based(md)) {
+               dm_stop_queue(md->queue);
+               set_bit(DMF_QUEUE_STOPPED, &md->flags);
+       }
+@@ -2982,7 +2982,8 @@ static int __dm_suspend(struct mapped_de
+        * We call dm_wait_for_completion to wait for all existing requests
+        * to finish.
+        */
+-      r = dm_wait_for_completion(md, task_state);
++      if (map)
++              r = dm_wait_for_completion(md, task_state);
+       if (!r)
+               set_bit(dmf_suspended_flag, &md->flags);
diff --git a/queue-6.12/dm-fix-queue-start-stop-imbalance-under-suspend-load-resume-races.patch b/queue-6.12/dm-fix-queue-start-stop-imbalance-under-suspend-load-resume-races.patch
new file mode 100644 (file)
index 0000000..488622c
--- /dev/null
@@ -0,0 +1,82 @@
+From 7f597c2cdb9d3263a6fce07c4fc0a9eaa8e8fc43 Mon Sep 17 00:00:00 2001
+From: Zheng Qixing <zhengqixing@huawei.com>
+Date: Tue, 26 Aug 2025 15:42:03 +0800
+Subject: dm: fix queue start/stop imbalance under suspend/load/resume races
+
+From: Zheng Qixing <zhengqixing@huawei.com>
+
+commit 7f597c2cdb9d3263a6fce07c4fc0a9eaa8e8fc43 upstream.
+
+When suspend and load run concurrently, before q->mq_ops is set in
+blk_mq_init_allocated_queue(), __dm_suspend() skip dm_stop_queue(). As a
+result, the queue's quiesce depth is not incremented.
+
+Later, once table load has finished and __dm_resume() runs, which triggers
+q->quiesce_depth ==0 warning in blk_mq_unquiesce_queue():
+Call Trace:
+ <TASK>
+ dm_start_queue+0x16/0x20 [dm_mod]
+ __dm_resume+0xac/0xb0 [dm_mod]
+ dm_resume+0x12d/0x150 [dm_mod]
+ do_resume+0x2c2/0x420 [dm_mod]
+ dev_suspend+0x30/0x130 [dm_mod]
+ ctl_ioctl+0x402/0x570 [dm_mod]
+ dm_ctl_ioctl+0x23/0x30 [dm_mod]
+
+Fix this by explicitly tracking whether the request queue was
+stopped in __dm_suspend() via a new DMF_QUEUE_STOPPED flag.
+Only call dm_start_queue() in __dm_resume() if the queue was
+actually stopped.
+
+Fixes: e70feb8b3e68 ("blk-mq: support concurrent queue quiesce/unquiesce")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-core.h |    1 +
+ drivers/md/dm.c      |    8 +++++---
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/md/dm-core.h
++++ b/drivers/md/dm-core.h
+@@ -162,6 +162,7 @@ struct mapped_device {
+ #define DMF_SUSPENDED_INTERNALLY 7
+ #define DMF_POST_SUSPENDING 8
+ #define DMF_EMULATE_ZONE_APPEND 9
++#define DMF_QUEUE_STOPPED 10
+ void disable_discard(struct mapped_device *md);
+ void disable_write_zeroes(struct mapped_device *md);
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -2970,8 +2970,10 @@ static int __dm_suspend(struct mapped_de
+        * Stop md->queue before flushing md->wq in case request-based
+        * dm defers requests to md->wq from md->queue.
+        */
+-      if (dm_request_based(md))
++      if (dm_request_based(md)) {
+               dm_stop_queue(md->queue);
++              set_bit(DMF_QUEUE_STOPPED, &md->flags);
++      }
+       flush_workqueue(md->wq);
+@@ -2993,7 +2995,7 @@ static int __dm_suspend(struct mapped_de
+       if (r < 0) {
+               dm_queue_flush(md);
+-              if (dm_request_based(md))
++              if (test_and_clear_bit(DMF_QUEUE_STOPPED, &md->flags))
+                       dm_start_queue(md->queue);
+               unlock_fs(md);
+@@ -3077,7 +3079,7 @@ static int __dm_resume(struct mapped_dev
+        * so that mapping of targets can work correctly.
+        * Request-based dm is queueing the deferred I/Os in its request_queue.
+        */
+-      if (dm_request_based(md))
++      if (test_and_clear_bit(DMF_QUEUE_STOPPED, &md->flags))
+               dm_start_queue(md->queue);
+       unlock_fs(md);
diff --git a/queue-6.12/ext4-fix-checks-for-orphan-inodes.patch b/queue-6.12/ext4-fix-checks-for-orphan-inodes.patch
new file mode 100644 (file)
index 0000000..d8be456
--- /dev/null
@@ -0,0 +1,106 @@
+From acf943e9768ec9d9be80982ca0ebc4bfd6b7631e Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 25 Sep 2025 14:30:39 +0200
+Subject: ext4: fix checks for orphan inodes
+
+From: Jan Kara <jack@suse.cz>
+
+commit acf943e9768ec9d9be80982ca0ebc4bfd6b7631e upstream.
+
+When orphan file feature is enabled, inode can be tracked as orphan
+either in the standard orphan list or in the orphan file. The first can
+be tested by checking ei->i_orphan list head, the second is recorded by
+EXT4_STATE_ORPHAN_FILE inode state flag. There are several places where
+we want to check whether inode is tracked as orphan and only some of
+them properly check for both possibilities. Luckily the consequences are
+mostly minor, the worst that can happen is that we track an inode as
+orphan although we don't need to and e2fsck then complains (resulting in
+occasional ext4/307 xfstest failures). Fix the problem by introducing a
+helper for checking whether an inode is tracked as orphan and use it in
+appropriate places.
+
+Fixes: 4a79a98c7b19 ("ext4: Improve scalability of ext4 orphan file handling")
+Cc: stable@kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
+Message-ID: <20250925123038.20264-2-jack@suse.cz>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/ext4.h   |   10 ++++++++++
+ fs/ext4/file.c   |    2 +-
+ fs/ext4/inode.c  |    2 +-
+ fs/ext4/orphan.c |    6 +-----
+ fs/ext4/super.c  |    4 ++--
+ 5 files changed, 15 insertions(+), 9 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1970,6 +1970,16 @@ static inline bool ext4_verity_in_progre
+ #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
+ /*
++ * Check whether the inode is tracked as orphan (either in orphan file or
++ * orphan list).
++ */
++static inline bool ext4_inode_orphan_tracked(struct inode *inode)
++{
++      return ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) ||
++              !list_empty(&EXT4_I(inode)->i_orphan);
++}
++
++/*
+  * Codes for operating systems
+  */
+ #define EXT4_OS_LINUX         0
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -354,7 +354,7 @@ static void ext4_inode_extension_cleanup
+        * to cleanup the orphan list in ext4_handle_inode_extension(). Do it
+        * now.
+        */
+-      if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
++      if (ext4_inode_orphan_tracked(inode) && inode->i_nlink) {
+               handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
+               if (IS_ERR(handle)) {
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4330,7 +4330,7 @@ static int ext4_fill_raw_inode(struct in
+                * old inodes get re-used with the upper 16 bits of the
+                * uid/gid intact.
+                */
+-              if (ei->i_dtime && list_empty(&ei->i_orphan)) {
++              if (ei->i_dtime && !ext4_inode_orphan_tracked(inode)) {
+                       raw_inode->i_uid_high = 0;
+                       raw_inode->i_gid_high = 0;
+               } else {
+--- a/fs/ext4/orphan.c
++++ b/fs/ext4/orphan.c
+@@ -109,11 +109,7 @@ int ext4_orphan_add(handle_t *handle, st
+       WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
+                    !inode_is_locked(inode));
+-      /*
+-       * Inode orphaned in orphan file or in orphan list?
+-       */
+-      if (ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) ||
+-          !list_empty(&EXT4_I(inode)->i_orphan))
++      if (ext4_inode_orphan_tracked(inode))
+               return 0;
+       /*
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1461,9 +1461,9 @@ static void ext4_free_in_core_inode(stru
+ static void ext4_destroy_inode(struct inode *inode)
+ {
+-      if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
++      if (ext4_inode_orphan_tracked(inode)) {
+               ext4_msg(inode->i_sb, KERN_ERR,
+-                       "Inode %lu (%p): orphan list check failed!",
++                       "Inode %lu (%p): inode tracked as orphan!",
+                        inode->i_ino, EXT4_I(inode));
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
+                               EXT4_I(inode), sizeof(struct ext4_inode_info),
diff --git a/queue-6.12/ksmbd-add-max-ip-connections-parameter.patch b/queue-6.12/ksmbd-add-max-ip-connections-parameter.patch
new file mode 100644 (file)
index 0000000..8d8a287
--- /dev/null
@@ -0,0 +1,122 @@
+From d8b6dc9256762293048bf122fc11c4e612d0ef5d Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Wed, 1 Oct 2025 09:25:35 +0900
+Subject: ksmbd: add max ip connections parameter
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit d8b6dc9256762293048bf122fc11c4e612d0ef5d upstream.
+
+This parameter set the maximum number of connections per ip address.
+The default is 8.
+
+Cc: stable@vger.kernel.org
+Fixes: c0d41112f1a5 ("ksmbd: extend the connection limiting mechanism to support IPv6")
+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/ksmbd_netlink.h |    5 +++--
+ fs/smb/server/server.h        |    1 +
+ fs/smb/server/transport_ipc.c |    3 +++
+ fs/smb/server/transport_tcp.c |   27 ++++++++++++++++-----------
+ 4 files changed, 23 insertions(+), 13 deletions(-)
+
+--- a/fs/smb/server/ksmbd_netlink.h
++++ b/fs/smb/server/ksmbd_netlink.h
+@@ -112,10 +112,11 @@ struct ksmbd_startup_request {
+       __u32   smbd_max_io_size;       /* smbd read write size */
+       __u32   max_connections;        /* Number of maximum simultaneous connections */
+       __s8    bind_interfaces_only;
+-      __s8    reserved[503];          /* Reserved room */
++      __u32   max_ip_connections;     /* Number of maximum connection per ip address */
++      __s8    reserved[499];          /* Reserved room */
+       __u32   ifc_list_sz;            /* interfaces list size */
+       __s8    ____payload[];
+-};
++} __packed;
+ #define KSMBD_STARTUP_CONFIG_INTERFACES(s)    ((s)->____payload)
+--- a/fs/smb/server/server.h
++++ b/fs/smb/server/server.h
+@@ -43,6 +43,7 @@ struct ksmbd_server_config {
+       unsigned int            auth_mechs;
+       unsigned int            max_connections;
+       unsigned int            max_inflight_req;
++      unsigned int            max_ip_connections;
+       char                    *conf[SERVER_CONF_WORK_GROUP + 1];
+       struct task_struct      *dh_task;
+--- a/fs/smb/server/transport_ipc.c
++++ b/fs/smb/server/transport_ipc.c
+@@ -335,6 +335,9 @@ static int ipc_server_config_on_startup(
+       if (req->max_connections)
+               server_conf.max_connections = req->max_connections;
++      if (req->max_ip_connections)
++              server_conf.max_ip_connections = req->max_ip_connections;
++
+       ret = ksmbd_set_netbios_name(req->netbios_name);
+       ret |= ksmbd_set_server_string(req->server_string);
+       ret |= ksmbd_set_work_group(req->work_group);
+--- a/fs/smb/server/transport_tcp.c
++++ b/fs/smb/server/transport_tcp.c
+@@ -240,6 +240,7 @@ static int ksmbd_kthread_fn(void *p)
+       struct interface *iface = (struct interface *)p;
+       struct ksmbd_conn *conn;
+       int ret;
++      unsigned int max_ip_conns;
+       while (!kthread_should_stop()) {
+               mutex_lock(&iface->sock_release_lock);
+@@ -257,34 +258,38 @@ static int ksmbd_kthread_fn(void *p)
+                       continue;
+               }
++              if (!server_conf.max_ip_connections)
++                      goto skip_max_ip_conns_limit;
++
+               /*
+                * Limits repeated connections from clients with the same IP.
+                */
++              max_ip_conns = 0;
+               down_read(&conn_list_lock);
+-              list_for_each_entry(conn, &conn_list, conns_list)
++              list_for_each_entry(conn, &conn_list, conns_list) {
+ #if IS_ENABLED(CONFIG_IPV6)
+                       if (client_sk->sk->sk_family == AF_INET6) {
+                               if (memcmp(&client_sk->sk->sk_v6_daddr,
+-                                         &conn->inet6_addr, 16) == 0) {
+-                                      ret = -EAGAIN;
+-                                      break;
+-                              }
++                                         &conn->inet6_addr, 16) == 0)
++                                      max_ip_conns++;
+                       } else if (inet_sk(client_sk->sk)->inet_daddr ==
+-                               conn->inet_addr) {
+-                              ret = -EAGAIN;
+-                              break;
+-                      }
++                               conn->inet_addr)
++                              max_ip_conns++;
+ #else
+                       if (inet_sk(client_sk->sk)->inet_daddr ==
+-                          conn->inet_addr) {
++                          conn->inet_addr)
++                              max_ip_conns++;
++#endif
++                      if (server_conf.max_ip_connections <= max_ip_conns) {
+                               ret = -EAGAIN;
+                               break;
+                       }
+-#endif
++              }
+               up_read(&conn_list_lock);
+               if (ret == -EAGAIN)
+                       continue;
++skip_max_ip_conns_limit:
+               if (server_conf.max_connections &&
+                   atomic_inc_return(&active_num_conn) >= server_conf.max_connections) {
+                       pr_info_ratelimited("Limit the maximum number of connections(%u)\n",
diff --git a/queue-6.12/ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch b/queue-6.12/ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch
new file mode 100644 (file)
index 0000000..cb7f1a2
--- /dev/null
@@ -0,0 +1,38 @@
+From 88daf2f448aad05a2e6df738d66fe8b0cf85cee0 Mon Sep 17 00:00:00 2001
+From: Matvey Kovalev <matvey.kovalev@ispras.ru>
+Date: Thu, 25 Sep 2025 15:12:34 +0300
+Subject: ksmbd: fix error code overwriting in smb2_get_info_filesystem()
+
+From: Matvey Kovalev <matvey.kovalev@ispras.ru>
+
+commit 88daf2f448aad05a2e6df738d66fe8b0cf85cee0 upstream.
+
+If client doesn't negotiate with SMB3.1.1 POSIX Extensions,
+then proper error code won't be returned due to overwriting.
+
+Return error immediately.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: e2f34481b24db ("cifsd: add server-side procedures for SMB3")
+Cc: stable@vger.kernel.org
+Signed-off-by: Matvey Kovalev <matvey.kovalev@ispras.ru>
+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/smb2pdu.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -5600,7 +5600,8 @@ static int smb2_get_info_filesystem(stru
+               if (!work->tcon->posix_extensions) {
+                       pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
+-                      rc = -EOPNOTSUPP;
++                      path_put(&path);
++                      return -EOPNOTSUPP;
+               } else {
+                       info = (struct filesystem_posix_info *)(rsp->Buffer);
+                       info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
diff --git a/queue-6.12/ksmbd-fix-race-condition-in-rpc-handle-list-access.patch b/queue-6.12/ksmbd-fix-race-condition-in-rpc-handle-list-access.patch
new file mode 100644 (file)
index 0000000..e7e824d
--- /dev/null
@@ -0,0 +1,101 @@
+From 305853cce379407090a73b38c5de5ba748893aee Mon Sep 17 00:00:00 2001
+From: Yunseong Kim <ysk@kzalloc.com>
+Date: Mon, 15 Sep 2025 22:44:09 +0000
+Subject: ksmbd: Fix race condition in RPC handle list access
+
+From: Yunseong Kim <ysk@kzalloc.com>
+
+commit 305853cce379407090a73b38c5de5ba748893aee upstream.
+
+The 'sess->rpc_handle_list' XArray manages RPC handles within a ksmbd
+session. Access to this list is intended to be protected by
+'sess->rpc_lock' (an rw_semaphore). However, the locking implementation was
+flawed, leading to potential race conditions.
+
+In ksmbd_session_rpc_open(), the code incorrectly acquired only a read lock
+before calling xa_store() and xa_erase(). Since these operations modify
+the XArray structure, a write lock is required to ensure exclusive access
+and prevent data corruption from concurrent modifications.
+
+Furthermore, ksmbd_session_rpc_method() accessed the list using xa_load()
+without holding any lock at all. This could lead to reading inconsistent
+data or a potential use-after-free if an entry is concurrently removed and
+the pointer is dereferenced.
+
+Fix these issues by:
+1. Using down_write() and up_write() in ksmbd_session_rpc_open()
+   to ensure exclusive access during XArray modification, and ensuring
+   the lock is correctly released on error paths.
+2. Adding down_read() and up_read() in ksmbd_session_rpc_method()
+   to safely protect the lookup.
+
+Fixes: a1f46c99d9ea ("ksmbd: fix use-after-free in ksmbd_session_rpc_open")
+Fixes: b685757c7b08 ("ksmbd: Implements sess->rpc_handle_list as xarray")
+Cc: stable@vger.kernel.org
+Signed-off-by: Yunseong Kim <ysk@kzalloc.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/mgmt/user_session.c |   26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+--- a/fs/smb/server/mgmt/user_session.c
++++ b/fs/smb/server/mgmt/user_session.c
+@@ -104,29 +104,32 @@ int ksmbd_session_rpc_open(struct ksmbd_
+       if (!entry)
+               return -ENOMEM;
+-      down_read(&sess->rpc_lock);
+       entry->method = method;
+       entry->id = id = ksmbd_ipc_id_alloc();
+       if (id < 0)
+               goto free_entry;
++
++      down_write(&sess->rpc_lock);
+       old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP);
+-      if (xa_is_err(old))
++      if (xa_is_err(old)) {
++              up_write(&sess->rpc_lock);
+               goto free_id;
++      }
+       resp = ksmbd_rpc_open(sess, id);
+-      if (!resp)
+-              goto erase_xa;
++      if (!resp) {
++              xa_erase(&sess->rpc_handle_list, entry->id);
++              up_write(&sess->rpc_lock);
++              goto free_id;
++      }
+-      up_read(&sess->rpc_lock);
++      up_write(&sess->rpc_lock);
+       kvfree(resp);
+       return id;
+-erase_xa:
+-      xa_erase(&sess->rpc_handle_list, entry->id);
+ free_id:
+       ksmbd_rpc_id_free(entry->id);
+ free_entry:
+       kfree(entry);
+-      up_read(&sess->rpc_lock);
+       return -EINVAL;
+ }
+@@ -144,9 +147,14 @@ void ksmbd_session_rpc_close(struct ksmb
+ int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
+ {
+       struct ksmbd_session_rpc *entry;
++      int method;
++      down_read(&sess->rpc_lock);
+       entry = xa_load(&sess->rpc_handle_list, id);
+-      return entry ? entry->method : 0;
++      method = entry ? entry->method : 0;
++      up_read(&sess->rpc_lock);
++
++      return method;
+ }
+ void ksmbd_session_destroy(struct ksmbd_session *sess)
diff --git a/queue-6.12/loongarch-automatically-disable-kaslr-if-boot-from-kexec_file.patch b/queue-6.12/loongarch-automatically-disable-kaslr-if-boot-from-kexec_file.patch
new file mode 100644 (file)
index 0000000..2dd4387
--- /dev/null
@@ -0,0 +1,43 @@
+From c8168b4faf1d62cbb320a3e518ad31cdd567cb05 Mon Sep 17 00:00:00 2001
+From: Youling Tang <tangyouling@kylinos.cn>
+Date: Thu, 2 Oct 2025 22:39:08 +0800
+Subject: LoongArch: Automatically disable kaslr if boot from kexec_file
+
+From: Youling Tang <tangyouling@kylinos.cn>
+
+commit c8168b4faf1d62cbb320a3e518ad31cdd567cb05 upstream.
+
+Automatically disable kaslr when the kernel loads from kexec_file.
+
+kexec_file loads the secondary kernel image to a non-linked address,
+inherently providing KASLR-like randomization.
+
+However, on LoongArch where System RAM may be non-contiguous, enabling
+KASLR for the second kernel may relocate it to an invalid memory region
+and cause a boot failure. Thus, we disable KASLR when "kexec_file" is
+detected in the command line.
+
+To ensure compatibility with older kernels loaded via kexec_file, this
+patch should be backported to stable branches.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/loongarch/kernel/relocate.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/loongarch/kernel/relocate.c
++++ b/arch/loongarch/kernel/relocate.c
+@@ -166,6 +166,10 @@ static inline __init bool kaslr_disabled
+               return true;
+ #endif
++      str = strstr(boot_command_line, "kexec_file");
++      if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' '))
++              return true;
++
+       return false;
+ }
index a156f9ee588f6f1038910a296d781eaf4573d718..d94cdf2a3f09e474880aec9420267e981f80eb80 100644 (file)
@@ -234,3 +234,10 @@ fs-udf-fix-oob-read-in-lengthallocdescs-handling.patch
 net-nfc-nci-add-parameter-validation-for-packet-data.patch
 mfd-rz-mtu3-fix-mtu5-nfcr-register-offset.patch
 mfd-vexpress-sysreg-check-the-return-value-of-devm_gpiochip_add_data.patch
+dm-fix-queue-start-stop-imbalance-under-suspend-load-resume-races.patch
+dm-fix-null-pointer-dereference-in-__dm_suspend.patch
+loongarch-automatically-disable-kaslr-if-boot-from-kexec_file.patch
+ksmbd-fix-race-condition-in-rpc-handle-list-access.patch
+ksmbd-fix-error-code-overwriting-in-smb2_get_info_filesystem.patch
+ksmbd-add-max-ip-connections-parameter.patch
+ext4-fix-checks-for-orphan-inodes.patch