Skip to content

Commit b698b9a

Browse files
committed
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/[email protected] v1: https://lore.kernel.org/[email protected] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 15d6f74 + 440c9d4 commit b698b9a

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

net/vmw_vsock/af_vsock.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,19 @@ static void __vsock_release(struct sock *sk, int level)
824824
*/
825825
lock_sock_nested(sk, level);
826826

827-
sock_orphan(sk);
827+
/* Indicate to vsock_remove_sock() that the socket is being released and
828+
* can be removed from the bound_table. Unlike transport reassignment
829+
* case, where the socket must remain bound despite vsock_remove_sock()
830+
* being called from the transport release() callback.
831+
*/
832+
sock_set_flag(sk, SOCK_DEAD);
828833

829834
if (vsk->transport)
830835
vsk->transport->release(vsk);
831836
else if (sock_type_connectible(sk->sk_type))
832837
vsock_remove_sock(vsk);
833838

839+
sock_orphan(sk);
834840
sk->sk_shutdown = SHUTDOWN_MASK;
835841

836842
skb_queue_purge(&sk->sk_receive_queue);

tools/testing/vsock/vsock_test.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,6 +1788,42 @@ static void test_stream_connect_retry_server(const struct test_opts *opts)
17881788
close(fd);
17891789
}
17901790

1791+
static void test_stream_linger_client(const struct test_opts *opts)
1792+
{
1793+
struct linger optval = {
1794+
.l_onoff = 1,
1795+
.l_linger = 1
1796+
};
1797+
int fd;
1798+
1799+
fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
1800+
if (fd < 0) {
1801+
perror("connect");
1802+
exit(EXIT_FAILURE);
1803+
}
1804+
1805+
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &optval, sizeof(optval))) {
1806+
perror("setsockopt(SO_LINGER)");
1807+
exit(EXIT_FAILURE);
1808+
}
1809+
1810+
close(fd);
1811+
}
1812+
1813+
static void test_stream_linger_server(const struct test_opts *opts)
1814+
{
1815+
int fd;
1816+
1817+
fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
1818+
if (fd < 0) {
1819+
perror("accept");
1820+
exit(EXIT_FAILURE);
1821+
}
1822+
1823+
vsock_wait_remote_close(fd);
1824+
close(fd);
1825+
}
1826+
17911827
static struct test_case test_cases[] = {
17921828
{
17931829
.name = "SOCK_STREAM connection reset",
@@ -1943,6 +1979,11 @@ static struct test_case test_cases[] = {
19431979
.run_client = test_stream_connect_retry_client,
19441980
.run_server = test_stream_connect_retry_server,
19451981
},
1982+
{
1983+
.name = "SOCK_STREAM SO_LINGER null-ptr-deref",
1984+
.run_client = test_stream_linger_client,
1985+
.run_server = test_stream_linger_server,
1986+
},
19461987
{},
19471988
};
19481989

0 commit comments

Comments
 (0)