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:
commit
b698b9a8ac
2 changed files with 48 additions and 1 deletions
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue