forked from mirrors/linux
		
	flow_offload: validate flags of filter and actions
Add process to validate flags of filter and actions when adding a tc filter. We need to prevent adding filter with flags conflicts with its actions. Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com> Signed-off-by: Louis Peens <louis.peens@corigine.com> Signed-off-by: Simon Horman <simon.horman@corigine.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									13926d19a1
								
							
						
					
					
						commit
						c86e0209dc
					
				
					 7 changed files with 51 additions and 20 deletions
				
			
		|  | @ -203,7 +203,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions, | |||
| int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, | ||||
| 		    struct nlattr *est, | ||||
| 		    struct tc_action *actions[], int init_res[], size_t *attr_size, | ||||
| 		    u32 flags, struct netlink_ext_ack *extack); | ||||
| 		    u32 flags, u32 fl_flags, struct netlink_ext_ack *extack); | ||||
| struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, bool police, | ||||
| 					 bool rtnl_held, | ||||
| 					 struct netlink_ext_ack *extack); | ||||
|  |  | |||
|  | @ -330,6 +330,9 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, | |||
| 		      struct nlattr **tb, struct nlattr *rate_tlv, | ||||
| 		      struct tcf_exts *exts, u32 flags, | ||||
| 		      struct netlink_ext_ack *extack); | ||||
| int tcf_exts_validate_ex(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | ||||
| 			 struct nlattr *rate_tlv, struct tcf_exts *exts, | ||||
| 			 u32 flags, u32 fl_flags, struct netlink_ext_ack *extack); | ||||
| void tcf_exts_destroy(struct tcf_exts *exts); | ||||
| void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src); | ||||
| int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts); | ||||
|  |  | |||
|  | @ -1385,7 +1385,8 @@ static bool tc_act_bind(u32 flags) | |||
| 
 | ||||
| int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, | ||||
| 		    struct nlattr *est, struct tc_action *actions[], | ||||
| 		    int init_res[], size_t *attr_size, u32 flags, | ||||
| 		    int init_res[], size_t *attr_size, | ||||
| 		    u32 flags, u32 fl_flags, | ||||
| 		    struct netlink_ext_ack *extack) | ||||
| { | ||||
| 	struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {}; | ||||
|  | @ -1423,7 +1424,18 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, | |||
| 		sz += tcf_action_fill_size(act); | ||||
| 		/* Start from index 0 */ | ||||
| 		actions[i - 1] = act; | ||||
| 		if (!tc_act_bind(flags)) { | ||||
| 		if (tc_act_bind(flags)) { | ||||
| 			bool skip_sw = tc_skip_sw(fl_flags); | ||||
| 			bool skip_hw = tc_skip_hw(fl_flags); | ||||
| 
 | ||||
| 			if (tc_act_bind(act->tcfa_flags)) | ||||
| 				continue; | ||||
| 			if (skip_sw != tc_act_skip_sw(act->tcfa_flags) || | ||||
| 			    skip_hw != tc_act_skip_hw(act->tcfa_flags)) { | ||||
| 				err = -EINVAL; | ||||
| 				goto err; | ||||
| 			} | ||||
| 		} else { | ||||
| 			err = tcf_action_offload_add(act, extack); | ||||
| 			if (tc_act_skip_sw(act->tcfa_flags) && err) | ||||
| 				goto err; | ||||
|  | @ -1926,7 +1938,7 @@ static int tcf_action_add(struct net *net, struct nlattr *nla, | |||
| 
 | ||||
| 	for (loop = 0; loop < 10; loop++) { | ||||
| 		ret = tcf_action_init(net, NULL, nla, NULL, actions, init_res, | ||||
| 				      &attr_size, flags, extack); | ||||
| 				      &attr_size, flags, 0, extack); | ||||
| 		if (ret != -EAGAIN) | ||||
| 			break; | ||||
| 	} | ||||
|  |  | |||
|  | @ -3025,9 +3025,9 @@ void tcf_exts_destroy(struct tcf_exts *exts) | |||
| } | ||||
| EXPORT_SYMBOL(tcf_exts_destroy); | ||||
| 
 | ||||
| int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | ||||
| 		      struct nlattr *rate_tlv, struct tcf_exts *exts, | ||||
| 		      u32 flags, struct netlink_ext_ack *extack) | ||||
| int tcf_exts_validate_ex(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | ||||
| 			 struct nlattr *rate_tlv, struct tcf_exts *exts, | ||||
| 			 u32 flags, u32 fl_flags, struct netlink_ext_ack *extack) | ||||
| { | ||||
| #ifdef CONFIG_NET_CLS_ACT | ||||
| 	{ | ||||
|  | @ -3061,7 +3061,8 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | |||
| 			flags |= TCA_ACT_FLAGS_BIND; | ||||
| 			err = tcf_action_init(net, tp, tb[exts->action], | ||||
| 					      rate_tlv, exts->actions, init_res, | ||||
| 					      &attr_size, flags, extack); | ||||
| 					      &attr_size, flags, fl_flags, | ||||
| 					      extack); | ||||
| 			if (err < 0) | ||||
| 				return err; | ||||
| 			exts->nr_actions = err; | ||||
|  | @ -3077,6 +3078,15 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | |||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(tcf_exts_validate_ex); | ||||
| 
 | ||||
| int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, | ||||
| 		      struct nlattr *rate_tlv, struct tcf_exts *exts, | ||||
| 		      u32 flags, struct netlink_ext_ack *extack) | ||||
| { | ||||
| 	return tcf_exts_validate_ex(net, tp, tb, rate_tlv, exts, | ||||
| 				    flags, 0, extack); | ||||
| } | ||||
| EXPORT_SYMBOL(tcf_exts_validate); | ||||
| 
 | ||||
| void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src) | ||||
|  |  | |||
|  | @ -1917,12 +1917,14 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp, | |||
| 			struct cls_fl_filter *f, struct fl_flow_mask *mask, | ||||
| 			unsigned long base, struct nlattr **tb, | ||||
| 			struct nlattr *est, | ||||
| 			struct fl_flow_tmplt *tmplt, u32 flags, | ||||
| 			struct fl_flow_tmplt *tmplt, | ||||
| 			u32 flags, u32 fl_flags, | ||||
| 			struct netlink_ext_ack *extack) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = tcf_exts_validate(net, tp, tb, est, &f->exts, flags, extack); | ||||
| 	err = tcf_exts_validate_ex(net, tp, tb, est, &f->exts, flags, | ||||
| 				   fl_flags, extack); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -2036,7 +2038,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, | |||
| 	} | ||||
| 
 | ||||
