Skip to content

Commit

Permalink
tests/ncdevmem: Fix double-free of queue array
Browse files Browse the repository at this point in the history
netdev_bind_rx takes ownership of the queue array passed as parameter
and frees it, so a queue array buffer cannot be reused across multiple
netdev_bind_rx calls.

This commit fixes that by always passing in a newly created queue array
to all netdev_bind_rx calls in ncdevmem.

Fixes: 85585b4 ("selftests: add ncdevmem, netcat for devmem TCP")
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Reviewed-by: Joe Damato <jdamato@fastly.com>
Reviewed-by: Mina Almasry <almasrymina@google.com>
Link: https://patch.msgid.link/20250508084434.1933069-1-cratiu@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Cosmin Ratiu authored and Jakub Kicinski committed May 9, 2025
1 parent f11cf94 commit 97c4e09
Showing 1 changed file with 22 additions and 33 deletions.
55 changes: 22 additions & 33 deletions tools/testing/selftests/drivers/net/hw/ncdevmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,22 @@ static int parse_address(const char *str, int port, struct sockaddr_in6 *sin6)
return 0;
}

static struct netdev_queue_id *create_queues(void)
{
struct netdev_queue_id *queues;
size_t i = 0;

queues = calloc(num_queues, sizeof(*queues));
for (i = 0; i < num_queues; i++) {
queues[i]._present.type = 1;
queues[i]._present.id = 1;
queues[i].type = NETDEV_QUEUE_TYPE_RX;
queues[i].id = start_queue + i;
}

return queues;
}

int do_server(struct memory_buffer *mem)
{
char ctrl_data[sizeof(int) * 20000];
Expand All @@ -448,7 +464,6 @@ int do_server(struct memory_buffer *mem)
char buffer[256];
int socket_fd;
int client_fd;
size_t i = 0;
int ret;

ret = parse_address(server_ip, atoi(port), &server_sin);
Expand All @@ -471,16 +486,7 @@ int do_server(struct memory_buffer *mem)

sleep(1);

queues = malloc(sizeof(*queues) * num_queues);

for (i = 0; i < num_queues; i++) {
queues[i]._present.type = 1;
queues[i]._present.id = 1;
queues[i].type = NETDEV_QUEUE_TYPE_RX;
queues[i].id = start_queue + i;
}

if (bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys))
if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys))
error(1, 0, "Failed to bind\n");

tmp_mem = malloc(mem->size);
Expand Down Expand Up @@ -545,7 +551,6 @@ int do_server(struct memory_buffer *mem)
goto cleanup;
}

i++;
for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) {
if (cm->cmsg_level != SOL_SOCKET ||
(cm->cmsg_type != SCM_DEVMEM_DMABUF &&
Expand Down Expand Up @@ -630,49 +635,33 @@ int do_server(struct memory_buffer *mem)

void run_devmem_tests(void)
{
struct netdev_queue_id *queues;
struct memory_buffer *mem;
struct ynl_sock *ys;
size_t i = 0;

mem = provider->alloc(getpagesize() * NUM_PAGES);

/* Configure RSS to divert all traffic from our devmem queues */
if (configure_rss())
error(1, 0, "rss error\n");

queues = calloc(num_queues, sizeof(*queues));

if (configure_headersplit(1))
error(1, 0, "Failed to configure header split\n");

if (!bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys))
if (!bind_rx_queue(ifindex, mem->fd,
calloc(num_queues, sizeof(struct netdev_queue_id)),
num_queues, &ys))
error(1, 0, "Binding empty queues array should have failed\n");

for (i = 0; i < num_queues; i++) {
queues[i]._present.type = 1;
queues[i]._present.id = 1;
queues[i].type = NETDEV_QUEUE_TYPE_RX;
queues[i].id = start_queue + i;
}

if (configure_headersplit(0))
error(1, 0, "Failed to configure header split\n");

if (!bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys))
if (!bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys))
error(1, 0, "Configure dmabuf with header split off should have failed\n");

if (configure_headersplit(1))
error(1, 0, "Failed to configure header split\n");

for (i = 0; i < num_queues; i++) {
queues[i]._present.type = 1;
queues[i]._present.id = 1;
queues[i].type = NETDEV_QUEUE_TYPE_RX;
queues[i].id = start_queue + i;
}

if (bind_rx_queue(ifindex, mem->fd, queues, num_queues, &ys))
if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys))
error(1, 0, "Failed to bind\n");

/* Deactivating a bound queue should not be legal */
Expand Down

0 comments on commit 97c4e09

Please sign in to comment.