2626#include <net/ip.h>
2727#include <net/ipv6.h>
2828#include <net/dsfield.h>
29+ #include <net/pkt_cls.h>
2930
3031#include <linux/tc_act/tc_skbedit.h>
3132#include <net/tc_act/tc_skbedit.h>
@@ -100,6 +101,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
100101 struct netlink_ext_ack * extack )
101102{
102103 struct tc_action_net * tn = net_generic (net , skbedit_net_id );
104+ struct tcf_chain * newchain = NULL , * oldchain ;
103105 struct tcf_skbedit_params * params_new ;
104106 struct nlattr * tb [TCA_SKBEDIT_MAX + 1 ];
105107 struct tc_skbedit * parm ;
@@ -187,12 +189,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
187189 return - EEXIST ;
188190 }
189191 }
192+ err = tcf_action_check_ctrlact (parm -> action , tp , & newchain , extack );
193+ if (err )
194+ goto release_idr ;
190195
191196 params_new = kzalloc (sizeof (* params_new ), GFP_KERNEL );
192- if (unlikely (!params_new )) {
193- tcf_idr_release (* a , bind );
194- return - ENOMEM ;
195- }
197+ if (unlikely (!params_new ))
198+ goto put_chain ;
196199
197200 params_new -> flags = flags ;
198201 if (flags & SKBEDIT_F_PRIORITY )
@@ -209,6 +212,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
209212 params_new -> mask = * mask ;
210213
211214 spin_lock_bh (& d -> tcf_lock );
215+ oldchain = d -> tcf_goto_chain ;
216+ d -> tcf_goto_chain = newchain ;
212217 d -> tcf_action = parm -> action ;
213218 rcu_swap_protected (d -> params , params_new ,
214219 lockdep_is_held (& d -> tcf_lock ));
@@ -218,7 +223,16 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
218223
219224 if (ret == ACT_P_CREATED )
220225 tcf_idr_insert (tn , * a );
226+ if (oldchain )
227+ tcf_chain_put_by_act (oldchain );
221228 return ret ;
229+
230+ put_chain :
231+ if (newchain )
232+ tcf_chain_put_by_act (newchain );
233+ release_idr :
234+ tcf_idr_release (* a , bind );
235+ return err ;
222236}
223237
224238static int tcf_skbedit_dump (struct sk_buff * skb , struct tc_action * a ,
0 commit comments