1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

Merge branch 'vsock-null-ptr-deref-when-so_linger-enabled'

Michal Luczaj says:

====================
vsock: null-ptr-deref when SO_LINGER enabled

syzbot pointed out that a recent patching of a use-after-free introduced a
null-ptr-deref. This series fixes the problem and adds a test.

v2: https://lore.kernel.org/20250206-vsock-linger-nullderef-v2-0-f8a1f19146f8@rbox.co
v1: https://lore.kernel.org/20250204-vsock-linger-nullderef-v1-0-6eb1760fa93e@rbox.co
====================

Link: https://patch.msgid.link/20250210-vsock-linger-nullderef-v3-0-ef6244d02b54@rbox.co
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-02-12 20:01:30 -08:00
commit b698b9a8ac
2 changed files with 48 additions and 1 deletions

View file

@ -824,13 +824,19 @@ static void __vsock_release(struct sock *sk, int level)
*/
lock_sock_nested(sk, level);
sock_orphan(sk);
/* Indicate to vsock_remove_sock() that the socket is being released and
* can be removed from the bound_table. Unlike transport reassignment
* case, where the socket must remain bound despite vsock_remove_sock()
* being called from the transport release() callback.
*/
sock_set_flag(sk, SOCK_DEAD);
if (vsk->transport)
vsk->transport->release(vsk);
else if (sock_type_connectible(sk->sk_type))
vsock_remove_sock(vsk);
sock_orphan(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
skb_queue_purge(&sk->sk_receive_queue);

View file

@ -1788,6 +1788,42 @@ static void test_stream_connect_retry_server(const struct test_opts *opts)
close(fd);
}
static void test_stream_linger_client(const struct test_opts *opts)
{
struct linger optval = {
.l_onoff = 1,
.l_linger = 1
};
int fd;
fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
if (fd < 0) {
perror("connect");
exit(EXIT_FAILURE);
}
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &optval, sizeof(optval))) {
perror("setsockopt(SO_LINGER)");
exit(EXIT_FAILURE);
}
close(fd);
}
static void test_stream_linger_server(const struct test_opts *opts)
{
int fd;
fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
if (fd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
vsock_wait_remote_close(fd);
close(fd);
}
static struct test_case test_cases[] = {
{
.name = "SOCK_STREAM connection reset",
@ -1943,6 +1979,11 @@ static struct test_case test_cases[] = {
.run_client = test_stream_connect_retry_client,
.run_server = test_stream_connect_retry_server,
},
{
.name = "SOCK_STREAM SO_LINGER null-ptr-deref",
.run_client = test_stream_linger_client,
.run_server = test_stream_linger_server,
},
{},
};