Thread (12 messages) 12 messages, 2 authors, 6d ago

[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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help