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 --- 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