aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-01-23 23:35:39 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:11:22 -0500
commit27a3421e4821734bc19496faa77b380605dc3b23 (patch)
treef9ded49845a39f41352ed09130bf3d2bd05e4ffe
parent5feb5e1aaa887f6427b8290bce48bfb6b7010fc6 (diff)
[NET_SCHED]: Use nla_policy for attribute validation in packet schedulers
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/sch_atm.c12
-rw-r--r--net/sched/sch_cbq.c47
-rw-r--r--net/sched/sch_dsmark.c33
-rw-r--r--net/sched/sch_gred.c16
-rw-r--r--net/sched/sch_hfsc.c14
-rw-r--r--net/sched/sch_htb.c17
-rw-r--r--net/sched/sch_netem.c19
-rw-r--r--net/sched/sch_red.c11
-rw-r--r--net/sched/sch_tbf.c11
9 files changed, 87 insertions, 93 deletions
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 0c71f2eb96bc..335273416384 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -195,6 +195,11 @@ static const u8 llc_oui_ip[] = {
195 0x08, 0x00 195 0x08, 0x00
196}; /* Ethertype IP (0800) */ 196}; /* Ethertype IP (0800) */
197 197
198static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
199 [TCA_ATM_FD] = { .type = NLA_U32 },
200 [TCA_ATM_EXCESS] = { .type = NLA_U32 },
201};
202
198static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, 203static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
199 struct nlattr **tca, unsigned long *arg) 204 struct nlattr **tca, unsigned long *arg)
200{ 205{
@@ -225,11 +230,12 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
225 return -EBUSY; 230 return -EBUSY;
226 if (opt == NULL) 231 if (opt == NULL)
227 return -EINVAL; 232 return -EINVAL;
228 error = nla_parse_nested(tb, TCA_ATM_MAX, opt, NULL); 233
234 error = nla_parse_nested(tb, TCA_ATM_MAX, opt, atm_policy);
229 if (error < 0) 235 if (error < 0)
230 return error; 236 return error;
231 237
232 if (!tb[TCA_ATM_FD] || nla_len(tb[TCA_ATM_FD]) < sizeof(fd)) 238 if (!tb[TCA_ATM_FD])
233 return -EINVAL; 239 return -EINVAL;
234 fd = nla_get_u32(tb[TCA_ATM_FD]); 240 fd = nla_get_u32(tb[TCA_ATM_FD]);
235 pr_debug("atm_tc_change: fd %d\n", fd); 241 pr_debug("atm_tc_change: fd %d\n", fd);
@@ -243,8 +249,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
243 if (!tb[TCA_ATM_EXCESS]) 249 if (!tb[TCA_ATM_EXCESS])
244 excess = NULL; 250 excess = NULL;
245 else { 251 else {
246 if (nla_len(tb[TCA_ATM_EXCESS]) != sizeof(u32))
247 return -EINVAL;
248 excess = (struct atm_flow_data *) 252 excess = (struct atm_flow_data *)
249 atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS])); 253 atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
250 if (!excess) 254 if (!excess)
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index da0f6c0152de..09969c1fbc08 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1377,6 +1377,16 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
1377 return 0; 1377 return 0;
1378} 1378}
1379 1379
1380static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
1381 [TCA_CBQ_LSSOPT] = { .len = sizeof(struct tc_cbq_lssopt) },
1382 [TCA_CBQ_WRROPT] = { .len = sizeof(struct tc_cbq_wrropt) },
1383 [TCA_CBQ_FOPT] = { .len = sizeof(struct tc_cbq_fopt) },
1384 [TCA_CBQ_OVL_STRATEGY] = { .len = sizeof(struct tc_cbq_ovl) },
1385 [TCA_CBQ_RATE] = { .len = sizeof(struct tc_ratespec) },
1386 [TCA_CBQ_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
1387 [TCA_CBQ_POLICE] = { .len = sizeof(struct tc_cbq_police) },
1388};
1389
1380static int cbq_init(struct Qdisc *sch, struct nlattr *opt) 1390static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
1381{ 1391{
1382 struct cbq_sched_data *q = qdisc_priv(sch); 1392 struct cbq_sched_data *q = qdisc_priv(sch);
@@ -1384,16 +1394,11 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
1384 struct tc_ratespec *r; 1394 struct tc_ratespec *r;
1385 int err; 1395 int err;
1386 1396
1387 err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL); 1397 err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
1388 if (err < 0) 1398 if (err < 0)
1389 return err; 1399 return err;
1390 1400
1391 if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL || 1401 if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
1392 nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
1393 return -EINVAL;
1394
1395 if (tb[TCA_CBQ_LSSOPT] &&
1396 nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
1397 return -EINVAL; 1402 return -EINVAL;
1398 1403
1399 r = nla_data(tb[TCA_CBQ_RATE]); 1404 r = nla_data(tb[TCA_CBQ_RATE]);
@@ -1771,36 +1776,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
1771 if (opt == NULL) 1776 if (opt == NULL)
1772 return -EINVAL; 1777 return -EINVAL;
1773 1778
1774 err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL); 1779 err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
1775 if (err < 0) 1780 if (err < 0)
1776 return err; 1781 return err;
1777 1782
1778 if (tb[TCA_CBQ_OVL_STRATEGY] &&
1779 nla_len(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(struct tc_cbq_ovl))
1780 return -EINVAL;
1781
1782 if (tb[TCA_CBQ_FOPT] &&
1783 nla_len(tb[TCA_CBQ_FOPT]) < sizeof(struct tc_cbq_fopt))
1784 return -EINVAL;
1785
1786 if (tb[TCA_CBQ_RATE] &&
1787 nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
1788 return -EINVAL;
1789
1790 if (tb[TCA_CBQ_LSSOPT] &&
1791 nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
1792 return -EINVAL;
1793
1794 if (tb[TCA_CBQ_WRROPT] &&
1795 nla_len(tb[TCA_CBQ_WRROPT]) < sizeof(struct tc_cbq_wrropt))
1796 return -EINVAL;
1797
1798#ifdef CONFIG_NET_CLS_ACT
1799 if (tb[TCA_CBQ_POLICE] &&
1800 nla_len(tb[TCA_CBQ_POLICE]) < sizeof(struct tc_cbq_police))
1801 return -EINVAL;
1802#endif
1803
1804 if (cl) { 1783 if (cl) {
1805 /* Check parent */ 1784 /* Check parent */
1806 if (parentid) { 1785 if (parentid) {
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index f1d0a08aca75..0df911fd67b1 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -99,6 +99,14 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl)
99{ 99{
100} 100}
101 101
102static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
103 [TCA_DSMARK_INDICES] = { .type = NLA_U16 },
104 [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
105 [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG },
106 [TCA_DSMARK_MASK] = { .type = NLA_U8 },
107 [TCA_DSMARK_VALUE] = { .type = NLA_U8 },
108};
109
102static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent, 110static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
103 struct nlattr **tca, unsigned long *arg) 111 struct nlattr **tca, unsigned long *arg)
104{ 112{
@@ -119,21 +127,15 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
119 if (!opt) 127 if (!opt)
120 goto errout; 128 goto errout;
121 129
122 err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL); 130 err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
123 if (err < 0) 131 if (err < 0)
124 return err; 132 goto errout;
125 133
126 err = -EINVAL; 134 if (tb[TCA_DSMARK_MASK])
127 if (tb[TCA_DSMARK_MASK]) {
128 if (nla_len(tb[TCA_DSMARK_MASK]) < sizeof(u8))
129 goto errout;
130 mask = nla_get_u8(tb[TCA_DSMARK_MASK]); 135 mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
131 } 136
132 if (tb[TCA_DSMARK_VALUE]) { 137 if (tb[TCA_DSMARK_VALUE])
133 if (nla_len(tb[TCA_DSMARK_VALUE]) < sizeof(u8))
134 goto errout;
135 p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]); 138 p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
136 }
137 139
138 if (tb[TCA_DSMARK_MASK]) 140 if (tb[TCA_DSMARK_MASK])
139 p->mask[*arg-1] = mask; 141 p->mask[*arg-1] = mask;
@@ -359,23 +361,18 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
359 if (!opt) 361 if (!opt)
360 goto errout; 362 goto errout;
361 363
362 err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL); 364 err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
363 if (err < 0) 365 if (err < 0)
364 goto errout; 366 goto errout;
365 367
366 err = -EINVAL; 368 err = -EINVAL;
367 if (nla_len(tb[TCA_DSMARK_INDICES]) < sizeof(u16))
368 goto errout;
369 indices = nla_get_u16(tb[TCA_DSMARK_INDICES]); 369 indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
370 370
371 if (hweight32(indices) != 1) 371 if (hweight32(indices) != 1)
372 goto errout; 372 goto errout;
373 373
374 if (tb[TCA_DSMARK_DEFAULT_INDEX]) { 374 if (tb[TCA_DSMARK_DEFAULT_INDEX])
375 if (nla_len(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(u16))
376 goto errout;
377 default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]); 375 default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
378 }
379 376
380 mask = kmalloc(indices * 2, GFP_KERNEL); 377 mask = kmalloc(indices * 2, GFP_KERNEL);
381 if (mask == NULL) { 378 if (mask == NULL) {
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 365c7d8b17ab..3a9d226ff1e4 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -356,7 +356,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
356 struct tc_gred_sopt *sopt; 356 struct tc_gred_sopt *sopt;
357 int i; 357 int i;
358 358
359 if (dps == NULL || nla_len(dps) < sizeof(*sopt)) 359 if (dps == NULL)
360 return -EINVAL; 360 return -EINVAL;
361 361
362 sopt = nla_data(dps); 362 sopt = nla_data(dps);
@@ -425,6 +425,12 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
425 return 0; 425 return 0;
426} 426}
427 427
428static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
429 [TCA_GRED_PARMS] = { .len = sizeof(struct tc_gred_qopt) },
430 [TCA_GRED_STAB] = { .len = 256 },
431 [TCA_GRED_DPS] = { .len = sizeof(struct tc_gred_sopt) },
432};
433
428static int gred_change(struct Qdisc *sch, struct nlattr *opt) 434static int gred_change(struct Qdisc *sch, struct nlattr *opt)
429{ 435{
430 struct gred_sched *table = qdisc_priv(sch); 436 struct gred_sched *table = qdisc_priv(sch);
@@ -436,7 +442,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
436 if (opt == NULL) 442 if (opt == NULL)
437 return -EINVAL; 443 return -EINVAL;
438 444
439 err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL); 445 err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
440 if (err < 0) 446 if (err < 0)
441 return err; 447 return err;
442 448
@@ -444,9 +450,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
444 return gred_change_table_def(sch, opt); 450 return gred_change_table_def(sch, opt);
445 451
446 if (tb[TCA_GRED_PARMS] == NULL || 452 if (tb[TCA_GRED_PARMS] == NULL ||
447 nla_len(tb[TCA_GRED_PARMS]) < sizeof(*ctl) || 453 tb[TCA_GRED_STAB] == NULL)
448 tb[TCA_GRED_STAB] == NULL ||
449 nla_len(tb[TCA_GRED_STAB]) < 256)
450 return -EINVAL; 454 return -EINVAL;
451 455
452 err = -EINVAL; 456 err = -EINVAL;
@@ -499,7 +503,7 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt)
499 if (opt == NULL) 503 if (opt == NULL)
500 return -EINVAL; 504 return -EINVAL;
501 505
502 err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL); 506 err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
503 if (err < 0) 507 if (err < 0)
504 return err; 508 return err;
505 509
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 10a2f35a27a8..87293d0db1d7 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -986,6 +986,12 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
986 cl->cl_flags |= HFSC_USC; 986 cl->cl_flags |= HFSC_USC;
987} 987}
988 988
989static const struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
990 [TCA_HFSC_RSC] = { .len = sizeof(struct tc_service_curve) },
991 [TCA_HFSC_FSC] = { .len = sizeof(struct tc_service_curve) },
992 [TCA_HFSC_USC] = { .len = sizeof(struct tc_service_curve) },
993};
994
989static int 995static int
990hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, 996hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
991 struct nlattr **tca, unsigned long *arg) 997 struct nlattr **tca, unsigned long *arg)
@@ -1002,29 +1008,23 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1002 if (opt == NULL) 1008 if (opt == NULL)
1003 return -EINVAL; 1009 return -EINVAL;
1004 1010
1005 err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, NULL); 1011 err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, hfsc_policy);
1006 if (err < 0) 1012 if (err < 0)
1007 return err; 1013 return err;
1008 1014
1009 if (tb[TCA_HFSC_RSC]) { 1015 if (tb[TCA_HFSC_RSC]) {
1010 if (nla_len(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
1011 return -EINVAL;
1012 rsc = nla_data(tb[TCA_HFSC_RSC]); 1016 rsc = nla_data(tb[TCA_HFSC_RSC]);
1013 if (rsc->m1 == 0 && rsc->m2 == 0) 1017 if (rsc->m1 == 0 && rsc->m2 == 0)
1014 rsc = NULL; 1018 rsc = NULL;
1015 } 1019 }
1016 1020
1017 if (tb[TCA_HFSC_FSC]) { 1021 if (tb[TCA_HFSC_FSC]) {
1018 if (nla_len(tb[TCA_HFSC_FSC]) < sizeof(*fsc))
1019 return -EINVAL;
1020 fsc = nla_data(tb[TCA_HFSC_FSC]); 1022 fsc = nla_data(tb[TCA_HFSC_FSC]);
1021 if (fsc->m1 == 0 && fsc->m2 == 0) 1023 if (fsc->m1 == 0 && fsc->m2 == 0)
1022 fsc = NULL; 1024 fsc = NULL;
1023 } 1025 }
1024 1026
1025 if (tb[TCA_HFSC_USC]) { 1027 if (tb[TCA_HFSC_USC]) {
1026 if (nla_len(tb[TCA_HFSC_USC]) < sizeof(*usc))
1027 return -EINVAL;
1028 usc = nla_data(tb[TCA_HFSC_USC]); 1028 usc = nla_data(tb[TCA_HFSC_USC]);
1029 if (usc->m1 == 0 && usc->m2 == 0) 1029 if (usc->m1 == 0 && usc->m2 == 0)
1030 usc = NULL; 1030 usc = NULL;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 69fac320f8bc..e1a579efc215 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -992,6 +992,13 @@ static void htb_reset(struct Qdisc *sch)
992 INIT_LIST_HEAD(q->drops + i); 992 INIT_LIST_HEAD(q->drops + i);
993} 993}
994 994
995static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
996 [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) },
997 [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) },
998 [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
999 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
1000};
1001
995static int htb_init(struct Qdisc *sch, struct nlattr *opt) 1002static int htb_init(struct Qdisc *sch, struct nlattr *opt)
996{ 1003{
997 struct htb_sched *q = qdisc_priv(sch); 1004 struct htb_sched *q = qdisc_priv(sch);
@@ -1003,12 +1010,11 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
1003 if (!opt) 1010 if (!opt)
1004 return -EINVAL; 1011 return -EINVAL;
1005 1012
1006 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, NULL); 1013 err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
1007 if (err < 0) 1014 if (err < 0)
1008 return err; 1015 return err;
1009 1016
1010 if (tb[TCA_HTB_INIT] == NULL || 1017 if (tb[TCA_HTB_INIT] == NULL) {
1011 nla_len(tb[TCA_HTB_INIT]) < sizeof(*gopt)) {
1012 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n"); 1018 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
1013 return -EINVAL; 1019 return -EINVAL;
1014 } 1020 }
@@ -1319,13 +1325,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
1319 if (!opt) 1325 if (!opt)
1320 goto failure; 1326 goto failure;
1321 1327
1322 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, NULL); 1328 err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
1323 if (err < 0) 1329 if (err < 0)
1324 goto failure; 1330 goto failure;
1325 1331
1326 err = -EINVAL; 1332 err = -EINVAL;
1327 if (tb[TCA_HTB_PARMS] == NULL || 1333 if (tb[TCA_HTB_PARMS] == NULL)
1328 nla_len(tb[TCA_HTB_PARMS]) < sizeof(*hopt))
1329 goto failure; 1334 goto failure;
1330 1335
1331 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch); 1336 parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 1a755799ffb8..c9c649b26eaa 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -368,9 +368,6 @@ static int get_correlation(struct Qdisc *sch, const struct nlattr *attr)
368 struct netem_sched_data *q = qdisc_priv(sch); 368 struct netem_sched_data *q = qdisc_priv(sch);
369 const struct tc_netem_corr *c = nla_data(attr); 369 const struct tc_netem_corr *c = nla_data(attr);
370 370
371 if (nla_len(attr) != sizeof(*c))
372 return -EINVAL;
373
374 init_crandom(&q->delay_cor, c->delay_corr); 371 init_crandom(&q->delay_cor, c->delay_corr);
375 init_crandom(&q->loss_cor, c->loss_corr); 372 init_crandom(&q->loss_cor, c->loss_corr);
376 init_crandom(&q->dup_cor, c->dup_corr); 373 init_crandom(&q->dup_cor, c->dup_corr);
@@ -382,9 +379,6 @@ static int get_reorder(struct Qdisc *sch, const struct nlattr *attr)
382 struct netem_sched_data *q = qdisc_priv(sch); 379 struct netem_sched_data *q = qdisc_priv(sch);
383 const struct tc_netem_reorder *r = nla_data(attr); 380 const struct tc_netem_reorder *r = nla_data(attr);
384 381
385 if (nla_len(attr) != sizeof(*r))
386 return -EINVAL;
387
388 q->reorder = r->probability; 382 q->reorder = r->probability;
389 init_crandom(&q->reorder_cor, r->correlation); 383 init_crandom(&q->reorder_cor, r->correlation);
390 return 0; 384 return 0;
@@ -395,14 +389,17 @@ static int get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
395 struct netem_sched_data *q = qdisc_priv(sch); 389 struct netem_sched_data *q = qdisc_priv(sch);
396 const struct tc_netem_corrupt *r = nla_data(attr); 390 const struct tc_netem_corrupt *r = nla_data(attr);
397 391
398 if (nla_len(attr) != sizeof(*r))
399 return -EINVAL;
400
401 q->corrupt = r->probability; 392 q->corrupt = r->probability;
402 init_crandom(&q->corrupt_cor, r->correlation); 393 init_crandom(&q->corrupt_cor, r->correlation);
403 return 0; 394 return 0;
404} 395}
405 396
397static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
398 [TCA_NETEM_CORR] = { .len = sizeof(struct tc_netem_corr) },
399 [TCA_NETEM_REORDER] = { .len = sizeof(struct tc_netem_reorder) },
400 [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) },
401};
402
406/* Parse netlink message to set options */ 403/* Parse netlink message to set options */
407static int netem_change(struct Qdisc *sch, struct nlattr *opt) 404static int netem_change(struct Qdisc *sch, struct nlattr *opt)
408{ 405{
@@ -414,8 +411,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
414 if (opt == NULL) 411 if (opt == NULL)
415 return -EINVAL; 412 return -EINVAL;
416 413
417 ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, NULL, qopt, 414 ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, netem_policy,
418 sizeof(*qopt)); 415 qopt, sizeof(*qopt));
419 if (ret < 0) 416 if (ret < 0)
420 return ret; 417 return ret;
421 418
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index dcf6afc196f8..3dcd493f4f4a 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -201,6 +201,11 @@ static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
201 return NULL; 201 return NULL;
202} 202}
203 203
204static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
205 [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) },
206 [TCA_RED_STAB] = { .len = RED_STAB_SIZE },
207};
208
204static int red_change(struct Qdisc *sch, struct nlattr *opt) 209static int red_change(struct Qdisc *sch, struct nlattr *opt)
205{ 210{
206 struct red_sched_data *q = qdisc_priv(sch); 211 struct red_sched_data *q = qdisc_priv(sch);
@@ -212,14 +217,12 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
212 if (opt == NULL) 217 if (opt == NULL)
213 return -EINVAL; 218 return -EINVAL;
214 219
215 err = nla_parse_nested(tb, TCA_RED_MAX, opt, NULL); 220 err = nla_parse_nested(tb, TCA_RED_MAX, opt, red_policy);
216 if (err < 0) 221 if (err < 0)
217 return err; 222 return err;
218 223
219 if (tb[TCA_RED_PARMS] == NULL || 224 if (tb[TCA_RED_PARMS] == NULL ||
220 nla_len(tb[TCA_RED_PARMS]) < sizeof(*ctl) || 225 tb[TCA_RED_STAB] == NULL)
221 tb[TCA_RED_STAB] == NULL ||
222 nla_len(tb[TCA_RED_STAB]) < RED_STAB_SIZE)
223 return -EINVAL; 226 return -EINVAL;
224 227
225 ctl = nla_data(tb[TCA_RED_PARMS]); 228 ctl = nla_data(tb[TCA_RED_PARMS]);
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index b7a185dc3def..0b7d78f59d8c 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -270,6 +270,12 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
270 return NULL; 270 return NULL;
271} 271}
272 272
273static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
274 [TCA_TBF_PARMS] = { .len = sizeof(struct tc_tbf_qopt) },
275 [TCA_TBF_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
276 [TCA_TBF_PTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
277};
278
273static int tbf_change(struct Qdisc* sch, struct nlattr *opt) 279static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
274{ 280{
275 int err; 281 int err;
@@ -281,13 +287,12 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
281 struct Qdisc *child = NULL; 287 struct Qdisc *child = NULL;
282 int max_size,n; 288 int max_size,n;
283 289
284 err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, NULL); 290 err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy);
285 if (err < 0) 291 if (err < 0)
286 return err; 292 return err;
287 293
288 err = -EINVAL; 294 err = -EINVAL;
289 if (tb[TCA_TBF_PARMS] == NULL || 295 if (tb[TCA_TBF_PARMS] == NULL)
290 nla_len(tb[TCA_TBF_PARMS]) < sizeof(*qopt))
291 goto done; 296 goto done;
292 297
293 qopt = nla_data(tb[TCA_TBF_PARMS]); 298 qopt = nla_data(tb[TCA_TBF_PARMS]);