Subject: [PATCH net v2] tipc: clear sock->sk on the failed-insert path in
tipc_sk_create()
When tipc_sk_create() fails to insert the new socket (tipc_sk_insert() returns
non-zero), its error path frees the sk with sk_free() but leaves
sock->sk pointing at the freed object:
if (tipc_sk_insert(tsk)) {
sk_free(sk);
pr_warn("Socket create failed; port number exhausted\n");
return -EINVAL;
}
This is harmless for plain socket(): the syscall layer clears sock->ops before
releasing, so tipc_release() is never called. It is not harmless on the accept()
path. tipc_accept() creates the pre-allocated child socket with
tipc_sk_create(net, new_sock, 0, kern); on failure it leaves new_sock->sk
dangling and new_sock->ops non-NULL, and do_accept() then fput()s the new
file, so __sock_release() -> tipc_release() runs
lock_sock(new_sock->sk) on the freed sk -- a use-after-free write of the sk_lock
spinlock.
tipc_release() already guards this exact "failed accept() releases a pre-allocated
child" case with "if (sk == NULL) return 0;", but the guard is bypassed because
tipc_sk_create() left sock->sk non-NULL
(dangling) rather than NULL.
Clear sock->sk on the failed-insert path so the existing tipc_release() NULL
check fires and the use-after-free is avoided.
Reviewed-by: Tung Nguyen <redacted>