ksmbd: fix UAF issue in ksmbd_tcp_new_connection()
authorNamjae Jeon <linkinjeon@kernel.org>
Sat, 13 Jan 2024 06:30:07 +0000 (15:30 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jan 2024 23:35:44 +0000 (15:35 -0800)
commit 38d20c62903d669693a1869aa68c4dd5674e2544 upstream.

The race is between the handling of a new TCP connection and
its disconnection. It leads to UAF on `struct tcp_transport` in
ksmbd_tcp_new_connection() function.

Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22991
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/connection.c
fs/smb/server/connection.h
fs/smb/server/transport_rdma.c
fs/smb/server/transport_tcp.c

index b6fa1e2..7977827 100644 (file)
@@ -415,13 +415,7 @@ static void stop_sessions(void)
 again:
        down_read(&conn_list_lock);
        list_for_each_entry(conn, &conn_list, conns_list) {
-               struct task_struct *task;
-
                t = conn->transport;
-               task = t->handler;
-               if (task)
-                       ksmbd_debug(CONN, "Stop session handler %s/%d\n",
-                                   task->comm, task_pid_nr(task));
                ksmbd_conn_set_exiting(conn);
                if (t->ops->shutdown) {
                        up_read(&conn_list_lock);
index 342f935..0e04cf8 100644 (file)
@@ -135,7 +135,6 @@ struct ksmbd_transport_ops {
 struct ksmbd_transport {
        struct ksmbd_conn               *conn;
        struct ksmbd_transport_ops      *ops;
-       struct task_struct              *handler;
 };
 
 #define KSMBD_TCP_RECV_TIMEOUT (7 * HZ)
index c5629a6..8faa25c 100644 (file)
@@ -2039,6 +2039,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs)
 static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
 {
        struct smb_direct_transport *t;
+       struct task_struct *handler;
        int ret;
 
        if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) {
@@ -2056,11 +2057,11 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id)
        if (ret)
                goto out_err;
 
-       KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
-                                             KSMBD_TRANS(t)->conn, "ksmbd:r%u",
-                                             smb_direct_port);
-       if (IS_ERR(KSMBD_TRANS(t)->handler)) {
-               ret = PTR_ERR(KSMBD_TRANS(t)->handler);
+       handler = kthread_run(ksmbd_conn_handler_loop,
+                             KSMBD_TRANS(t)->conn, "ksmbd:r%u",
+                             smb_direct_port);
+       if (IS_ERR(handler)) {
+               ret = PTR_ERR(handler);
                pr_err("Can't start thread\n");
                goto out_err;
        }
index eff7a1d..9d42221 100644 (file)
@@ -185,6 +185,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
        struct sockaddr *csin;
        int rc = 0;
        struct tcp_transport *t;
+       struct task_struct *handler;
 
        t = alloc_transport(client_sk);
        if (!t) {
@@ -199,13 +200,13 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
                goto out_error;
        }
 
-       KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop,
-                                             KSMBD_TRANS(t)->conn,
-                                             "ksmbd:%u",
-                                             ksmbd_tcp_get_port(csin));
-       if (IS_ERR(KSMBD_TRANS(t)->handler)) {
+       handler = kthread_run(ksmbd_conn_handler_loop,
+                             KSMBD_TRANS(t)->conn,
+                             "ksmbd:%u",
+                             ksmbd_tcp_get_port(csin));
+       if (IS_ERR(handler)) {
                pr_err("cannot start conn thread\n");
-               rc = PTR_ERR(KSMBD_TRANS(t)->handler);
+               rc = PTR_ERR(handler);
                free_transport(t);
        }
        return rc;