* [PATCH] net/sched: act_gate: Limit the max value for cycletime [not found] <6a83310d.dbb3a75c.20434b.0069.GAE@google.com> @ 2026-08-18 10:44 ` Edward Adam Davis 2026-08-22 20:20 ` Jakub Kicinski 0 siblings, 1 reply; 10+ messages in thread From: Edward Adam Davis @ 2026-08-18 10:44 UTC (permalink / raw) To: syzbot+0054fed3dc9085390f51 Cc: jhs, jiri, davem, edumazet, kuba, pabeni, horms, Po.Liu, netdev, linux-kernel, syzkaller-bugs If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, an overflow occurs during the assignment of cycle in gate_timer_func(): cycle = p->tcfg_cycletime; // overflow, cycle = -1 Since the local variable cycle is declared as ktime_t (i.e., s64), the assignment overflows. This leads to an incorrect calculation of the close_time value. Ultimately, the new hrtimer expiry time becomes less than now, causing __hrtimer_run_queues() to execute the "timer callback" for an excessively long period, which triggers a soft lockup. [1] Another factor is that the passed interval value is 1; while this accelerates the problematic progression of close_time, it is not the decisive factor in the issue described in [1]. When initializing cycletime, ensuring its value does not exceed S64_MAX guarantees that the hrtimer can correctly calculate a valid expiry time. [1] watchdog: BUG: soft lockup - CPU#1 stuck for 3s! [syz-executor291:5020] pc : seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:76 Call trace: arch_local_irq_restore arch/arm64/include/asm/irqflags.h:195 [inline] (P) seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:75 (P) ktime_get+0x68/0x218 kernel/time/timekeeping.c:971 gate_get_time+0x1c/0xa4 net/sched/act_gate.c:23 gate_timer_func+0x1a8/0x390 net/sched/act_gate.c:101 __run_hrtimer kernel/time/hrtimer.c:2032 [inline] __hrtimer_run_queues+0x314/0xbe0 kernel/time/hrtimer.c:2096 hrtimer_run_softirq+0x15c/0x21c kernel/time/hrtimer.c:2113 handle_softirqs+0x2ec/0xd98 kernel/softirq.c:622 __do_softirq+0x14/0x20 kernel/softirq.c:656 ____do_softirq+0x14/0x20 arch/arm64/kernel/irq.c:78 call_on_irq_stack+0x30/0x48 arch/arm64/kernel/entry.S:885 do_softirq_own_stack+0x20/0x2c arch/arm64/kernel/irq.c:83 invoke_softirq kernel/softirq.c:503 [inline] __irq_exit_rcu+0x1ac/0x428 kernel/softirq.c:735 irq_exit_rcu+0x14/0x84 kernel/softirq.c:752 __el1_irq arch/arm64/kernel/entry-common.c:531 [inline] el1_interrupt+0x40/0x60 arch/arm64/kernel/entry-common.c:543 el1h_64_irq_handler+0x18/0x24 arch/arm64/kernel/entry-common.c:548 el1h_64_irq+0x6c/0x70 arch/arm64/kernel/entry.S:586 __daif_local_irq_enable arch/arm64/include/asm/irqflags.h:26 [inline] (P) arch_local_irq_enable arch/arm64/include/asm/irqflags.h:48 [inline] (P) __local_bh_enable_ip+0x1f0/0x35c kernel/softirq.c:455 (P) local_bh_enable include/linux/bottom_half.h:33 [inline] __alloc_skb+0x1c8/0x610 net/core/skbuff.c:699 alloc_skb include/linux/skbuff.h:1384 [inline] alloc_skb_with_frags+0xb8/0x690 net/core/skbuff.c:6775 sock_alloc_send_pskb+0x740/0x850 net/core/sock.c:3012 unix_dgram_sendmsg+0x434/0x1078 net/unix/af_unix.c:2137 sock_sendmsg_nosec net/socket.c:775 [inline] Fixes: a51c328df310 ("net: qos: introduce a gate control flow action") Reported-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0054fed3dc9085390f51 Tested-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com Signed-off-by: Edward Adam Davis <eadavis@qq.com> --- net/sched/act_gate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c index fdbfcaa3e2ab..ad5a6d75bbda 100644 --- a/net/sched/act_gate.c +++ b/net/sched/act_gate.c @@ -501,6 +501,8 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, cycle = ktime_add_ns(cycle, entry->interval); cycletime = cycle; } + if (cycletime > S64_MAX) + cycletime = S64_MAX; p->tcfg_cycletime = cycletime; p->tcfg_cycletime_ext = cycletime_ext; -- 2.43.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] net/sched: act_gate: Limit the max value for cycletime 2026-08-18 10:44 ` [PATCH] net/sched: act_gate: Limit the max value for cycletime Edward Adam Davis @ 2026-08-22 20:20 ` Jakub Kicinski 2026-08-23 4:07 ` [PATCH v2] " Edward Adam Davis 0 siblings, 1 reply; 10+ messages in thread From: Jakub Kicinski @ 2026-08-22 20:20 UTC (permalink / raw) To: eadavis Cc: Jakub Kicinski, syzbot+0054fed3dc9085390f51, jhs, jiri, davem, edumazet, pabeni, horms, Po.Liu, netdev, linux-kernel, syzkaller-bugs This is an AI-generated review of your patch. The human sending this email has considered the AI review valid, or at least plausible. --- net/sched: act_gate: Limit the max value for cycletime The patch clamps a user supplied TCA_GATE_CYCLE_TIME to S64_MAX in tcf_gate_init() before storing it in p->tcfg_cycletime, so that the ktime_t (s64) arithmetic used to compute gate close times does not see a negative cycle. It is tagged as the fix for a syzbot soft lockup inside gate_timer_func(). Closes: https://syzkaller.appspot.com/bug?extid=0054fed3dc9085390f51 > diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c > index fdbfcaa3e2ab..ad5a6d75bbda 100644 > --- a/net/sched/act_gate.c > +++ b/net/sched/act_gate.c > @@ -501,6 +501,8 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, > cycle = ktime_add_ns(cycle, entry->interval); > cycletime = cycle; > } > + if (cycletime > S64_MAX) > + cycletime = S64_MAX; [Severity: High] This isn't a bug introduced by this patch, since cycletime == S64_MAX combined with a non-zero basetime already wrapped before it, but does clamping to S64_MAX actually close the reported soft lockup? The consumers do not use the cycle value on its own, they compute an absolute expiry as base + (n + 1) * cycle with plain signed ktime arithmetic: net/sched/act_gate.c:gate_get_start_time() { ... cycle = param->tcfg_cycletime; n = div64_u64(ktime_sub_ns(now, base), cycle); *start = ktime_add_ns(base, (n + 1) * cycle); } With cycle == S64_MAX and any non-zero basetime that is not in the future, div64_u64(now - base, S64_MAX) is 0, so the addition is base + S64_MAX and wraps negative (for a basetime of 1000 ns, start becomes S64_MIN + 1000). gate_start_timer() then takes min_t(ktime_t, start, expires) and arms the timer with that past absolute value in HRTIMER_MODE_ABS_SOFT. gate_timer_func() recomputes the same wrapped value on every invocation: net/sched/act_gate.c:gate_timer_func() { ... if (ktime_after(now, close_time)) { cycle = p->tcfg_cycletime; base = ns_to_ktime(p->tcfg_basetime); n = div64_u64(ktime_sub_ns(now, base), cycle); close_time = ktime_add_ns(base, (n + 1) * cycle); } ... hrtimer_set_expires(&gact->hitimer, close_time); ... return HRTIMER_RESTART; } Since the expiry never advances past now, doesn't __hrtimer_run_queues() keep re-running the callback in the same softirq pass, reproducing the watchdog trace quoted in the changelog? Only basetime == 0 self-corrects, because 0 + S64_MAX stays positive, which would explain why the syzbot reproducer no longer trips; adding a base-time of 1000 appears to trip it again. Two follow-on effects of that loop: gate_timer_func() re-takes gact->tcf_lock on every iteration, and hrtimer_cancel() in tcf_gate_cleanup() (and on the replace path in tcf_gate_init()) can never see the perpetually re-armed timer dequeued, so the params and entry list are never handed to call_rcu(&p->rcu, tcf_gate_params_free_rcu). Note also that TCA_GATE_BASE_TIME is read with a plain nla_get_u64() and gate_policy declares it as unrestricted NLA_U64, so any basetime/cycletime pair whose sum exceeds S64_MAX wraps the same way, for example cycletime = 2^62 with basetime = 3 * 2^62. Would bounding the computed expiry instead (basetime + cycletime <= KTIME_MAX), or rejecting the input in a narrower range as sch_taprio does, be a better fit? Related to this, the changelog says: When initializing cycletime, ensuring its value does not exceed S64_MAX guarantees that the hrtimer can correctly calculate a valid expiry time. Given the wrap in base + (n + 1) * cycle above, is that guarantee accurate for non-zero basetime? [Severity: Medium] Should an out-of-range cycle time be rejected rather than silently rewritten? gate_policy declares the attribute with no range restriction: [TCA_GATE_CYCLE_TIME] = { .type = NLA_U64 }, and tcf_gate_dump() echoes the stored value back in the same attribute: if (nla_put_u64_64bit(skb, TCA_GATE_CYCLE_TIME, p->tcfg_cycletime, TCA_GATE_PAD)) so a request with cycle-time 0xffffffffffffffff now succeeds, while a subsequent dump reports S64_MAX. There is no -EINVAL, no NL_SET_BAD_ATTR and no extack message on that path. A later replace that omits the attribute also inherits the rewritten value: net/sched/act_gate.c:tcf_gate_init() { ... if (!err && !tb[TCA_GATE_CYCLE_TIME]) cycletime = cur_p->tcfg_cycletime; ... } Every other invalid input in this file is rejected with -EINVAL plus extack (interval == 0 in fill_gate_entry(), bad clockid in gate_clock_resolve(), empty entry list), and the same knob in sch_taprio is rejected rather than clamped: net/sched/sch_taprio.c:parse_taprio_schedule() { ... if (cycle < 0 || cycle > INT_MAX) { NL_SET_ERR_MSG(extack, "'cycle_time' is too big"); return -EINVAL; } ... } The branch immediately above the new check cannot exceed S64_MAX, since intervals are non-zero u32 values and roughly 2^31 entries would be needed, so the check only covers the user supplied attribute. Could it move to the parse stage and return -EINVAL with NL_SET_BAD_ATTR on TCA_GATE_CYCLE_TIME instead? > p->tcfg_cycletime = cycletime; > p->tcfg_cycletime_ext = cycletime_ext; > -- pw-bot: cr ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2] net/sched: act_gate: Limit the max value for cycletime 2026-08-22 20:20 ` Jakub Kicinski @ 2026-08-23 4:07 ` Edward Adam Davis 2026-08-25 8:25 ` Jamal Hadi Salim 0 siblings, 1 reply; 10+ messages in thread From: Edward Adam Davis @ 2026-08-23 4:07 UTC (permalink / raw) To: kuba Cc: Po.Liu, davem, eadavis, edumazet, horms, jhs, jiri, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, an overflow occurs during the assignment of cycle in gate_timer_func(): cycle = p->tcfg_cycletime; // overflow, cycle = -1 Since the local variable cycle is declared as ktime_t (i.e., s64), the assignment overflows. This leads to an incorrect calculation of the close_time value. Ultimately, the new hrtimer expiry time becomes less than now, causing __hrtimer_run_queues() to execute the "timer callback" for an excessively long period, which triggers a soft lockup. [1] Another factor is that the passed interval value is 1; while this accelerates the problematic progression of close_time, it is not the decisive factor in the issue described in [1]. When initializing cycletime, ensuring its value does not exceed INT_MAX guarantees that the hrtimer can correctly calculate a valid expiry time. [1] watchdog: BUG: soft lockup - CPU#1 stuck for 3s! [syz-executor291:5020] pc : seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:76 Call trace: arch_local_irq_restore arch/arm64/include/asm/irqflags.h:195 [inline] (P) seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:75 (P) ktime_get+0x68/0x218 kernel/time/timekeeping.c:971 gate_get_time+0x1c/0xa4 net/sched/act_gate.c:23 gate_timer_func+0x1a8/0x390 net/sched/act_gate.c:101 __run_hrtimer kernel/time/hrtimer.c:2032 [inline] __hrtimer_run_queues+0x314/0xbe0 kernel/time/hrtimer.c:2096 hrtimer_run_softirq+0x15c/0x21c kernel/time/hrtimer.c:2113 handle_softirqs+0x2ec/0xd98 kernel/softirq.c:622 __do_softirq+0x14/0x20 kernel/softirq.c:656 ____do_softirq+0x14/0x20 arch/arm64/kernel/irq.c:78 call_on_irq_stack+0x30/0x48 arch/arm64/kernel/entry.S:885 do_softirq_own_stack+0x20/0x2c arch/arm64/kernel/irq.c:83 invoke_softirq kernel/softirq.c:503 [inline] __irq_exit_rcu+0x1ac/0x428 kernel/softirq.c:735 irq_exit_rcu+0x14/0x84 kernel/softirq.c:752 __el1_irq arch/arm64/kernel/entry-common.c:531 [inline] el1_interrupt+0x40/0x60 arch/arm64/kernel/entry-common.c:543 el1h_64_irq_handler+0x18/0x24 arch/arm64/kernel/entry-common.c:548 el1h_64_irq+0x6c/0x70 arch/arm64/kernel/entry.S:586 __daif_local_irq_enable arch/arm64/include/asm/irqflags.h:26 [inline] (P) arch_local_irq_enable arch/arm64/include/asm/irqflags.h:48 [inline] (P) __local_bh_enable_ip+0x1f0/0x35c kernel/softirq.c:455 (P) local_bh_enable include/linux/bottom_half.h:33 [inline] __alloc_skb+0x1c8/0x610 net/core/skbuff.c:699 alloc_skb include/linux/skbuff.h:1384 [inline] alloc_skb_with_frags+0xb8/0x690 net/core/skbuff.c:6775 sock_alloc_send_pskb+0x740/0x850 net/core/sock.c:3012 unix_dgram_sendmsg+0x434/0x1078 net/unix/af_unix.c:2137 sock_sendmsg_nosec net/socket.c:775 [inline] Fixes: a51c328df310 ("net: qos: introduce a gate control flow action") Reported-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0054fed3dc9085390f51 Tested-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com Signed-off-by: Edward Adam Davis <eadavis@qq.com> --- v1 -> v2: return -EINVAL with NL_SET_BAD_ATTR net/sched/act_gate.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c index fdbfcaa3e2ab..30bcf173274c 100644 --- a/net/sched/act_gate.c +++ b/net/sched/act_gate.c @@ -501,6 +501,14 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, cycle = ktime_add_ns(cycle, entry->interval); cycletime = cycle; } + + if (cycletime < 0 || cycletime > INT_MAX) { + NL_SET_ERR_MSG(extack, "'cycle_time' is too big"); + err = -EINVAL; + spin_unlock_bh(&gact->tcf_lock); + goto err_free; + } + p->tcfg_cycletime = cycletime; p->tcfg_cycletime_ext = cycletime_ext; -- 2.43.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2] net/sched: act_gate: Limit the max value for cycletime 2026-08-23 4:07 ` [PATCH v2] " Edward Adam Davis @ 2026-08-25 8:25 ` Jamal Hadi Salim 2026-08-25 9:01 ` Edward Adam Davis 0 siblings, 1 reply; 10+ messages in thread From: Jamal Hadi Salim @ 2026-08-25 8:25 UTC (permalink / raw) To: Edward Adam Davis Cc: kuba, Po.Liu, davem, edumazet, horms, jiri, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs On Sun, Aug 23, 2026 at 12:07 AM Edward Adam Davis <eadavis@qq.com> wrote: > > If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, > an overflow occurs during the assignment of cycle in gate_timer_func(): > > cycle = p->tcfg_cycletime; // overflow, cycle = -1 > > Since the local variable cycle is declared as ktime_t (i.e., s64), > the assignment overflows. > Review the sashiko feedback. At least two of those concerns look legit and need to be addressed: 1) complaint about timer disarm on replace 2) INT_MAX being too narrow cheers, jamal > This leads to an incorrect calculation of the close_time value. > Ultimately, the new hrtimer expiry time becomes less than now, causing > __hrtimer_run_queues() to execute the "timer callback" for an excessively > long period, which triggers a soft lockup. [1] > > Another factor is that the passed interval value is 1; while this accelerates > the problematic progression of close_time, it is not the decisive factor in > the issue described in [1]. > > When initializing cycletime, ensuring its value does not exceed INT_MAX > guarantees that the hrtimer can correctly calculate a valid expiry time. > > [1] > watchdog: BUG: soft lockup - CPU#1 stuck for 3s! [syz-executor291:5020] > pc : seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:76 > Call trace: > arch_local_irq_restore arch/arm64/include/asm/irqflags.h:195 [inline] (P) > seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:75 (P) > ktime_get+0x68/0x218 kernel/time/timekeeping.c:971 > gate_get_time+0x1c/0xa4 net/sched/act_gate.c:23 > gate_timer_func+0x1a8/0x390 net/sched/act_gate.c:101 > __run_hrtimer kernel/time/hrtimer.c:2032 [inline] > __hrtimer_run_queues+0x314/0xbe0 kernel/time/hrtimer.c:2096 > hrtimer_run_softirq+0x15c/0x21c kernel/time/hrtimer.c:2113 > handle_softirqs+0x2ec/0xd98 kernel/softirq.c:622 > __do_softirq+0x14/0x20 kernel/softirq.c:656 > ____do_softirq+0x14/0x20 arch/arm64/kernel/irq.c:78 > call_on_irq_stack+0x30/0x48 arch/arm64/kernel/entry.S:885 > do_softirq_own_stack+0x20/0x2c arch/arm64/kernel/irq.c:83 > invoke_softirq kernel/softirq.c:503 [inline] > __irq_exit_rcu+0x1ac/0x428 kernel/softirq.c:735 > irq_exit_rcu+0x14/0x84 kernel/softirq.c:752 > __el1_irq arch/arm64/kernel/entry-common.c:531 [inline] > el1_interrupt+0x40/0x60 arch/arm64/kernel/entry-common.c:543 > el1h_64_irq_handler+0x18/0x24 arch/arm64/kernel/entry-common.c:548 > el1h_64_irq+0x6c/0x70 arch/arm64/kernel/entry.S:586 > __daif_local_irq_enable arch/arm64/include/asm/irqflags.h:26 [inline] (P) > arch_local_irq_enable arch/arm64/include/asm/irqflags.h:48 [inline] (P) > __local_bh_enable_ip+0x1f0/0x35c kernel/softirq.c:455 (P) > local_bh_enable include/linux/bottom_half.h:33 [inline] > __alloc_skb+0x1c8/0x610 net/core/skbuff.c:699 > alloc_skb include/linux/skbuff.h:1384 [inline] > alloc_skb_with_frags+0xb8/0x690 net/core/skbuff.c:6775 > sock_alloc_send_pskb+0x740/0x850 net/core/sock.c:3012 > unix_dgram_sendmsg+0x434/0x1078 net/unix/af_unix.c:2137 > sock_sendmsg_nosec net/socket.c:775 [inline] > > Fixes: a51c328df310 ("net: qos: introduce a gate control flow action") > Reported-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=0054fed3dc9085390f51 > Tested-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com > Signed-off-by: Edward Adam Davis <eadavis@qq.com> > --- > v1 -> v2: return -EINVAL with NL_SET_BAD_ATTR > > net/sched/act_gate.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c > index fdbfcaa3e2ab..30bcf173274c 100644 > --- a/net/sched/act_gate.c > +++ b/net/sched/act_gate.c > @@ -501,6 +501,14 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, > cycle = ktime_add_ns(cycle, entry->interval); > cycletime = cycle; > } > + > + if (cycletime < 0 || cycletime > INT_MAX) { > + NL_SET_ERR_MSG(extack, "'cycle_time' is too big"); > + err = -EINVAL; > + spin_unlock_bh(&gact->tcf_lock); > + goto err_free; > + } > + > p->tcfg_cycletime = cycletime; > p->tcfg_cycletime_ext = cycletime_ext; > > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2] net/sched: act_gate: Limit the max value for cycletime 2026-08-25 8:25 ` Jamal Hadi Salim @ 2026-08-25 9:01 ` Edward Adam Davis 2026-08-25 9:31 ` Jamal Hadi Salim 0 siblings, 1 reply; 10+ messages in thread From: Edward Adam Davis @ 2026-08-25 9:01 UTC (permalink / raw) To: jhs Cc: Po.Liu, davem, eadavis, edumazet, horms, jiri, kuba, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs On Tue, 25 Aug 2026 04:25:04 -0400, Jamal Hadi Salim <jhs@mojatatu.com> wrote: > On Sun, Aug 23, 2026 at 12:07 AM Edward Adam Davis <eadavis@qq.com> wrote: > > > > If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, > > an overflow occurs during the assignment of cycle in gate_timer_func(): > > > > cycle = p->tcfg_cycletime; // overflow, cycle = -1 > > > > Since the local variable cycle is declared as ktime_t (i.e., s64), > > the assignment overflows. > > > > Review the sashiko feedback. At least two of those concerns look legit > and need to be addressed: > 1) complaint about timer disarm on replace 2) INT_MAX being too narrow I haven't received any feedback regarding sashiko, and I didn't quite understand the points made in item 1); could you please provide more details? Regarding item 2), if INT_MAX is too narrow, do you have a suitable value to recommend? S64_MAX? cheers, Edward ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2] net/sched: act_gate: Limit the max value for cycletime 2026-08-25 9:01 ` Edward Adam Davis @ 2026-08-25 9:31 ` Jamal Hadi Salim 2026-08-25 12:08 ` Edward Adam Davis 0 siblings, 1 reply; 10+ messages in thread From: Jamal Hadi Salim @ 2026-08-25 9:31 UTC (permalink / raw) To: Edward Adam Davis Cc: Po.Liu, davem, edumazet, horms, jiri, kuba, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs On Tue, Aug 25, 2026 at 5:01 AM Edward Adam Davis <eadavis@qq.com> wrote: > > On Tue, 25 Aug 2026 04:25:04 -0400, Jamal Hadi Salim <jhs@mojatatu.com> wrote: > > On Sun, Aug 23, 2026 at 12:07 AM Edward Adam Davis <eadavis@qq.com> wrote: > > > > > > If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, > > > an overflow occurs during the assignment of cycle in gate_timer_func(): > > > > > > cycle = p->tcfg_cycletime; // overflow, cycle = -1 > > > > > > Since the local variable cycle is declared as ktime_t (i.e., s64), > > > the assignment overflows. > > > > > > > Review the sashiko feedback. At least two of those concerns look legit > > and need to be addressed: > > 1) complaint about timer disarm on replace 2) INT_MAX being too narrow > I haven't received any feedback regarding sashiko, and I didn't quite > understand the points made in item 1); could you please provide more > details? You should always look at patchwork for reviews from the AIs - i just happened to have cycles and peeked and even my responses are best effort. Some maintainers forward AI reviews on a best-effort basis (Jakub forwarded you the v1 review), so you may end up getting radio silence if nobody has time. So, going forward, the first line of defense is to look at patchwork 24 hours + after you post your patch. Address those by sending a new version or rebut them on the list. > Regarding item 2), if INT_MAX is too narrow, do you have a suitable value > to recommend? S64_MAX? Handwave: The safe bound is one that keeps base + cycletime <= KTIME_MAX. To be verbose per sashiko: cycletime is an unrestricted NLA_U64 consumed as ktime_t (s64). A 200 s cycle time does not overflow any s64 arithmetic, but your v2 rejects it. tdc test a721 (tools/testing/selftests/tc-testing/tc-tests/actions/gate.json) uses cycle-time 200000000000ns and expects success; your v2 breaks it. sch_taprio uses INT_MAX but its semantics/tests differ. S64_MAX is the actual overflow boundary (U64_MAX is what makes the s64 go negative); but even S64_MAX + a non-zero basetime wraps in base + (n+1)*cycle > cheers, > Edward > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2] net/sched: act_gate: Limit the max value for cycletime 2026-08-25 9:31 ` Jamal Hadi Salim @ 2026-08-25 12:08 ` Edward Adam Davis 2026-08-25 12:13 ` [PATCH v3] " Edward Adam Davis 0 siblings, 1 reply; 10+ messages in thread From: Edward Adam Davis @ 2026-08-25 12:08 UTC (permalink / raw) To: jhs Cc: Po.Liu, davem, eadavis, edumazet, horms, jiri, kuba, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs On Tue, 25 Aug 2026 05:31:28 -0400, Jamal Hadi Salim <jhs@mojatatu.com> wrote: > On Tue, Aug 25, 2026 at 5:01 AM Edward Adam Davis <eadavis@qq.com> wrote: > > > > On Tue, 25 Aug 2026 04:25:04 -0400, Jamal Hadi Salim <jhs@mojatatu.com> wrote: > > > On Sun, Aug 23, 2026 at 12:07 AM Edward Adam Davis <eadavis@qq.com> wrote: > > > > > > > > If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, > > > > an overflow occurs during the assignment of cycle in gate_timer_func(): > > > > > > > > cycle = p->tcfg_cycletime; // overflow, cycle = -1 > > > > > > > > Since the local variable cycle is declared as ktime_t (i.e., s64), > > > > the assignment overflows. > > > > > > > > > > Review the sashiko feedback. At least two of those concerns look legit > > > and need to be addressed: > > > 1) complaint about timer disarm on replace 2) INT_MAX being too narrow > > I haven't received any feedback regarding sashiko, and I didn't quite > > understand the points made in item 1); could you please provide more > > details? > > You should always look at patchwork for reviews from the AIs - i just > happened to have cycles and peeked and even my responses are best > effort. Some maintainers forward AI reviews on a best-effort basis > (Jakub forwarded you the v1 review), so you may end up getting radio > silence if nobody has time. So, going forward, the first line of > defense is to look at patchwork 24 hours + after you post your patch. > Address those by sending a new version or rebut them on the list. > > Regarding item 2), if INT_MAX is too narrow, do you have a suitable value > > to recommend? S64_MAX? > > Handwave: The safe bound is one that keeps base + cycletime <= KTIME_MAX. > To be verbose per sashiko: > cycletime is an unrestricted NLA_U64 consumed as ktime_t (s64). A 200 > s cycle time does not overflow any s64 arithmetic, but your v2 rejects > it. tdc test a721 > (tools/testing/selftests/tc-testing/tc-tests/actions/gate.json) uses > cycle-time 200000000000ns and expects success; your v2 breaks it. > sch_taprio uses INT_MAX but its semantics/tests differ. S64_MAX is the > actual overflow boundary (U64_MAX is what makes the s64 go negative); > but even S64_MAX + a non-zero basetime wraps in base + (n+1)*cycle Got it, thanks. BR, Edward ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3] net/sched: act_gate: Limit the max value for cycletime 2026-08-25 12:08 ` Edward Adam Davis @ 2026-08-25 12:13 ` Edward Adam Davis 2026-08-27 19:15 ` Jakub Kicinski 2026-08-27 19:17 ` Jakub Kicinski 0 siblings, 2 replies; 10+ messages in thread From: Edward Adam Davis @ 2026-08-25 12:13 UTC (permalink / raw) To: eadavis Cc: Po.Liu, davem, edumazet, horms, jhs, jiri, kuba, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs If the user passes a cycletime value of 0xFFFFFFFFFFFFFFFFULL, an overflow occurs during the assignment of cycle in gate_timer_func(): cycle = p->tcfg_cycletime; // overflow, cycle = -1 Since the local variable cycle is declared as ktime_t (i.e., s64), the assignment overflows. This leads to an incorrect calculation of the close_time value. Ultimately, the new hrtimer expiry time becomes less than now, causing __hrtimer_run_queues() to execute the "timer callback" for an excessively long period, which triggers a soft lockup. [1] Another factor is that the passed interval value is 1; while this accelerates the problematic progression of close_time, it is not the decisive factor in the issue described in [1]. Modify the cycletime range in the policy to (0, S64_MAX), when parsing cycletime, ensuring its value does not exceed S64_MAX guarantees that the hrtimer can correctly calculate a valid expiry time. [1] watchdog: BUG: soft lockup - CPU#1 stuck for 3s! [syz-executor291:5020] pc : seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:76 Call trace: arch_local_irq_restore arch/arm64/include/asm/irqflags.h:195 [inline] (P) seqcount_lockdep_reader_access+0xd8/0xf8 include/linux/seqlock.h:75 (P) ktime_get+0x68/0x218 kernel/time/timekeeping.c:971 gate_get_time+0x1c/0xa4 net/sched/act_gate.c:23 gate_timer_func+0x1a8/0x390 net/sched/act_gate.c:101 __run_hrtimer kernel/time/hrtimer.c:2032 [inline] __hrtimer_run_queues+0x314/0xbe0 kernel/time/hrtimer.c:2096 hrtimer_run_softirq+0x15c/0x21c kernel/time/hrtimer.c:2113 handle_softirqs+0x2ec/0xd98 kernel/softirq.c:622 __do_softirq+0x14/0x20 kernel/softirq.c:656 ____do_softirq+0x14/0x20 arch/arm64/kernel/irq.c:78 call_on_irq_stack+0x30/0x48 arch/arm64/kernel/entry.S:885 do_softirq_own_stack+0x20/0x2c arch/arm64/kernel/irq.c:83 invoke_softirq kernel/softirq.c:503 [inline] __irq_exit_rcu+0x1ac/0x428 kernel/softirq.c:735 irq_exit_rcu+0x14/0x84 kernel/softirq.c:752 __el1_irq arch/arm64/kernel/entry-common.c:531 [inline] el1_interrupt+0x40/0x60 arch/arm64/kernel/entry-common.c:543 el1h_64_irq_handler+0x18/0x24 arch/arm64/kernel/entry-common.c:548 el1h_64_irq+0x6c/0x70 arch/arm64/kernel/entry.S:586 __daif_local_irq_enable arch/arm64/include/asm/irqflags.h:26 [inline] (P) arch_local_irq_enable arch/arm64/include/asm/irqflags.h:48 [inline] (P) __local_bh_enable_ip+0x1f0/0x35c kernel/softirq.c:455 (P) local_bh_enable include/linux/bottom_half.h:33 [inline] __alloc_skb+0x1c8/0x610 net/core/skbuff.c:699 alloc_skb include/linux/skbuff.h:1384 [inline] alloc_skb_with_frags+0xb8/0x690 net/core/skbuff.c:6775 sock_alloc_send_pskb+0x740/0x850 net/core/sock.c:3012 unix_dgram_sendmsg+0x434/0x1078 net/unix/af_unix.c:2137 sock_sendmsg_nosec net/socket.c:775 [inline] Fixes: a51c328df310 ("net: qos: introduce a gate control flow action") Reported-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0054fed3dc9085390f51 Tested-by: syzbot+0054fed3dc9085390f51@syzkaller.appspotmail.com Signed-off-by: Edward Adam Davis <eadavis@qq.com> --- v1 -> v2: return -EINVAL with NL_SET_BAD_ATTR v2 -> v3: using policy to limit cycletime range net/sched/act_gate.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c index fdbfcaa3e2ab..4c4a0f80dec1 100644 --- a/net/sched/act_gate.c +++ b/net/sched/act_gate.c @@ -166,13 +166,19 @@ static const struct nla_policy entry_policy[TCA_GATE_ENTRY_MAX + 1] = { [TCA_GATE_ENTRY_MAX_OCTETS] = { .type = NLA_S32 }, }; +static const struct netlink_range_validation_signed gate_cycle_time_range = { + .min = 0, + .max = S64_MAX, +}; + static const struct nla_policy gate_policy[TCA_GATE_MAX + 1] = { [TCA_GATE_PARMS] = NLA_POLICY_EXACT_LEN(sizeof(struct tc_gate)), [TCA_GATE_PRIORITY] = { .type = NLA_S32 }, [TCA_GATE_ENTRY_LIST] = { .type = NLA_NESTED }, [TCA_GATE_BASE_TIME] = { .type = NLA_U64 }, - [TCA_GATE_CYCLE_TIME] = { .type = NLA_U64 }, + [TCA_GATE_CYCLE_TIME] = + NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &gate_cycle_time_range), [TCA_GATE_CYCLE_TIME_EXT] = { .type = NLA_U64 }, [TCA_GATE_FLAGS] = { .type = NLA_U32 }, [TCA_GATE_CLOCKID] = { .type = NLA_S32 }, @@ -501,6 +507,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, cycle = ktime_add_ns(cycle, entry->interval); cycletime = cycle; } + p->tcfg_cycletime = cycletime; p->tcfg_cycletime_ext = cycletime_ext; -- 2.43.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3] net/sched: act_gate: Limit the max value for cycletime 2026-08-25 12:13 ` [PATCH v3] " Edward Adam Davis @ 2026-08-27 19:15 ` Jakub Kicinski 2026-08-27 19:17 ` Jakub Kicinski 1 sibling, 0 replies; 10+ messages in thread From: Jakub Kicinski @ 2026-08-27 19:15 UTC (permalink / raw) To: eadavis Cc: Jakub Kicinski, Po.Liu, davem, edumazet, horms, jhs, jiri, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs This is an AI-generated review of your patch. The human sending this email has considered the AI review valid, or at least plausible. --- net/sched: act_gate: Limit the max value for cycletime This changes the act_gate netlink policy so that TCA_GATE_CYCLE_TIME is validated with NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64) against a range of 0 to S64_MAX, with the intent of preventing an s64 overflow in gate_timer_func() that led to a soft lockup reported by syzbot. Closes: https://syzkaller.appspot.com/bug?extid=0054fed3dc9085390f51 A couple of questions on the changelog and on the diff below. > Modify the cycletime range in the policy to (0, S64_MAX), when parsing > cycletime, ensuring its value does not exceed S64_MAX guarantees that the > hrtimer can correctly calculate a valid expiry time. [Severity: Low] Should this read [0, S64_MAX] instead of (0, S64_MAX)? gate_cycle_time_range uses .min = 0 and the range check in nla_validate_int_range_signed() is inclusive, so a cycletime of 0 is still accepted, and it keeps its special meaning in tcf_gate_init(): if (!cycletime) { struct tcfg_gate_entry *entry; ktime_t cycle = 0; list_for_each_entry(entry, &p->entries, list) cycle = ktime_add_ns(cycle, entry->interval); cycletime = cycle; } As written, the open interval wording suggests 0 is now rejected, which a backporter might rely on. > diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c > index fdbfcaa3e2ab9..4c4a0f80dec1f 100644 > --- a/net/sched/act_gate.c > +++ b/net/sched/act_gate.c > @@ -166,13 +166,19 @@ static const struct nla_policy entry_policy[TCA_GATE_ENTRY_MAX + 1] = { > [TCA_GATE_ENTRY_MAX_OCTETS] = { .type = NLA_S32 }, > }; > > +static const struct netlink_range_validation_signed gate_cycle_time_range = { > + .min = 0, > + .max = S64_MAX, > +}; > + > static const struct nla_policy gate_policy[TCA_GATE_MAX + 1] = { > [TCA_GATE_PARMS] = > NLA_POLICY_EXACT_LEN(sizeof(struct tc_gate)), > [TCA_GATE_PRIORITY] = { .type = NLA_S32 }, > [TCA_GATE_ENTRY_LIST] = { .type = NLA_NESTED }, > [TCA_GATE_BASE_TIME] = { .type = NLA_U64 }, > - [TCA_GATE_CYCLE_TIME] = { .type = NLA_U64 }, > + [TCA_GATE_CYCLE_TIME] = > + NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &gate_cycle_time_range), [Severity: High] Does capping cycletime at S64_MAX actually remove the soft lockup? The expiry is not computed from cycletime alone. In gate_get_start_time(): base = ns_to_ktime(param->tcfg_basetime); now = gate_get_time(gact); if (ktime_after(base, now)) { *start = base; return; } cycle = param->tcfg_cycletime; n = div64_u64(ktime_sub_ns(now, base), cycle); *start = ktime_add_ns(base, (n + 1) * cycle); TCA_GATE_BASE_TIME is left as { .type = NLA_U64 } with no range, so with basetime = 1 and cycletime = S64_MAX (both accepted by the new policy) n becomes 0 and the addition is 1 + (2^63 - 1), which wraps to S64_MIN since ktime_add_ns() is plain 64-bit addition. gate_start_timer() only clamps downward: start = min_t(ktime_t, start, expires); hrtimer_start(&gact->hitimer, start, HRTIMER_MODE_ABS_SOFT); so the wrapped negative value is armed as an absolute expiry in the past. The catch-up branch of gate_timer_func() then recomputes the same value on every invocation: if (ktime_after(now, close_time)) { ktime_t cycle, base; u64 n; cycle = p->tcfg_cycletime; base = ns_to_ktime(p->tcfg_basetime); n = div64_u64(ktime_sub_ns(now, base), cycle); close_time = ktime_add_ns(base, (n + 1) * cycle); } ... hrtimer_set_expires(&gact->hitimer, close_time); ... return HRTIMER_RESTART; which looks like the same "gate_timer_func in hrtimer_run_softirq" pattern from the report, reachable via RTM_NEWACTION with basetime = 1, cycletime = S64_MAX and one entry with a non-zero interval. A wide band of policy-legal pairs wraps the same way, for example cycletime = S64_MAX - 10 with basetime = 10^12. Would bounding the whole base + (n + 1) * cycle arithmetic be needed here, the way sch_taprio.c does it? static const struct netlink_range_validation_signed taprio_cycle_time_range = { .min = 0, .max = INT_MAX, }; -- pw-bot: cr ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3] net/sched: act_gate: Limit the max value for cycletime 2026-08-25 12:13 ` [PATCH v3] " Edward Adam Davis 2026-08-27 19:15 ` Jakub Kicinski @ 2026-08-27 19:17 ` Jakub Kicinski 1 sibling, 0 replies; 10+ messages in thread From: Jakub Kicinski @ 2026-08-27 19:17 UTC (permalink / raw) To: Edward Adam Davis Cc: Po.Liu, davem, edumazet, horms, jhs, jiri, linux-kernel, netdev, pabeni, syzbot+0054fed3dc9085390f51, syzkaller-bugs On Tue, 25 Aug 2026 20:13:02 +0800 Edward Adam Davis wrote: > static const struct nla_policy gate_policy[TCA_GATE_MAX + 1] = { > [TCA_GATE_PARMS] = > NLA_POLICY_EXACT_LEN(sizeof(struct tc_gate)), > [TCA_GATE_PRIORITY] = { .type = NLA_S32 }, > [TCA_GATE_ENTRY_LIST] = { .type = NLA_NESTED }, > [TCA_GATE_BASE_TIME] = { .type = NLA_U64 }, > - [TCA_GATE_CYCLE_TIME] = { .type = NLA_U64 }, > + [TCA_GATE_CYCLE_TIME] = > + NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &gate_cycle_time_range), Why are you changing the type of the attr? S64_MAX is perfectly fine as range for NLA_U64 > [TCA_GATE_CYCLE_TIME_EXT] = { .type = NLA_U64 }, > [TCA_GATE_FLAGS] = { .type = NLA_U32 }, > [TCA_GATE_CLOCKID] = { .type = NLA_S32 }, > @@ -501,6 +507,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, > cycle = ktime_add_ns(cycle, entry->interval); > cycletime = cycle; > } > + > p->tcfg_cycletime = cycletime; > p->tcfg_cycletime_ext = cycletime_ext; Unrelated noise, please pay more attention. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-08-27 19:17 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <6a83310d.dbb3a75c.20434b.0069.GAE@google.com>
2026-08-18 10:44 ` [PATCH] net/sched: act_gate: Limit the max value for cycletime Edward Adam Davis
2026-08-22 20:20 ` Jakub Kicinski
2026-08-23 4:07 ` [PATCH v2] " Edward Adam Davis
2026-08-25 8:25 ` Jamal Hadi Salim
2026-08-25 9:01 ` Edward Adam Davis
2026-08-25 9:31 ` Jamal Hadi Salim
2026-08-25 12:08 ` Edward Adam Davis
2026-08-25 12:13 ` [PATCH v3] " Edward Adam Davis
2026-08-27 19:15 ` Jakub Kicinski
2026-08-27 19:17 ` Jakub Kicinski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox