diff options
Diffstat (limited to 'net/sched/cls_flower.c')
| -rw-r--r-- | net/sched/cls_flower.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index dad04e710493..12ca9d13db83 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c | |||
| @@ -1290,17 +1290,23 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 1290 | struct cls_fl_head *head = rtnl_dereference(tp->root); | 1290 | struct cls_fl_head *head = rtnl_dereference(tp->root); |
| 1291 | struct cls_fl_filter *fold = *arg; | 1291 | struct cls_fl_filter *fold = *arg; |
| 1292 | struct cls_fl_filter *fnew; | 1292 | struct cls_fl_filter *fnew; |
| 1293 | struct fl_flow_mask *mask; | ||
| 1293 | struct nlattr **tb; | 1294 | struct nlattr **tb; |
| 1294 | struct fl_flow_mask mask = {}; | ||
| 1295 | int err; | 1295 | int err; |
| 1296 | 1296 | ||
| 1297 | if (!tca[TCA_OPTIONS]) | 1297 | if (!tca[TCA_OPTIONS]) |
| 1298 | return -EINVAL; | 1298 | return -EINVAL; |
| 1299 | 1299 | ||
| 1300 | tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL); | 1300 | mask = kzalloc(sizeof(struct fl_flow_mask), GFP_KERNEL); |
| 1301 | if (!tb) | 1301 | if (!mask) |
| 1302 | return -ENOBUFS; | 1302 | return -ENOBUFS; |
| 1303 | 1303 | ||
| 1304 | tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL); | ||
| 1305 | if (!tb) { | ||
| 1306 | err = -ENOBUFS; | ||
| 1307 | goto errout_mask_alloc; | ||
| 1308 | } | ||
| 1309 | |||
| 1304 | err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS], | 1310 | err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS], |
| 1305 | fl_policy, NULL); | 1311 | fl_policy, NULL); |
| 1306 | if (err < 0) | 1312 | if (err < 0) |
| @@ -1343,12 +1349,12 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 1343 | } | 1349 | } |
| 1344 | } | 1350 | } |
| 1345 | 1351 | ||
| 1346 | err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr, | 1352 | err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr, |
| 1347 | tp->chain->tmplt_priv, extack); | 1353 | tp->chain->tmplt_priv, extack); |
| 1348 | if (err) | 1354 | if (err) |
| 1349 | goto errout_idr; | 1355 | goto errout_idr; |
| 1350 | 1356 | ||
| 1351 | err = fl_check_assign_mask(head, fnew, fold, &mask); | 1357 | err = fl_check_assign_mask(head, fnew, fold, mask); |
| 1352 | if (err) | 1358 | if (err) |
| 1353 | goto errout_idr; | 1359 | goto errout_idr; |
| 1354 | 1360 | ||
| @@ -1365,7 +1371,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 1365 | if (!tc_skip_hw(fnew->flags)) { | 1371 | if (!tc_skip_hw(fnew->flags)) { |
| 1366 | err = fl_hw_replace_filter(tp, fnew, extack); | 1372 | err = fl_hw_replace_filter(tp, fnew, extack); |
| 1367 | if (err) | 1373 | if (err) |
| 1368 | goto errout_mask; | 1374 | goto errout_mask_ht; |
| 1369 | } | 1375 | } |
| 1370 | 1376 | ||
| 1371 | if (!tc_in_hw(fnew->flags)) | 1377 | if (!tc_in_hw(fnew->flags)) |
| @@ -1392,8 +1398,13 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 1392 | } | 1398 | } |
| 1393 | 1399 | ||
| 1394 | kfree(tb); | 1400 | kfree(tb); |
| 1401 | kfree(mask); | ||
| 1395 | return 0; | 1402 | return 0; |
| 1396 | 1403 | ||
| 1404 | errout_mask_ht: | ||
| 1405 | rhashtable_remove_fast(&fnew->mask->ht, &fnew->ht_node, | ||
| 1406 | fnew->mask->filter_ht_params); | ||
| 1407 | |||
| 1397 | errout_mask: | 1408 | errout_mask: |
| 1398 | fl_mask_put(head, fnew->mask, false); | 1409 | fl_mask_put(head, fnew->mask, false); |
| 1399 | 1410 | ||
| @@ -1405,6 +1416,8 @@ errout: | |||
| 1405 | kfree(fnew); | 1416 | kfree(fnew); |
| 1406 | errout_tb: | 1417 | errout_tb: |
| 1407 | kfree(tb); | 1418 | kfree(tb); |
| 1419 | errout_mask_alloc: | ||
| 1420 | kfree(mask); | ||
| 1408 | return err; | 1421 | return err; |
| 1409 | } | 1422 | } |
| 1410 | 1423 | ||
