[PATCH net 1/1] inet_diag: cap bytecode filter complexity
From: Zihan Xi <hidden>
Date: 2026-09-07 13:53:23
Also in:
lkml, stable
Subsystem:
networking [general], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
inet_diag dumps run request-supplied bytecode through inet_diag_bc_sk()
while walking TCP, UDP and MPTCP hash buckets under their bucket locks.
The auditor currently accepts an arbitrarily long program, so a dump
can spend unbounded time in that locked section.
That fact is already present at the git epoch: tcpdiag_bc_audit() had
no op cap, and tcpdiag_dump() ran the bytecode under the listener and
ehash locks. Later inet_diag extraction only moved the same code.
ss(8) filters only need a handful of compare/host/mark operations.
Reject programs with more than 64 ops in inet_diag_bc_audit() so TCP,
UDP and MPTCP dumps share the same limit. 64 is a policy cap above a
normal ss(8) filter, not a lock-hold budget.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Vega <redacted>
Assisted-by: LLM
Co-developed-by: Luxing Yin <redacted>
Signed-off-by: Luxing Yin <redacted>
Signed-off-by: Zihan Xi <redacted>
---
net/ipv4/inet_diag.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 34b77aa87d0a4..1ca528cd3e72b 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c@@ -725,6 +725,12 @@ static bool valid_cgroupcond(const struct inet_diag_bc_op *op, int len, } #endif +/* ss(8) filters only need a handful of compare/host/mark ops. + * Bound the program so dump walks cannot run an arbitrarily long + * bytecode sequence under the socket hash bucket locks. + */ +#define INET_DIAG_BC_MAX_OPS 64 + static int inet_diag_bc_audit(struct inet_diag_dump_data *cb_data, const struct sk_buff *skb) {
@@ -732,6 +738,7 @@ static int inet_diag_bc_audit(struct inet_diag_dump_data *cb_data, const void *bytecode, *bc; int bytecode_len, len; bool net_admin; + int ops = 0; if (!attr) return 0;
@@ -747,6 +754,9 @@ static int inet_diag_bc_audit(struct inet_diag_dump_data *cb_data, int min_len = sizeof(struct inet_diag_bc_op); const struct inet_diag_bc_op *op = bc; + if (++ops > INET_DIAG_BC_MAX_OPS) + return -EINVAL; + switch (op->code) { case INET_DIAG_BC_S_COND: case INET_DIAG_BC_D_COND:
--
2.43.0