Message ID | 20250206-vsock-linger-nullderef-v2-2-f8a1f19146f8@rbox.co (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | vsock: null-ptr-deref when SO_LINGER enabled | expand |
On Thu, Feb 06, 2025 at 12:06:48AM +0100, Michal Luczaj wrote: >Explicitly close() a TCP_ESTABLISHED (connectible) socket with SO_LINGER >enabled. > >As for now, test does not verify if close() actually lingers. >On an unpatched machine, may trigger a null pointer dereference. > >Tested-by: Luigi Leonardi <leonardi@redhat.com> >Signed-off-by: Michal Luczaj <mhal@rbox.co> >--- > tools/testing/vsock/vsock_test.c | 41 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > >diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c >index dfff8b288265f96b602cb1bfa0e6dce02f114222..d0f6d253ac72d08a957cb81a3c38fcc72bec5a53 100644 >--- a/tools/testing/vsock/vsock_test.c >+++ b/tools/testing/vsock/vsock_test.c >@@ -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, >+ }, > {}, > }; > > >-- >2.48.1 > Thanks! Reviewed-by: Luigi Leonardi <leonardi@redhat.com>
On Thu, Feb 06, 2025 at 12:06:48AM +0100, Michal Luczaj wrote: >Explicitly close() a TCP_ESTABLISHED (connectible) socket with SO_LINGER >enabled. > >As for now, test does not verify if close() actually lingers. >On an unpatched machine, may trigger a null pointer dereference. > >Tested-by: Luigi Leonardi <leonardi@redhat.com> >Signed-off-by: Michal Luczaj <mhal@rbox.co> >--- > tools/testing/vsock/vsock_test.c | 41 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> > >diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c >index dfff8b288265f96b602cb1bfa0e6dce02f114222..d0f6d253ac72d08a957cb81a3c38fcc72bec5a53 100644 >--- a/tools/testing/vsock/vsock_test.c >+++ b/tools/testing/vsock/vsock_test.c >@@ -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, >+ }, > {}, > }; > > >-- >2.48.1 >
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index dfff8b288265f96b602cb1bfa0e6dce02f114222..d0f6d253ac72d08a957cb81a3c38fcc72bec5a53 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -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, + }, {}, };