Skip to content

Commit

Permalink
fq_codel: reject silly quantum parameters
Browse files Browse the repository at this point in the history
[ Upstream commit c7c5e6f ]

syzbot found that forcing a big quantum attribute would crash hosts fast,
essentially using this:

tc qd replace dev eth0 root fq_codel quantum 4294967295

This is because fq_codel_dequeue() would have to loop
~2^31 times in :

	if (flow->deficit <= 0) {
		flow->deficit += q->quantum;
		list_move_tail(&flow->flowchain, &q->old_flows);
		goto begin;
	}

SFQ max quantum is 2^19 (half a megabyte)
Lets adopt a max quantum of one megabyte for FQ_CODEL.

Fixes: 4b549a2 ("fq_codel: Fair Queue Codel AQM")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Eric Dumazet authored and gregkh committed Sep 22, 2021
1 parent 6e2d36f commit 8c01c62
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
2 changes: 2 additions & 0 deletions include/uapi/linux/pkt_sched.h
Expand Up @@ -826,6 +826,8 @@ struct tc_codel_xstats {

/* FQ_CODEL */

#define FQ_CODEL_QUANTUM_MAX (1 << 20)

enum {
TCA_FQ_CODEL_UNSPEC,
TCA_FQ_CODEL_TARGET,
Expand Down
12 changes: 10 additions & 2 deletions net/sched/sch_fq_codel.c
Expand Up @@ -369,6 +369,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
{
struct fq_codel_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
u32 quantum = 0;
int err;

if (!opt)
Expand All @@ -386,6 +387,13 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
q->flows_cnt > 65536)
return -EINVAL;
}
if (tb[TCA_FQ_CODEL_QUANTUM]) {
quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
if (quantum > FQ_CODEL_QUANTUM_MAX) {
NL_SET_ERR_MSG(extack, "Invalid quantum");
return -EINVAL;
}
}
sch_tree_lock(sch);

if (tb[TCA_FQ_CODEL_TARGET]) {
Expand All @@ -412,8 +420,8 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
if (tb[TCA_FQ_CODEL_ECN])
q->cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);

if (tb[TCA_FQ_CODEL_QUANTUM])
q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
if (quantum)
q->quantum = quantum;

if (tb[TCA_FQ_CODEL_DROP_BATCH_SIZE])
q->drop_batch_size = max(1U, nla_get_u32(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]));
Expand Down

0 comments on commit 8c01c62

Please sign in to comment.