Skip to content

Commit b9a24bb

Browse files
congwangdavem330
authored andcommitted
net_sched: properly handle failure case of tcf_exts_init()
After commit 22dc13c ("net_sched: convert tcf_exts from list to pointer array") we do dynamic allocation in tcf_exts_init(), therefore we need to handle the ENOMEM case properly. Cc: Jamal Hadi Salim <[email protected]> Signed-off-by: Cong Wang <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c1346a7 commit b9a24bb

File tree

11 files changed

+181
-74
lines changed

11 files changed

+181
-74
lines changed

include/net/pkt_cls.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,19 @@ struct tcf_exts {
6969
int police;
7070
};
7171

72-
static inline void tcf_exts_init(struct tcf_exts *exts, int action, int police)
72+
static inline int tcf_exts_init(struct tcf_exts *exts, int action, int police)
7373
{
7474
#ifdef CONFIG_NET_CLS_ACT
7575
exts->type = 0;
7676
exts->nr_actions = 0;
7777
exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
7878
GFP_KERNEL);
79-
WARN_ON(!exts->actions); /* TODO: propagate the error to callers */
79+
if (!exts->actions)
80+
return -ENOMEM;
8081
#endif
8182
exts->action = action;
8283
exts->police = police;
84+
return 0;
8385
}
8486

