]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ksmbd: fix use-after-free in __smb2_lease_break_noti()
authorNamjae Jeon <linkinjeon@kernel.org>
Sat, 26 Jul 2025 15:52:17 +0000 (11:52 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Aug 2025 08:47:32 +0000 (09:47 +0100)
[ Upstream commit 21a4e47578d44c6b37c4fc4aba8ed7cc8dbb13de ]

Move tcp_transport free to ksmbd_conn_free. If ksmbd connection is
referenced when ksmbd server thread terminates, It will not be freed,
but conn->tcp_transport is freed. __smb2_lease_break_noti can be performed
asynchronously when the connection is disconnected. __smb2_lease_break_noti
calls ksmbd_conn_write, which can cause use-after-free
when conn->ksmbd_transport is already freed.

Cc: stable@vger.kernel.org
Reported-by: Norbert Szetei <norbert@doyensec.com>
Tested-by: Norbert Szetei <norbert@doyensec.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
[ Removed declaration of non-existent function ksmbd_find_netdev_name_iface_list() from transport_tcp.h. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/smb/server/connection.c
fs/smb/server/transport_tcp.c
fs/smb/server/transport_tcp.h

index e7bcc383003103cfeabf0dbd979931384dba40b5..abbf756891a9cea7027c09460614d317d18d38ff 100644 (file)
@@ -39,8 +39,10 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
        xa_destroy(&conn->sessions);
        kvfree(conn->request_buf);
        kfree(conn->preauth_info);
-       if (atomic_dec_and_test(&conn->refcnt))
+       if (atomic_dec_and_test(&conn->refcnt)) {
+               ksmbd_free_transport(conn->transport);
                kfree(conn);
+       }
 }
 
 /**
index 2ce7f75059cb35c42ae9e0843bdaee001207078e..c27f0cef3b592bc3f0a96a3198ede2a36a0154f2 100644 (file)
@@ -93,17 +93,21 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
        return t;
 }
 
-static void free_transport(struct tcp_transport *t)
+void ksmbd_free_transport(struct ksmbd_transport *kt)
 {
-       kernel_sock_shutdown(t->sock, SHUT_RDWR);
-       sock_release(t->sock);
-       t->sock = NULL;
+       struct tcp_transport *t = TCP_TRANS(kt);
 
-       ksmbd_conn_free(KSMBD_TRANS(t)->conn);
+       sock_release(t->sock);
        kfree(t->iov);
        kfree(t);
 }
 
+static void free_transport(struct tcp_transport *t)
+{
+       kernel_sock_shutdown(t->sock, SHUT_RDWR);
+       ksmbd_conn_free(KSMBD_TRANS(t)->conn);
+}
+
 /**
  * kvec_array_init() - initialize a IO vector segment
  * @new:       IO vector to be initialized
index e338bebe322f10269b4bacc00b2d488fd04ee4e0..5925ec5df47552a8cf6d55718ca42f74d36c460c 100644 (file)
@@ -7,6 +7,7 @@
 #define __KSMBD_TRANSPORT_TCP_H__
 
 int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz);
+void ksmbd_free_transport(struct ksmbd_transport *kt);
 int ksmbd_tcp_init(void);
 void ksmbd_tcp_destroy(void);