[PATCH net-next v3 4/5] net/sched: sch_taprio: cap the number of schedule entries
flat view
COOLING6d
REVIEWED: 1 (0M)
From: Jamal Hadi Salim <jhs@mojatatu.com>
Date: 2026-10-13 08:54:49
Subsystem:
cbs/etf/taprio qdiscs, networking [general], tc subsystem, the rest · Maintainers:
Vinicius Costa Gomes, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Jamal Hadi Salim, Jiri Pirko, Linus Torvalds
1 review trailer.
parse_sched_list() accepts _any number_ of TCA_TAPRIO_SCHED_ENTRY elements. The only bound is the enclosing nlattr u16 nla_len. A minimal accepted entry is 12 bytes (the entry nest plus TCA_TAPRIO_SCHED_ENTRY_INTERVAL), so that u16 admits roughly 5460 entries - protocol-bounded amplification, not truly unbounded, but far past any hardware schedule. The bug: Each entry is a separate sched_entry allocation (368 bytes, rounded up to the kmalloc-512 bucket) and, in full offload, is also composed into a per-entry offload array, so the largest representable minimal list pins roughly 2.7 MiB for the lifetime of the schedule. Some context: The schedule list is not dumped the way the gate action list is: a taprio dump is bounded by the carrying skb (the 32K dump skb, and NLMSG_GOODSIZE for notify and unicast get), which keeps the plain nla_nest_end() closes from ever seeing a wrapped length. But the input-side amplification is the same class as the act_gate entry list, and the offload interface composes every supplied entry into the hardware schedule table without a capacity check. The top of the accepted band cannot be read back: a schedule above roughly 900 entries does not fit the 32K dump skb, so "tc qdisc show" fails loudly with -EMSGSIZE for it (as the action-dump patch does). The pre-existing silent gaps - no change notification above about 100 entries, and no unicast get reply - are tracked separately. The Cap: Cap the list at 1024 entries. This matches the SJA1105 schedule-table capacity (SJA1110 provides 4096) and the act_gate entry cap, and keeps the list inside the current 16-bit TLV format. This is an operational cap on a configuration the uAPI accepted before, so it is net-next hardening; a stable backport would start rejecting taprio configurations that install today. Conditions to recreate the bug: CAP_NET_ADMIN with CONFIG_NET_SCH_TAPRIO=y. Install a taprio qdisc with more than 1024 minimal TCA_TAPRIO_SCHED_ENTRY elements over a raw netlink RTM_NEWQDISC request. The cap rejects the list with -E2BIG and an extack naming the limit; 1024 entries install. Reviewed-by: Victor Nogueira <redacted> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> --- net/sched/sch_taprio.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 39ac5b97aa3a..8e7fb6d0fc00 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c@@ -49,6 +49,13 @@ static struct static_key_false taprio_have_working_mqprio; */ #define TAPRIO_PICOS_PER_BYTE_MIN 17 +/* Each entry is a separate 368-byte sched_entry and, in full offload, is + * also composed into a per-entry offload array. The u16 nla_len admits + * roughly 5460 minimal 12-byte entries, pinning ~2 MiB; 1024 matches the + * SJA1105 schedule-table capacity (SJA1110 provides 4096) and the act_gate cap. + */ +#define TAPRIO_ENTRIES_MAX 1024U + struct sched_entry { /* Durations between this GCL entry and the GCL entry where the * respective traffic class gate closes
@@ -1105,6 +1112,13 @@ static int parse_sched_list(struct taprio_sched *q, struct nlattr *list, continue; } + if (i >= TAPRIO_ENTRIES_MAX) { + NL_SET_ERR_MSG_FMT(extack, + "Too many schedule entries, at most %u are supported", + TAPRIO_ENTRIES_MAX); + return -E2BIG; + } + entry = kzalloc_obj(*entry); if (!entry) { NL_SET_ERR_MSG(extack, "Not enough memory for entry");
--
2.43.0