8587
/**

net/sched/cls_basic.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,12 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,
138138
struct tcf_exts e;
139139
struct tcf_ematch_tree t;
140140

141-
tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
142-
err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
141+
err = tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
143142
if (err < 0)
144143
return err;
144+
err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
145+
if (err < 0)
146+
goto errout;
145147

146148
err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES], &t);
147149
if (err < 0)
@@ -189,7 +191,10 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
189191
if (!fnew)
190192
return -ENOBUFS;
191193

192-
tcf_exts_init(&fnew->exts, TCA_BASIC_ACT, TCA_BASIC_POLICE);
194+
err = tcf_exts_init(&fnew->exts, TCA_BASIC_ACT, TCA_BASIC_POLICE);
195+
if (err < 0)
196+
goto errout;
197+
193198
err = -EINVAL;
194199
if (handle) {
195200
fnew->handle = handle;
@@ -226,6 +231,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
226231

227232
return 0;
228233
errout:
234+
tcf_exts_destroy(&fnew->exts);
229235
kfree(fnew);
230236
return err;
231237
}

net/sched/cls_bpf.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,17 +311,19 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
311311
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
312312
return -EINVAL;
313313

314-
tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE);
315-
ret = tcf_exts_validate(net, tp, tb, est, &exts, ovr);
314+
ret = tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE);
316315
if (ret < 0)
317316
return ret;
317+
ret = tcf_exts_validate(net, tp, tb, est, &exts, ovr);
318+
if (ret < 0)
319+
goto errout;
318320

319321
if (tb[TCA_BPF_FLAGS]) {
320322
u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
321323

322324
if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) {
323-
tcf_exts_destroy(&exts);
324-
return -EINVAL;
325+
ret = -EINVAL;
326+
goto errout;
325327
}
326328

327329
have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
@@ -331,10 +333,8 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
331333

332334
ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
333335
cls_bpf_prog_from_efd(tb, prog, tp);
334-
if (ret < 0) {
335-
tcf_exts_destroy(&exts);
336-
return ret;
337-
}
336+
if (ret < 0)
337+
goto errout;
338338

339339
if (tb[TCA_BPF_CLASSID]) {
340340
prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
@@ -343,6 +343,10 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
343343

344344
tcf_exts_change(tp, &prog->exts, &exts);
345345
return 0;
346+
347+
errout:
348+
tcf_exts_destroy(&exts);
349+
return ret;
346350
}
347351

348352
static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp,
@@ -388,7 +392,9 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
388392
if (!prog)
389393
return -ENOBUFS;
390394

391-
tcf_exts_init(&prog->exts, TCA_BPF_ACT, TCA_BPF_POLICE);
395+
ret = tcf_exts_init(&prog->exts, TCA_BPF_ACT, TCA_BPF_POLICE);
396+
if (ret < 0)
397+
goto errout;
392398

393399
if (oldprog) {
394400
if (handle && oldprog->handle != handle) {
@@ -420,9 +426,10 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
420426

421427
*arg = (unsigned long) prog;
422428
return 0;
429+
423430
errout:
431+
tcf_exts_destroy(&prog->exts);
424432
kfree(prog);
425-
426433
return ret;
427434
}
428435

net/sched/cls_cgroup.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,24 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
9393
if (!new)
9494
return -ENOBUFS;
9595

96-
tcf_exts_init(&new->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
96+
err = tcf_exts_init(&new->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
97+
if (err < 0)
98+
goto errout;
9799
new->handle = handle;
98100
new->tp = tp;
99101
err = nla_parse_nested(tb, TCA_CGROUP_MAX, tca[TCA_OPTIONS],
100102
cgroup_policy);
101103
if (err < 0)
102104
goto errout;
103105

104-
tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
105-
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
106+
err = tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
106107
if (err < 0)
107108
goto errout;
109+
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
110+
if (err < 0) {
111+
tcf_exts_destroy(&e);
112+
goto errout;
113+
}
108114

109115
err = tcf_em_tree_validate(tp, tb[TCA_CGROUP_EMATCHES], &t);
110116
if (err < 0) {
@@ -120,6 +126,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
120126
call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
121127
return 0;
122128
errout:
129+
tcf_exts_destroy(&new->exts);
123130
kfree(new);
124131
return err;
125132
}

net/sched/cls_flow.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -418,10 +418,12 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
418418
return -EOPNOTSUPP;
419419
}
420420

421-
tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
421+
err = tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
422+
if (err < 0)
423+
goto err1;
422424
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
423425
if (err < 0)
424-
return err;
426+
goto err1;
425427

426428
err = tcf_em_tree_validate(tp, tb[TCA_FLOW_EMATCHES], &t);
427429
if (err < 0)
@@ -432,13 +434,15 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
432434
if (!fnew)
433435
goto err2;
434436

435-
tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
437+
err = tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
438+
if (err < 0)
439+
goto err3;
436440

437441
fold = (struct flow_filter *)*arg;
438442
if (fold) {
439443
err = -EINVAL;
440444
if (fold->handle != handle && handle)
441-
goto err2;
445+
goto err3;
442446

443447
/* Copy fold into fnew */
444448
fnew->tp = fold->tp;
@@ -458,31 +462,31 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
458462
if (tb[TCA_FLOW_MODE])
459463
mode = nla_get_u32(tb[TCA_FLOW_MODE]);
460464
if (mode != FLOW_MODE_HASH && nkeys > 1)
461-
goto err2;
465+
goto err3;
462466

