History

Merge branch 'net-sched-action-bind'

Pedro Tammela says: ==================== net/sched: fix action bind logic Some actions are not handling the case where an action can be created and bound to a filter independently. These actions are checking for parameters only passed in the netlink message for create/change/replace, which then errors out for valid uses like: tc filter ... action pedit index 1 In the iproute2 side, we saw a couple of actions with their parsers broken when passing "index 1" as the only action argument, while the kernel side accepted it correctly. We fixed those as well. ====================

David S. Miller committed 3 years ago

Commit 3fa10562 parents aaa3c08 4a200563 files · +77 −58Browse files

Unified · Split

3 files
  1. net/sched/act_mpls.c +37 −29
  2. net/sched/act_pedit.c +31 −27
  3. net/sched/act_sample.c +9 −2
net/sched/act_mpls.c+37−29
@@ -190,40 +190,67 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, · 189 unmodified lines
190 parm = nla_data(tb[TCA_MPLS_PARMS]);190 parm = nla_data(tb[TCA_MPLS_PARMS]);
191 index = parm->index;191 index = parm->index;
192 192
193 err = tcf_idr_check_alloc(tn, &index, a, bind);
194 if (err < 0)
195 return err;
196 exists = err;
197 if (exists && bind)
198 return 0;
199
200 if (!exists) {
201 ret = tcf_idr_create(tn, index, est, a, &act_mpls_ops, bind,
202 true, flags);
203 if (ret) {
204 tcf_idr_cleanup(tn, index);
205 return ret;
206 }
207
208 ret = ACT_P_CREATED;
209 } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
210 tcf_idr_release(*a, bind);
211 return -EEXIST;
212 }
213
193 /* Verify parameters against action type. */214 /* Verify parameters against action type. */
194 switch (parm->m_action) {215 switch (parm->m_action) {
195 case TCA_MPLS_ACT_POP:216 case TCA_MPLS_ACT_POP:
196 if (!tb[TCA_MPLS_PROTO]) {217 if (!tb[TCA_MPLS_PROTO]) {
197 NL_SET_ERR_MSG_MOD(extack, "Protocol must be set for MPLS pop");218 NL_SET_ERR_MSG_MOD(extack, "Protocol must be set for MPLS pop");
198 return -EINVAL;219 err = -EINVAL;
220 goto release_idr;
199 }221 }
200 if (!eth_proto_is_802_3(nla_get_be16(tb[TCA_MPLS_PROTO]))) {222 if (!eth_proto_is_802_3(nla_get_be16(tb[TCA_MPLS_PROTO]))) {
201 NL_SET_ERR_MSG_MOD(extack, "Invalid protocol type for MPLS pop");223 NL_SET_ERR_MSG_MOD(extack, "Invalid protocol type for MPLS pop");
202 return -EINVAL;224 err = -EINVAL;
225 goto release_idr;
203 }226 }
204 if (tb[TCA_MPLS_LABEL] || tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] ||227 if (tb[TCA_MPLS_LABEL] || tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] ||
205 tb[TCA_MPLS_BOS]) {228 tb[TCA_MPLS_BOS]) {
206 NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC or BOS cannot be used with MPLS pop");229 NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC or BOS cannot be used with MPLS pop");
207 return -EINVAL;230 err = -EINVAL;
231 goto release_idr;
208 }232 }
209 break;233 break;
210 case TCA_MPLS_ACT_DEC_TTL:234 case TCA_MPLS_ACT_DEC_TTL:
211 if (tb[TCA_MPLS_PROTO] || tb[TCA_MPLS_LABEL] ||235 if (tb[TCA_MPLS_PROTO] || tb[TCA_MPLS_LABEL] ||
212 tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] || tb[TCA_MPLS_BOS]) {236 tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] || tb[TCA_MPLS_BOS]) {
213 NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC, BOS or protocol cannot be used with MPLS dec_ttl");237 NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC, BOS or protocol cannot be used with MPLS dec_ttl");
214 return -EINVAL;238 err = -EINVAL;
239 goto release_idr;
215 }240 }
216 break;241 break;
217 case TCA_MPLS_ACT_PUSH:242 case TCA_MPLS_ACT_PUSH:
218 case TCA_MPLS_ACT_MAC_PUSH:243 case TCA_MPLS_ACT_MAC_PUSH:
219 if (!tb[TCA_MPLS_LABEL]) {244 if (!tb[TCA_MPLS_LABEL]) {
220 NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push");245 NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push");
221 return -EINVAL;246 err = -EINVAL;
247 goto release_idr;
222 }248 }
223 if (tb[TCA_MPLS_PROTO] &&249 if (tb[TCA_MPLS_PROTO] &&
224 !eth_p_mpls(nla_get_be16(tb[TCA_MPLS_PROTO]))) {250 !eth_p_mpls(nla_get_be16(tb[TCA_MPLS_PROTO]))) {
225 NL_SET_ERR_MSG_MOD(extack, "Protocol must be an MPLS type for MPLS push");251 NL_SET_ERR_MSG_MOD(extack, "Protocol must be an MPLS type for MPLS push");
226 return -EPROTONOSUPPORT;252 err = -EPROTONOSUPPORT;
253 goto release_idr;
227 }254 }
228 /* Push needs a TTL - if not specified, set a default value. */255 /* Push needs a TTL - if not specified, set a default value. */
229 if (!tb[TCA_MPLS_TTL]) {256 if (!tb[TCA_MPLS_TTL]) {
@@ -238,33 +265,14 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, · 8 unmodified lines
238 case TCA_MPLS_ACT_MODIFY:265 case TCA_MPLS_ACT_MODIFY:
239 if (tb[TCA_MPLS_PROTO]) {266 if (tb[TCA_MPLS_PROTO]) {
240 NL_SET_ERR_MSG_MOD(extack, "Protocol cannot be used with MPLS modify");267 NL_SET_ERR_MSG_MOD(extack, "Protocol cannot be used with MPLS modify");
241 return -EINVAL;268 err = -EINVAL;
269 goto release_idr;
242 }270 }
243 break;271 break;
244 default:272 default:
245 NL_SET_ERR_MSG_MOD(extack, "Unknown MPLS action");273 NL_SET_ERR_MSG_MOD(extack, "Unknown MPLS action");
246 return -EINVAL;274 err = -EINVAL;
247 }275 goto release_idr;
248
249 err = tcf_idr_check_alloc(tn, &index, a, bind);
250 if (err < 0)
251 return err;
252 exists = err;
253 if (exists && bind)
254 return 0;
255
256 if (!exists) {
257 ret = tcf_idr_create(tn, index, est, a,
258 &act_mpls_ops, bind, true, flags);
259 if (ret) {
260 tcf_idr_cleanup(tn, index);
261 return ret;
262 }
263
264 ret = ACT_P_CREATED;
265 } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
266 tcf_idr_release(*a, bind);
267 return -EEXIST;
268 }276 }
269 277
270 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);278 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
net/sched/act_pedit.c+31−27
@@ -181,26 +181,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, · 180 unmodified lines
181 }181 }
182 182
183 parm = nla_data(pattr);183 parm = nla_data(pattr);
184 if (!parm->nkeys) {
185 NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
186 return -EINVAL;
187 }
188 ksize = parm->nkeys * sizeof(struct tc_pedit_key);
189 if (nla_len(pattr) < sizeof(*parm) + ksize) {
190 NL_SET_ERR_MSG_ATTR(extack, pattr, "Length of TCA_PEDIT_PARMS or TCA_PEDIT_PARMS_EX pedit attribute is invalid");
191 return -EINVAL;
192 }
193
194 nparms = kzalloc(sizeof(*nparms), GFP_KERNEL);
195 if (!nparms)
196 return -ENOMEM;
197
198 nparms->tcfp_keys_ex =
199 tcf_pedit_keys_ex_parse(tb[TCA_PEDIT_KEYS_EX], parm->nkeys);
200 if (IS_ERR(nparms->tcfp_keys_ex)) {
201 ret = PTR_ERR(nparms->tcfp_keys_ex);
202 goto out_free;
203 }
204 184
205 index = parm->index;185 index = parm->index;
206 err = tcf_idr_check_alloc(tn, &index, a, bind);186 err = tcf_idr_check_alloc(tn, &index, a, bind);
@@ -209,25 +189,49 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, · 2 unmodified lines
209 &act_pedit_ops, bind, flags);189 &act_pedit_ops, bind, flags);
210 if (ret) {190 if (ret) {
211 tcf_idr_cleanup(tn, index);191 tcf_idr_cleanup(tn, index);
212 goto out_free_ex;192 return ret;
213 }193 }
214 ret = ACT_P_CREATED;194 ret = ACT_P_CREATED;
215 } else if (err > 0) {195 } else if (err > 0) {
216 if (bind)196 if (bind)
217 goto out_free;197 return 0;
218 if (!(flags & TCA_ACT_FLAGS_REPLACE)) {198 if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
219 ret = -EEXIST;199 ret = -EEXIST;
220 goto out_release;200 goto out_release;
221 }201 }
222 } else {202 } else {
223 ret = err;203 return err;
224 goto out_free_ex;204 }
205
206 if (!parm->nkeys) {
207 NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
208 ret = -EINVAL;
209 goto out_release;
210 }
211 ksize = parm->nkeys * sizeof(struct tc_pedit_key);
212 if (nla_len(pattr) < sizeof(*parm) + ksize) {
213 NL_SET_ERR_MSG_ATTR(extack, pattr, "Length of TCA_PEDIT_PARMS or TCA_PEDIT_PARMS_EX pedit attribute is invalid");
214 ret = -EINVAL;
215 goto out_release;
216 }
217
218 nparms = kzalloc(sizeof(*nparms), GFP_KERNEL);
219 if (!nparms) {
220 ret = -ENOMEM;
221 goto out_release;
222 }
223
224 nparms->tcfp_keys_ex =
225 tcf_pedit_keys_ex_parse(tb[TCA_PEDIT_KEYS_EX], parm->nkeys);
226 if (IS_ERR(nparms->tcfp_keys_ex)) {
227 ret = PTR_ERR(nparms->tcfp_keys_ex);
228 goto out_free;
225 }229 }
226 230
227 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);231 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
228 if (err < 0) {232 if (err < 0) {
229 ret = err;233 ret = err;
230 goto out_release;234 goto out_free_ex;
231 }235 }
232 236
233 nparms->tcfp_off_max_hint = 0;237 nparms->tcfp_off_max_hint = 0;
@@ -278,12 +282,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, · 44 unmodified lines
278put_chain:282put_chain:
279 if (goto_ch)283 if (goto_ch)
280 tcf_chain_put_by_act(goto_ch);284 tcf_chain_put_by_act(goto_ch);
281out_release:
282 tcf_idr_release(*a, bind);
283out_free_ex:285out_free_ex:
284 kfree(nparms->tcfp_keys_ex);286 kfree(nparms->tcfp_keys_ex);
285out_free:287out_free:
286 kfree(nparms);288 kfree(nparms);
289out_release:
290 tcf_idr_release(*a, bind);
287 return ret;291 return ret;
288}292}
289 293
net/sched/act_sample.c+9−2
@@ -55,8 +55,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, · 54 unmodified lines
55 sample_policy, NULL);55 sample_policy, NULL);
56 if (ret < 0)56 if (ret < 0)
57 return ret;57 return ret;
58 if (!tb[TCA_SAMPLE_PARMS] || !tb[TCA_SAMPLE_RATE] ||58
59 !tb[TCA_SAMPLE_PSAMPLE_GROUP])59 if (!tb[TCA_SAMPLE_PARMS])
60 return -EINVAL;60 return -EINVAL;
61 61
62 parm = nla_data(tb[TCA_SAMPLE_PARMS]);62 parm = nla_data(tb[TCA_SAMPLE_PARMS]);
@@ -80,6 +80,13 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, · 17 unmodified lines
80 tcf_idr_release(*a, bind);80 tcf_idr_release(*a, bind);
81 return -EEXIST;81 return -EEXIST;
82 }82 }
83
84 if (!tb[TCA_SAMPLE_RATE] || !tb[TCA_SAMPLE_PSAMPLE_GROUP]) {
85 NL_SET_ERR_MSG(extack, "sample rate and group are required");
86 err = -EINVAL;
87 goto release_idr;
88 }
89
83 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);90 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
84 if (err < 0)91 if (err < 0)
85 goto release_idr;92 goto release_idr;