Commit 7ca52541 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

net_sched: sch_sfq: reject invalid perturb period



Gerrard Tai reported that SFQ perturb_period has no range check yet,
and this can be used to trigger a race condition fixed in a separate patch.

We want to make sure ctl->perturb_period * HZ will not overflow
and is positive.

Tested:

tc qd add dev lo root sfq perturb -10   # negative value : error
Error: sch_sfq: invalid perturb period.

tc qd add dev lo root sfq perturb 1000000000 # too big : error
Error: sch_sfq: invalid perturb period.

tc qd add dev lo root sfq perturb 2000000 # acceptable value
tc -s -d qd sh dev lo
qdisc sfq 8005: root refcnt 2 limit 127p quantum 64Kb depth 127 flows 128 divisor 1024 perturb 2000000sec
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Reported-by: default avatarGerrard Tai <gerrard.tai@starlabs.sg>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20250611083501.1810459-1-edumazet@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d4e6cb32
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -656,6 +656,14 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
		NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
		return -EINVAL;
	}

	if (ctl->perturb_period < 0 ||
	    ctl->perturb_period > INT_MAX / HZ) {
		NL_SET_ERR_MSG_MOD(extack, "invalid perturb period");
		return -EINVAL;
	}
	perturb_period = ctl->perturb_period * HZ;

	if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max,
					ctl_v1->Wlog, ctl_v1->Scell_log, NULL))
		return -EINVAL;
@@ -672,14 +680,12 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
	headdrop = q->headdrop;
	maxdepth = q->maxdepth;
	maxflows = q->maxflows;
	perturb_period = q->perturb_period;
	quantum = q->quantum;
	flags = q->flags;

	/* update and validate configuration */
	if (ctl->quantum)
		quantum = ctl->quantum;
	perturb_period = ctl->perturb_period * HZ;
	if (ctl->flows)
		maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
	if (ctl->divisor) {