Skip to content

Commit f66ef46

Browse files
mmhalkuba-moo
authored andcommitted
vsock/test: Add test for accept_queue memory leak
Attempt to enqueue a child after the queue was flushed, but before SOCK_DONE flag has been set. Test tries to produce a memory leak, kmemleak should be employed. Dealing with a race condition, test by its very nature may lead to a false negative. Fixed by commit d7b0ff5 ("virtio/vsock: Fix accept_queue memory leak"). Reviewed-by: Stefano Garzarella <[email protected]> Signed-off-by: Michal Luczaj <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f52e7f5 commit f66ef46

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

tools/testing/vsock/vsock_test.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
#include "control.h"
3030
#include "util.h"
3131

32+
/* Basic messages for control_writeulong(), control_readulong() */
33+
#define CONTROL_CONTINUE 1
34+
#define CONTROL_DONE 0
35+
3236
static void test_stream_connection_reset(const struct test_opts *opts)
3337
{
3438
union {
@@ -1474,6 +1478,49 @@ static void test_stream_cred_upd_on_set_rcvlowat(const struct test_opts *opts)
14741478
test_stream_credit_update_test(opts, false);
14751479
}
14761480

1481+
/* The goal of test leak_acceptq is to stress the race between connect() and
1482+
* close(listener). Implementation of client/server loops boils down to:
1483+
*
1484+
* client server
1485+
* ------ ------
1486+
* write(CONTINUE)
1487+
* expect(CONTINUE)
1488+
* listen()
1489+
* write(LISTENING)
1490+
* expect(LISTENING)
1491+
* connect() close()
1492+
*/
1493+
#define ACCEPTQ_LEAK_RACE_TIMEOUT 2 /* seconds */
1494+
1495+
static void test_stream_leak_acceptq_client(const struct test_opts *opts)
1496+
{
1497+
time_t tout;
1498+
int fd;
1499+
1500+
tout = current_nsec() + ACCEPTQ_LEAK_RACE_TIMEOUT * NSEC_PER_SEC;
1501+
do {
1502+
control_writeulong(CONTROL_CONTINUE);
1503+
1504+
fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
1505+
if (fd >= 0)
1506+
close(fd);
1507+
} while (current_nsec() < tout);
1508+
1509+
control_writeulong(CONTROL_DONE);
1510+
}
1511+
1512+
/* Test for a memory leak. User is expected to run kmemleak scan, see README. */
1513+
static void test_stream_leak_acceptq_server(const struct test_opts *opts)
1514+
{
1515+
int fd;
1516+
1517+
while (control_readulong() == CONTROL_CONTINUE) {
1518+
fd = vsock_stream_listen(VMADDR_CID_ANY, opts->peer_port);
1519+
control_writeln("LISTENING");
1520+
close(fd);
1521+
}
1522+
}
1523+
14771524
static struct test_case test_cases[] = {
14781525
{
14791526
.name = "SOCK_STREAM connection reset",
@@ -1604,6 +1651,11 @@ static struct test_case test_cases[] = {
16041651
.run_client = test_seqpacket_unsent_bytes_client,
16051652
.run_server = test_seqpacket_unsent_bytes_server,
16061653
},
1654+
{
1655+
.name = "SOCK_STREAM leak accept queue",
1656+
.run_client = test_stream_leak_acceptq_client,
1657+
.run_server = test_stream_leak_acceptq_server,
1658+
},
16071659
{},
16081660
};
16091661

0 commit comments

Comments
 (0)