Skip to content

Commit 1fab1fa

Browse files
llllIIIllllsmfrench
authored andcommitted
ksmbd: ipc: fix use-after-free in ipc_msg_send_request
ipc_msg_send_request() waits for a generic netlink reply using an ipc_msg_table_entry on the stack. The generic netlink handler (handle_generic_event()/handle_response()) fills entry->response under ipc_msg_table_lock, but ipc_msg_send_request() used to validate and free entry->response without holding the same lock. Under high concurrency this allows a race where handle_response() is copying data into entry->response while ipc_msg_send_request() has just freed it, leading to a slab-use-after-free reported by KASAN in handle_generic_event(): BUG: KASAN: slab-use-after-free in handle_generic_event+0x3c4/0x5f0 [ksmbd] Write of size 12 at addr ffff888198ee6e20 by task pool/109349 ... Freed by task: kvfree ipc_msg_send_request [ksmbd] ksmbd_rpc_open -> ksmbd_session_rpc_open [ksmbd] Fix by: - Taking ipc_msg_table_lock in ipc_msg_send_request() while validating entry->response, freeing it when invalid, and removing the entry from ipc_msg_table. - Returning the final entry->response pointer to the caller only after the hash entry is removed under the lock. - Returning NULL in the error path, preserving the original API semantics. This makes all accesses to entry->response consistent with handle_response(), which already updates and fills the response buffer under ipc_msg_table_lock, and closes the race that allowed the UAF. Cc: stable@vger.kernel.org Reported-by: Qianchang Zhao <pioooooooooip@gmail.com> Reported-by: Zhitong Liu <liuzhitong1993@gmail.com> Signed-off-by: Qianchang Zhao <pioooooooooip@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent dc10cf1 commit 1fab1fa

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

fs/smb/server/transport_ipc.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,12 +553,16 @@ static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle
553553
up_write(&ipc_msg_table_lock);
554554

555555
ret = ipc_msg_send(msg);
556-
if (ret)
556+
if (ret) {
557+
down_write(&ipc_msg_table_lock);
557558
goto out;
559+
}
558560

559561
ret = wait_event_interruptible_timeout(entry.wait,
560562
entry.response != NULL,
561563
IPC_WAIT_TIMEOUT);
564+
565+
down_write(&ipc_msg_table_lock);
562566
if (entry.response) {
563567
ret = ipc_validate_msg(&entry);
564568
if (ret) {
@@ -567,7 +571,6 @@ static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle
567571
}
568572
}
569573
out:
570-
down_write(&ipc_msg_table_lock);
571574
hash_del(&entry.ipc_table_hlist);
572575
up_write(&ipc_msg_table_lock);
573576
return entry.response;

0 commit comments

Comments
 (0)