aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/act_skbmod.c19
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/skbmod.json25
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;
198put_chain:
199 if (goto_ch)
200 tcf_chain_put_by_act(goto_ch);
201release_idr:
202 tcf_idr_release(*a, bind);
203 return err;
191} 204}
192 205
193static void tcf_skbmod_cleanup(struct tc_action *a) 206static 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]