From: Namjae Jeon linkinjeon@kernel.org
stable inclusion from stable-v5.15.81 commit 999daf367b924fdf14e9d83e034ee0f86bc17ec6 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I932W8 CVE: CVE-2024-26592
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 38d20c62903d669693a1869aa68c4dd5674e2544 ]
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: Sasha Levin sashal@kernel.org
Conflict: fs/ksmbd/transport_tcp.c
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/connection.c | 6 ------ fs/ksmbd/connection.h | 1 - fs/ksmbd/transport_rdma.c | 11 ++++++----- fs/ksmbd/transport_tcp.c | 13 +++++++------ 4 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c index f0818e764230..d48d177cba6b 100644 --- a/fs/ksmbd/connection.c +++ b/fs/ksmbd/connection.c @@ -434,13 +434,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); diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h index 75a1849ba828..9708ba99d8a5 100644 --- a/fs/ksmbd/connection.h +++ b/fs/ksmbd/connection.h @@ -128,7 +128,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) diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c index d3b60b833a81..2a8640ce1107 100644 --- a/fs/ksmbd/transport_rdma.c +++ b/fs/ksmbd/transport_rdma.c @@ -1976,6 +1976,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)) { @@ -1993,11 +1994,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; } diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c index d34812d140eb..79b40f26587c 100644 --- a/fs/ksmbd/transport_tcp.c +++ b/fs/ksmbd/transport_tcp.c @@ -183,6 +183,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) @@ -195,13 +196,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;