diff options
Diffstat (limited to 'net/sched/act_ife.c')
| -rw-r--r-- | net/sched/act_ife.c | 45 | 
1 files changed, 27 insertions, 18 deletions
| diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 9b1f2b3990ee..12489f60a979 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c @@ -29,6 +29,7 @@  #include <net/net_namespace.h>  #include <net/netlink.h>  #include <net/pkt_sched.h> +#include <net/pkt_cls.h>  #include <uapi/linux/tc_act/tc_ife.h>  #include <net/tc_act/tc_ife.h>  #include <linux/etherdevice.h> @@ -386,7 +387,7 @@ static int dump_metalist(struct sk_buff *skb, struct tcf_ife_info *ife)  	if (list_empty(&ife->metalist))  		return 0; -	nest = nla_nest_start(skb, TCA_IFE_METALST); +	nest = nla_nest_start_noflag(skb, TCA_IFE_METALST);  	if (!nest)  		goto out_nlmsg_trim; @@ -469,11 +470,12 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,  static int tcf_ife_init(struct net *net, struct nlattr *nla,  			struct nlattr *est, struct tc_action **a,  			int ovr, int bind, bool rtnl_held, -			struct netlink_ext_ack *extack) +			struct tcf_proto *tp, struct netlink_ext_ack *extack)  {  	struct tc_action_net *tn = net_generic(net, ife_net_id);  	struct nlattr *tb[TCA_IFE_MAX + 1];  	struct nlattr *tb2[IFE_META_MAX + 1]; +	struct tcf_chain *goto_ch = NULL;  	struct tcf_ife_params *p;  	struct tcf_ife_info *ife;  	u16 ife_type = ETH_P_IFE; @@ -484,7 +486,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,  	int ret = 0;  	int err; -	err = nla_parse_nested(tb, TCA_IFE_MAX, nla, ife_policy, NULL); +	err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy, +					  NULL);  	if (err < 0)  		return err; @@ -531,6 +534,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,  	}  	ife = to_ife(*a); +	err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); +	if (err < 0) +		goto release_idr; +  	p->flags = parm->flags;  	if (parm->flags & IFE_ENCODE) { @@ -561,15 +568,11 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,  		INIT_LIST_HEAD(&ife->metalist);  	if (tb[TCA_IFE_METALST]) { -		err = nla_parse_nested(tb2, IFE_META_MAX, tb[TCA_IFE_METALST], -				       NULL, NULL); -		if (err) { -metadata_parse_err: -			tcf_idr_release(*a, bind); -			kfree(p); -			return err; -		} - +		err = nla_parse_nested_deprecated(tb2, IFE_META_MAX, +						  tb[TCA_IFE_METALST], NULL, +						  NULL); +		if (err) +			goto metadata_parse_err;  		err = populate_metalist(ife, tb2, exists, rtnl_held);  		if (err)  			goto metadata_parse_err; @@ -581,21 +584,20 @@ metadata_parse_err:  		 * going to bail out  		 */  		err = use_all_metadata(ife, exists); -		if (err) { -			tcf_idr_release(*a, bind); -			kfree(p); -			return err; -		} +		if (err) +			goto metadata_parse_err;  	}  	if (exists)  		spin_lock_bh(&ife->tcf_lock); -	ife->tcf_action = parm->action;  	/* protected by tcf_lock when modifying existing action */ +	goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);  	rcu_swap_protected(ife->params, p, 1);  	if (exists)  		spin_unlock_bh(&ife->tcf_lock); +	if (goto_ch) +		tcf_chain_put_by_act(goto_ch);  	if (p)  		kfree_rcu(p, rcu); @@ -603,6 +605,13 @@ metadata_parse_err:  		tcf_idr_insert(tn, *a);  	return ret; +metadata_parse_err: +	if (goto_ch) +		tcf_chain_put_by_act(goto_ch); +release_idr: +	kfree(p); +	tcf_idr_release(*a, bind); +	return err;  }  static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, |