[PATCH net v3 2/3] net/sched: taprio: prevent cycle time extension overflow
From: Krystian Kaniewski
Date: Wed Nov 04 2026 - 09:28:16 EST
cycle_time_extension is an unrestricted signed 64-bit netlink value.
should_change_schedules() and get_interval_end_time() add it to an
absolute time without checking for overflow. A positive extension can
therefore wrap the result negative. The schedule handover test then
ignores an extension that should cover the admin base time. The
txtime-assist path can use the same wrapped value as its extended cycle
boundary.
Add one helper that saturates positive overflow at KTIME_MAX and use it
for both sums. Values that do not overflow, including negative
extensions, keep their existing behavior.
Fixes: c25031e99344 ("taprio: Add support for cycle-time-extension")
Fixes: 4cfd5779bd6e ("taprio: Add support for txtime-assist mode")
Acked-by: Vinicius Costa Gomes <vinicius.gomes@xxxxxxxxx>
Signed-off-by: Krystian Kaniewski <krystianmkaniewski@xxxxxxxxx>
---
v3:
- split the overflow handling from the advance_sched() change (Vinicius)
- use the same helper for the sum in get_interval_end_time()
- add Acked-by from Vinicius
- drop the obsolete Assisted-by trailers
- rebase onto current net/main
v2: https://lore.kernel.org/all/20261009123309.284193-3-krystianmkaniewski@xxxxxxxxx/
net/sched/sch_taprio.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 2a31b189d654e2..e4c937cf74c10f 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -239,6 +239,18 @@ static s32 get_cycle_time_elapsed(struct sched_gate_list *sched, ktime_t time)
return time_elapsed;
}
+/*
+ * Netlink accepts any s64 cycle_time_extension. Saturate positive overflow
+ * so comparisons remain monotonic in end_time.
+ */
+static ktime_t taprio_cycle_ext_end(ktime_t end_time, s64 extension)
+{
+ if (extension > 0 && end_time > KTIME_MAX - extension)
+ return KTIME_MAX;
+
+ return ktime_add_ns(end_time, extension);
+}
+
static ktime_t get_interval_end_time(struct sched_gate_list *sched,
struct sched_gate_list *admin,
struct sched_entry *entry,
@@ -249,7 +261,8 @@ static ktime_t get_interval_end_time(struct sched_gate_list *sched,
cycle_end = ktime_add_ns(intv_start, sched->cycle_time - cycle_elapsed);
intv_end = ktime_add_ns(intv_start, entry->interval);
- cycle_ext_end = ktime_add(cycle_end, sched->cycle_time_extension);
+ cycle_ext_end =
+ taprio_cycle_ext_end(cycle_end, sched->cycle_time_extension);
if (ktime_before(intv_end, cycle_end))
return intv_end;
@@ -916,7 +929,8 @@ static bool should_change_schedules(const struct sched_gate_list *admin,
* next schedule base_time, we can extend the current schedule
* for that amount.
*/
- extension_time = ktime_add_ns(end_time, oper->cycle_time_extension);
+ extension_time = taprio_cycle_ext_end(end_time,
+ oper->cycle_time_extension);
/* FIXME: the IEEE 802.1Q-2018 Specification isn't clear about
* how precisely the extension should be made. So after
--
2.53.0