Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net_sched: red: Avoid illegal values

Check the qmin & qmax values doesn't overflow for the given Wlog value.
Check that qmin <= qmax.

Fixes: a783474591f2 ("[PKT_SCHED]: Generic RED layer")
Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Nogah Frankel and committed by
David S. Miller
8afa10cb 5c472203

+22
+11
include/net/red.h
··· 168 168 v->qcount = -1; 169 169 } 170 170 171 + static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog) 172 + { 173 + if (fls(qth_min) + Wlog > 32) 174 + return false; 175 + if (fls(qth_max) + Wlog > 32) 176 + return false; 177 + if (qth_max < qth_min) 178 + return false; 179 + return true; 180 + } 181 + 171 182 static inline void red_set_parms(struct red_parms *p, 172 183 u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, 173 184 u8 Scell_log, u8 *stab, u32 max_P)
+3
net/sched/sch_choke.c
··· 369 369 370 370 ctl = nla_data(tb[TCA_CHOKE_PARMS]); 371 371 372 + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) 373 + return -EINVAL; 374 + 372 375 if (ctl->limit > CHOKE_MAX_QUEUE) 373 376 return -EINVAL; 374 377
+3
net/sched/sch_gred.c
··· 356 356 struct gred_sched *table = qdisc_priv(sch); 357 357 struct gred_sched_data *q = table->tab[dp]; 358 358 359 + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) 360 + return -EINVAL; 361 + 359 362 if (!q) { 360 363 table->tab[dp] = q = *prealloc; 361 364 *prealloc = NULL;
+2
net/sched/sch_red.c
··· 212 212 max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; 213 213 214 214 ctl = nla_data(tb[TCA_RED_PARMS]); 215 + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) 216 + return -EINVAL; 215 217 216 218 if (ctl->limit > 0) { 217 219 child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
+3
net/sched/sch_sfq.c
··· 639 639 if (ctl->divisor && 640 640 (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536)) 641 641 return -EINVAL; 642 + if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, 643 + ctl_v1->Wlog)) 644 + return -EINVAL; 642 645 if (ctl_v1 && ctl_v1->qth_min) { 643 646 p = kmalloc(sizeof(*p), GFP_KERNEL); 644 647 if (!p)