ksmbd: add free_transport ops in ksmbd connection
authorNamjae Jeon <linkinjeon@kernel.org>
Tue, 10 Jun 2025 09:52:56 +0000 (18:52 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 17 Jun 2025 21:26:44 +0000 (16:26 -0500)
free_transport function for tcp connection can be called from smbdirect.
It will cause kernel oops. This patch add free_transport ops in ksmbd
connection, and add each free_transports for tcp and smbdirect.

Fixes: 21a4e47578d4 ("ksmbd: fix use-after-free in __smb2_lease_break_noti()")
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/connection.c
fs/smb/server/connection.h
fs/smb/server/transport_rdma.c
fs/smb/server/transport_tcp.c

index 83764c230e9d4c9798bb6182cff8855c1e662d25..3f04a2977ba86c22eac06f6270496cee4526a365 100644 (file)
@@ -40,7 +40,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn)
        kvfree(conn->request_buf);
        kfree(conn->preauth_info);
        if (atomic_dec_and_test(&conn->refcnt)) {
-               ksmbd_free_transport(conn->transport);
+               conn->transport->ops->free_transport(conn->transport);
                kfree(conn);
        }
 }
index 6efed923bd687dbe1882f956ce999090ada6797e..dd3e0e3f7bf046bad0573fe900ef829fe82d030e 100644 (file)
@@ -133,6 +133,7 @@ struct ksmbd_transport_ops {
                          void *buf, unsigned int len,
                          struct smb2_buffer_desc_v1 *desc,
                          unsigned int desc_len);
+       void (*free_transport)(struct ksmbd_transport *kt);
 };
 
 struct ksmbd_transport {
index 4998df04ab95aed85934e041543cf0f6ad7fec25..64a428a06ace0cfda3008f4871f66be2c1fceae2 100644 (file)
@@ -159,7 +159,8 @@ struct smb_direct_transport {
 };
 
 #define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport))
-
+#define SMBD_TRANS(t)  ((struct smb_direct_transport *)container_of(t, \
+                               struct smb_direct_transport, transport))
 enum {
        SMB_DIRECT_MSG_NEGOTIATE_REQ = 0,
        SMB_DIRECT_MSG_DATA_TRANSFER
@@ -410,6 +411,11 @@ err:
        return NULL;
 }
 
+static void smb_direct_free_transport(struct ksmbd_transport *kt)
+{
+       kfree(SMBD_TRANS(kt));
+}
+
 static void free_transport(struct smb_direct_transport *t)
 {
        struct smb_direct_recvmsg *recvmsg;
@@ -455,7 +461,6 @@ static void free_transport(struct smb_direct_transport *t)
 
        smb_direct_destroy_pools(t);
        ksmbd_conn_free(KSMBD_TRANS(t)->conn);
-       kfree(t);
 }
 
 static struct smb_direct_sendmsg
@@ -2281,4 +2286,5 @@ static const struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = {
        .read           = smb_direct_read,
        .rdma_read      = smb_direct_rdma_read,
        .rdma_write     = smb_direct_rdma_write,
+       .free_transport = smb_direct_free_transport,
 };
index abedf510899a744a0e8a67004154c066d7472353..4e9f98db9ff4098425ba315717f5fd1c6aae7579 100644 (file)
@@ -93,7 +93,7 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
        return t;
 }
 
-void ksmbd_free_transport(struct ksmbd_transport *kt)
+static void ksmbd_tcp_free_transport(struct ksmbd_transport *kt)
 {
        struct tcp_transport *t = TCP_TRANS(kt);
 
@@ -656,4 +656,5 @@ static const struct ksmbd_transport_ops ksmbd_tcp_transport_ops = {
        .read           = ksmbd_tcp_read,
        .writev         = ksmbd_tcp_writev,
        .disconnect     = ksmbd_tcp_disconnect,
+       .free_transport = ksmbd_tcp_free_transport,
 };