463467
if (mode == FLOW_MODE_HASH)
464468
perturb_period = fold->perturb_period;
465469
if (tb[TCA_FLOW_PERTURB]) {
466470
if (mode != FLOW_MODE_HASH)
467-
goto err2;
471+
goto err3;
468472
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
469473
}
470474
} else {
471475
err = -EINVAL;
472476
if (!handle)
473-
goto err2;
477+
goto err3;
474478
if (!tb[TCA_FLOW_KEYS])
475-
goto err2;
479+
goto err3;
476480

477481
mode = FLOW_MODE_MAP;
478482
if (tb[TCA_FLOW_MODE])
479483
mode = nla_get_u32(tb[TCA_FLOW_MODE]);
480484
if (mode != FLOW_MODE_HASH && nkeys > 1)
481-
goto err2;
485+
goto err3;
482486

483487
if (tb[TCA_FLOW_PERTURB]) {
484488
if (mode != FLOW_MODE_HASH)
485-
goto err2;
489+
goto err3;
486490
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
487491
}
488492

@@ -542,6 +546,8 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
542546
call_rcu(&fold->rcu, flow_destroy_filter);
543547
return 0;
544548

549+
err3:
550+
tcf_exts_destroy(&fnew->exts);
545551
err2:
546552
tcf_em_tree_destroy(&t);
547553
kfree(fnew);

net/sched/cls_flower.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,10 +513,12 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp,
513513
struct tcf_exts e;
514514
int err;
515515

516-
tcf_exts_init(&e, TCA_FLOWER_ACT, 0);
517-
err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
516+
err = tcf_exts_init(&e, TCA_FLOWER_ACT, 0);
518517
if (err < 0)
519518
return err;
519+
err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
520+
if (err < 0)
521+
goto errout;
520522

521523
if (tb[TCA_FLOWER_CLASSID]) {
522524
f->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
@@ -585,7 +587,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
585587
if (!fnew)
586588
return -ENOBUFS;
587589

588-
tcf_exts_init(&fnew->exts, TCA_FLOWER_ACT, 0);
590+
err = tcf_exts_init(&fnew->exts, TCA_FLOWER_ACT, 0);
591+
if (err < 0)
592+
goto errout;
589593

590594
if (!handle) {
591595
handle = fl_grab_new_handle(tp, head);
@@ -649,6 +653,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
649653
return 0;
650654

651655
errout:
656+
tcf_exts_destroy(&fnew->exts);
652657
kfree(fnew);
653658
return err;
654659
}

net/sched/cls_fw.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,12 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
195195
u32 mask;
196196
int err;
197197

198-
tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
199-
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
198+
err = tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
200199
if (err < 0)
201200
return err;
201+
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
202+
if (err < 0)
203+
goto errout;
202204

203205
if (tb[TCA_FW_CLASSID]) {
204206
f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
@@ -270,10 +272,15 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
270272
#endif /* CONFIG_NET_CLS_IND */
271273
fnew->tp = f->tp;
272274

273-
tcf_exts_init(&fnew->exts, TCA_FW_ACT, TCA_FW_POLICE);
275+
err = tcf_exts_init(&fnew->exts, TCA_FW_ACT, TCA_FW_POLICE);
276+
if (err < 0) {
277+
kfree(fnew);
278+
return err;
279+
}
274280

275281
err = fw_change_attrs(net, tp, fnew, tb, tca, base, ovr);
276282
if (err < 0) {
283+
tcf_exts_destroy(&fnew->exts);
277284
kfree(fnew);
278285
return err;
279286
}
@@ -313,7 +320,9 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
313320
if (f == NULL)
314321
return -ENOBUFS;
315322

316-
tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE);
323+
err = tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE);
324+
if (err < 0)
325+
goto errout;
317326
f->id = handle;
318327
f->tp = tp;
319328

@@ -328,6 +337,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
328337
return 0;
329338

330339
errout:
340+
tcf_exts_destroy(&f->exts);
331341
kfree(f);
332342
return err;
333343
}

net/sched/cls_route.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,17 +383,19 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
383383
struct nlattr **tb, struct nlattr *est, int new,
384384
bool ovr)
385385
{
386-
int err;
387386
u32 id = 0, to = 0, nhandle = 0x8000;
388387
struct route4_filter *fp;
389388
unsigned int h1;
390389
struct route4_bucket *b;
391390
struct tcf_exts e;
391+
int err;
392392

393-
tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
394-
err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
393+
err = tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
395394
if (err < 0)
396395
return err;
396+
err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
397+
if (err < 0)
398+
goto errout;
397399

398400
err = -EINVAL;
399401
if (tb[TCA_ROUTE4_TO]) {
@@ -503,7 +505,10 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
503505
if (!f)
504506
goto errout;
505507

506-
tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
508+
err = tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
509+
if (err < 0)
510+
goto errout;
511+
507512
if (fold) {
508513
f->id = fold->id;
509514
f->iif = fold->iif;
@@ -557,6 +562,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
557562
return 0;
558563

559564
errout:
565+
tcf_exts_destroy(&f->exts);
560566
kfree(f);
561567
return err;
562568
}

0 commit comments

Comments
 (0)