diff options
| -rw-r--r-- | net/sched/act_skbmod.c | 19 | ||||
| -rw-r--r-- | tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json | 25 |
2 files changed, 41 insertions, 3 deletions
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index b9ab2c8f07f1..1d4c324d0a42 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
| 17 | #include <net/netlink.h> | 17 | #include <net/netlink.h> |
| 18 | #include <net/pkt_sched.h> | 18 | #include <net/pkt_sched.h> |
| 19 | #include <net/pkt_cls.h> | ||
| 19 | 20 | ||
| 20 | #include <linux/tc_act/tc_skbmod.h> | 21 | #include <linux/tc_act/tc_skbmod.h> |
| 21 | #include <net/tc_act/tc_skbmod.h> | 22 | #include <net/tc_act/tc_skbmod.h> |
| @@ -88,6 +89,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 88 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); | 89 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); |
| 89 | struct nlattr *tb[TCA_SKBMOD_MAX + 1]; | 90 | struct nlattr *tb[TCA_SKBMOD_MAX + 1]; |
| 90 | struct tcf_skbmod_params *p, *p_old; | 91 | struct tcf_skbmod_params *p, *p_old; |
| 92 | struct tcf_chain *goto_ch = NULL; | ||
| 91 | struct tc_skbmod *parm; | 93 | struct tc_skbmod *parm; |
| 92 | struct tcf_skbmod *d; | 94 | struct tcf_skbmod *d; |
| 93 | bool exists = false; | 95 | bool exists = false; |
| @@ -154,21 +156,24 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 154 | tcf_idr_release(*a, bind); | 156 | tcf_idr_release(*a, bind); |
| 155 | return -EEXIST; | 157 | return -EEXIST; |
| 156 | } | 158 | } |
| 159 | err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); | ||
| 160 | if (err < 0) | ||
| 161 | goto release_idr; | ||
| 157 | 162 | ||
| 158 | d = to_skbmod(*a); | 163 | d = to_skbmod(*a); |
| 159 | 164 | ||
| 160 | p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL); | 165 | p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL); |
| 161 | if (unlikely(!p)) { | 166 | if (unlikely(!p)) { |
| 162 | tcf_idr_release(*a, bind); | 167 | err = -ENOMEM; |
| 163 | return -ENOMEM; | 168 | goto put_chain; |
| 164 | } | 169 | } |
| 165 | 170 | ||
| 166 | p->flags = lflags; | 171 | p->flags = lflags; |
| 167 | d->tcf_action = parm->action; | ||
| 168 | 172 | ||
| 169 | if (ovr) | 173 | if (ovr) |
| 170 | spin_lock_bh(&d->tcf_lock); | 174 | spin_lock_bh(&d->tcf_lock); |
| 171 | /* Protected by tcf_lock if overwriting existing action. */ | 175 | /* Protected by tcf_lock if overwriting existing action. */ |
| 176 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); | ||
| 172 | p_old = rcu_dereference_protected(d->skbmod_p, 1); | 177 | p_old = rcu_dereference_protected(d->skbmod_p, 1); |
| 173 | 178 | ||
| 174 | if (lflags & SKBMOD_F_DMAC) | 179 | if (lflags & SKBMOD_F_DMAC) |
| @@ -184,10 +189,18 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 184 | 189 | ||
| 185 | if (p_old) | 190 | if (p_old) |
| 186 | kfree_rcu(p_old, rcu); | 191 | kfree_rcu(p_old, rcu); |
| 192 | if (goto_ch) | ||
| 193 | tcf_chain_put_by_act(goto_ch); | ||
| 187 | 194 | ||
| 188 | if (ret == ACT_P_CREATED) | 195 | if (ret == ACT_P_CREATED) |
| 189 | tcf_idr_insert(tn, *a); | 196 | tcf_idr_insert(tn, *a); |
| 190 | return ret; | 197 | return ret; |
| 198 | put_chain: | ||
| 199 | if (goto_ch) | ||
| 200 | tcf_chain_put_by_act(goto_ch); | ||
| 201 | release_idr: | ||
| 202 | tcf_idr_release(*a, bind); | ||
| 203 | return err; | ||
| 191 | } | 204 | } |
| 192 | 205 | ||
| 193 | static void tcf_skbmod_cleanup(struct tc_action *a) | 206 | static void tcf_skbmod_cleanup(struct tc_action *a) |
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json index fe3326e939c1..6eb4c4f97060 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json +++ b/tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json | |||
| @@ -392,5 +392,30 @@ | |||
| 392 | "teardown": [ | 392 | "teardown": [ |
| 393 | "$TC actions flush action skbmod" | 393 | "$TC actions flush action skbmod" |
| 394 | ] | 394 | ] |
| 395 | }, | ||
| 396 | { | ||
| 397 | "id": "b651", | ||
| 398 | "name": "Replace skbmod action with invalid goto_chain control", | ||
| 399 | "category": [ | ||
| 400 | "actions", | ||
| 401 | "skbmod" | ||
| 402 | ], | ||
| 403 | "setup": [ | ||
| 404 | [ | ||
| 405 | "$TC actions flush action skbmod", | ||
| 406 | 0, | ||
| 407 | 1, | ||
| 408 | 255 | ||
| 409 | ], | ||
| 410 | "$TC actions add action skbmod set etype 0x1111 pass index 90" | ||
| 411 | ], | ||
| 412 | "cmdUnderTest": "$TC actions replace action skbmod set etype 0x1111 goto chain 42 index 90 cookie c1a0c1a0", | ||
| 413 | "expExitCode": "255", | ||
| 414 | "verifyCmd": "$TC actions ls action skbmod", | ||
| 415 | "matchPattern": "action order [0-9]*: skbmod pass set etype 0x1111\\s+index 90 ref", | ||
| 416 | "matchCount": "1", | ||
| 417 | "teardown": [ | ||
| 418 | "$TC actions flush action skbmod" | ||
| 419 | ] | ||
| 395 | } | 420 | } |
| 396 | ] | 421 | ] |
