|
29 | 29 | #include "control.h"
|
30 | 30 | #include "util.h"
|
31 | 31 |
|
| 32 | +/* Basic messages for control_writeulong(), control_readulong() */ |
| 33 | +#define CONTROL_CONTINUE 1 |
| 34 | +#define CONTROL_DONE 0 |
| 35 | + |
32 | 36 | static void test_stream_connection_reset(const struct test_opts *opts)
|
33 | 37 | {
|
34 | 38 | union {
|
@@ -1474,6 +1478,49 @@ static void test_stream_cred_upd_on_set_rcvlowat(const struct test_opts *opts)
|
1474 | 1478 | test_stream_credit_update_test(opts, false);
|
1475 | 1479 | }
|
1476 | 1480 |
|
| 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 | + |
1477 | 1524 | static struct test_case test_cases[] = {
|
1478 | 1525 | {
|
1479 | 1526 | .name = "SOCK_STREAM connection reset",
|
@@ -1604,6 +1651,11 @@ static struct test_case test_cases[] = {
|
1604 | 1651 | .run_client = test_seqpacket_unsent_bytes_client,
|
1605 | 1652 | .run_server = test_seqpacket_unsent_bytes_server,
|
1606 | 1653 | },
|
| 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 | + }, |
1607 | 1659 | {},
|
1608 | 1660 | };
|
1609 | 1661 |
|
|
0 commit comments