| 	err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], | ||||
| 			   tp->chain->tmplt_priv, flags, extack); | ||||
| 			   tp->chain->tmplt_priv, flags, fnew->flags, | ||||
| 			   extack); | ||||
| 	if (err) | ||||
| 		goto errout; | ||||
| 
 | ||||
|  |  | |||
|  | @ -163,12 +163,13 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = { | |||
| static int mall_set_parms(struct net *net, struct tcf_proto *tp, | ||||
| 			  struct cls_mall_head *head, | ||||
| 			  unsigned long base, struct nlattr **tb, | ||||
| 			  struct nlattr *est, u32 flags, | ||||
| 			  struct nlattr *est, u32 flags, u32 fl_flags, | ||||
| 			  struct netlink_ext_ack *extack) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = tcf_exts_validate(net, tp, tb, est, &head->exts, flags, extack); | ||||
| 	err = tcf_exts_validate_ex(net, tp, tb, est, &head->exts, flags, | ||||
| 				   fl_flags, extack); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -226,8 +227,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, | |||
| 		goto err_alloc_percpu; | ||||
| 	} | ||||
| 
 | ||||
| 	err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], flags, | ||||
| 			     extack); | ||||
| 	err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], | ||||
| 			     flags, new->flags, extack); | ||||
| 	if (err) | ||||
| 		goto err_set_parms; | ||||
| 
 | ||||
|  |  | |||
|  | @ -709,12 +709,13 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { | |||
| static int u32_set_parms(struct net *net, struct tcf_proto *tp, | ||||
| 			 unsigned long base, | ||||
| 			 struct tc_u_knode *n, struct nlattr **tb, | ||||
| 			 struct nlattr *est, u32 flags, | ||||
| 			 struct nlattr *est, u32 flags, u32 fl_flags, | ||||
| 			 struct netlink_ext_ack *extack) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = tcf_exts_validate(net, tp, tb, est, &n->exts, flags, extack); | ||||
| 	err = tcf_exts_validate_ex(net, tp, tb, est, &n->exts, flags, | ||||
| 				   fl_flags, extack); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
|  | @ -895,7 +896,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, | |||
| 			return -ENOMEM; | ||||
| 
 | ||||
| 		err = u32_set_parms(net, tp, base, new, tb, | ||||
| 				    tca[TCA_RATE], flags, extack); | ||||
| 				    tca[TCA_RATE], flags, new->flags, | ||||
| 				    extack); | ||||
| 
 | ||||
| 		if (err) { | ||||
| 			u32_destroy_key(new, false); | ||||
|  | @ -1060,8 +1062,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, | |||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE], flags, | ||||
| 			    extack); | ||||
| 	err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE], | ||||
| 			    flags, n->flags, extack); | ||||
| 	if (err == 0) { | ||||
| 		struct tc_u_knode __rcu **ins; | ||||
| 		struct tc_u_knode *pins; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Baowen Zheng
						Baowen Zheng