lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260121131954.2710459-6-p@1g4.org>
Date: Wed, 21 Jan 2026 13:20:54 +0000
From: Paul Moses <p@....org>
To: netdev@...r.kernel.org
Cc: Jamal Hadi Salim <jhs@...atatu.com>, Cong Wang <xiyou.wangcong@...il.com>, Jiri Pirko <jiri@...nulli.us>, "David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>, Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>, Simon Horman <horms@...nel.org>, linux-kernel@...r.kernel.org, Paul Moses <p@....org>, stable@...r.kernel.org
Subject: [PATCH net v3 5/7] net/sched: act_gate: cancel timer outside tcf_lock

Move hrtimer_cancel() out from under tcf_lock, cancel only on clockid changes,
and always restart using the newly computed start time. For schedule
replacement, bypass the prior expiry clamp so basetime moves forward
without firing the new schedule early.

Other schedulers explicitly cancel hrtimers on reconfig/teardown, e.g.
sch_taprio advance_timer (commit 44d4775ca51805), sch_dualpi2 pi2_timer
(commit 320d031ad6e4d6), and qdisc_watchdog_cancel() (commit 2fbd3da3877ad8).

Fixes: a51c328df310 ("net: qos: introduce a gate control flow action")
Signed-off-by: Paul Moses <p@....org>
Cc: stable@...r.kernel.org
---
 net/sched/act_gate.c | 52 ++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c
index da4802bbaf4ca..48ff378bb051a 100644
--- a/net/sched/act_gate.c
+++ b/net/sched/act_gate.c
@@ -55,15 +55,17 @@ static void gate_get_start_time(struct tcf_gate *gact,
 	*start = ktime_add_ns(base, (n + 1) * cycle);
 }
 
-static void gate_start_timer(struct tcf_gate *gact, ktime_t start)
+static void gate_start_timer(struct tcf_gate *gact, ktime_t start, bool replace)
 {
 	ktime_t expires;
 
-	expires = hrtimer_get_expires(&gact->hitimer);
-	if (expires == 0)
-		expires = KTIME_MAX;
+	if (!replace) {
+		expires = hrtimer_get_expires(&gact->hitimer);
+		if (expires == 0)
+			expires = KTIME_MAX;
 
-	start = min_t(ktime_t, start, expires);
+		start = min_t(ktime_t, start, expires);
+	}
 
 	hrtimer_start(&gact->hitimer, start, HRTIMER_MODE_ABS_SOFT);
 }
@@ -307,24 +309,9 @@ static int parse_gate_list(struct nlattr *list_attr,
 	return err;
 }
 
-static void gate_setup_timer(struct tcf_gate *gact, u64 basetime,
-			     enum tk_offsets tko, s32 clockid,
-			     bool do_init)
+static void gate_setup_timer(struct tcf_gate *gact,
+			     enum tk_offsets tko, s32 clockid)
 {
-	struct tcf_gate_params *p;
-
-	if (!do_init) {
-		p = rcu_dereference_protected(gact->param,
-					      lockdep_is_held(&gact->tcf_lock));
-		if (basetime == p->tcfg_basetime &&
-		    tko == gact->tk_offset &&
-		    clockid == p->tcfg_clockid)
-			return;
-
-		spin_unlock_bh(&gact->tcf_lock);
-		hrtimer_cancel(&gact->hitimer);
-		spin_lock_bh(&gact->tcf_lock);
-	}
 	gact->tk_offset = tko;
 	hrtimer_setup(&gact->hitimer, gate_timer_func, clockid, HRTIMER_MODE_ABS_SOFT);
 }
@@ -527,8 +514,19 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
 		goto release_mem;
 
 	spin_lock_bh(&gact->tcf_lock);
-	gate_setup_timer(gact, basetime, tk_offset, clockid,
-			 ret == ACT_P_CREATED);
+
+	if (ret == ACT_P_CREATED) {
+		gate_setup_timer(gact, tk_offset, clockid);
+	} else {
+		old_p = rcu_dereference_protected(gact->param,
+						  lockdep_is_held(&gact->tcf_lock));
+		if (!old_p || clockid != old_p->tcfg_clockid) {
+			spin_unlock_bh(&gact->tcf_lock);
+			hrtimer_cancel(&gact->hitimer);
+			spin_lock_bh(&gact->tcf_lock);
+			gate_setup_timer(gact, tk_offset, clockid);
+		}
+	}
 	gate_get_start_time(gact, p, &start);
 
 	old_p = rcu_replace_pointer(gact->param, p,
@@ -542,7 +540,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
 
 	goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
 
-	gate_start_timer(gact, start);
+	gate_start_timer(gact, start, ret != ACT_P_CREATED);
 
 	spin_unlock_bh(&gact->tcf_lock);
 
@@ -562,9 +560,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
 	 * without taking tcf_lock.
 	 */
 	if (ret == ACT_P_CREATED)
-		gate_setup_timer(gact, 0,
-				 gact->tk_offset, 0,
-				 true);
+		gate_setup_timer(gact, gact->tk_offset, 0);
 	tcf_idr_release(*a, bind);
 	return err;
 }
-- 
2.52.GIT



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