77 lines
2.4 KiB
Diff
77 lines
2.4 KiB
Diff
From 1932e1bb8624ec520da5f61e3f5bbdd16b9f320d Mon Sep 17 00:00:00 2001
|
|
From: Namjae Jeon <linkinjeon@kernel.org>
|
|
Date: Fri, 11 Apr 2025 15:19:46 +0900
|
|
Subject: ksmbd: fix use-after-free in __smb2_lease_break_noti()
|
|
|
|
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>
|
|
---
|
|
fs/smb/server/connection.c | 4 +++-
|
|
fs/smb/server/transport_tcp.c | 14 +++++++++-----
|
|
fs/smb/server/transport_tcp.h | 1 +
|
|
3 files changed, 13 insertions(+), 6 deletions(-)
|
|
|
|
--- a/fs/smb/server/connection.c
|
|
+++ b/fs/smb/server/connection.c
|
|
@@ -39,8 +39,10 @@ void ksmbd_conn_free(struct ksmbd_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);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
--- a/fs/smb/server/transport_tcp.c
|
|
+++ b/fs/smb/server/transport_tcp.c
|
|
@@ -93,17 +93,21 @@ static struct tcp_transport *alloc_trans
|
|
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
|
|
--- a/fs/smb/server/transport_tcp.h
|
|
+++ b/fs/smb/server/transport_tcp.h
|
|
@@ -8,6 +8,7 @@
|
|
|
|
int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz);
|
|
struct interface *ksmbd_find_netdev_name_iface_list(char *netdev_name);
|
|
+void ksmbd_free_transport(struct ksmbd_transport *kt);
|
|
int ksmbd_tcp_init(void);
|
|
void ksmbd_tcp_destroy(void);
|
|
|