Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+77 -58
+37 -29
net/sched/act_mpls.c
··· 190 190 parm = nla_data(tb[TCA_MPLS_PARMS]); 191 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 214 /* Verify parameters against action type. */ 194 215 switch (parm->m_action) { 195 216 case TCA_MPLS_ACT_POP: 196 217 if (!tb[TCA_MPLS_PROTO]) { 197 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 222 if (!eth_proto_is_802_3(nla_get_be16(tb[TCA_MPLS_PROTO]))) { 201 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 227 if (tb[TCA_MPLS_LABEL] || tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] || 205 228 tb[TCA_MPLS_BOS]) { 206 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 233 break; 210 234 case TCA_MPLS_ACT_DEC_TTL: 211 235 if (tb[TCA_MPLS_PROTO] || tb[TCA_MPLS_LABEL] || 212 236 tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] || tb[TCA_MPLS_BOS]) { 213 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 241 break; 217 242 case TCA_MPLS_ACT_PUSH: 218 243 case TCA_MPLS_ACT_MAC_PUSH: 219 244 if (!tb[TCA_MPLS_LABEL]) { 220 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 249 if (tb[TCA_MPLS_PROTO] && 224 250 !eth_p_mpls(nla_get_be16(tb[TCA_MPLS_PROTO]))) { 225 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 255 /* Push needs a TTL - if not specified, set a default value. */ 229 256 if (!tb[TCA_MPLS_TTL]) { ··· 265 238 case TCA_MPLS_ACT_MODIFY: 266 239 if (tb[TCA_MPLS_PROTO]) { 267 240 NL_SET_ERR_MSG_MOD(extack, "Protocol cannot be used with MPLS modify"); 268 - return -EINVAL; 241 + err = -EINVAL; 242 + goto release_idr; 269 243 } 270 244 break; 271 245 default: 272 246 NL_SET_ERR_MSG_MOD(extack, "Unknown MPLS action"); 273 - return -EINVAL; 274 - } 275 - 276 - err = tcf_idr_check_alloc(tn, &index, a, bind); 277 - if (err < 0) 278 - return err; 279 - exists = err; 280 - if (exists && bind) 281 - return 0; 282 - 283 - if (!exists) { 284 - ret = tcf_idr_create(tn, index, est, a, 285 - &act_mpls_ops, bind, true, flags); 286 - if (ret) { 287 - tcf_idr_cleanup(tn, index); 288 - return ret; 289 - } 290 - 291 - ret = ACT_P_CREATED; 292 - } else if (!(flags & TCA_ACT_FLAGS_REPLACE)) { 293 - tcf_idr_release(*a, bind); 294 - return -EEXIST; 247 + err = -EINVAL; 248 + goto release_idr; 295 249 } 296 250 297 251 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
+31 -27
net/sched/act_pedit.c
··· 181 181 } 182 182 183 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 185 index = parm->index; 206 186 err = tcf_idr_check_alloc(tn, &index, a, bind); ··· 189 209 &act_pedit_ops, bind, flags); 190 210 if (ret) { 191 211 tcf_idr_cleanup(tn, index); 192 - goto out_free_ex; 212 + return ret; 193 213 } 194 214 ret = ACT_P_CREATED; 195 215 } else if (err > 0) { 196 216 if (bind) 197 - goto out_free; 217 + return 0; 198 218 if (!(flags & TCA_ACT_FLAGS_REPLACE)) { 199 219 ret = -EEXIST; 200 220 goto out_release; 201 221 } 202 222 } else { 203 - ret = err; 204 - goto out_free_ex; 223 + return err; 224 + } 225 + 226 + if (!parm->nkeys) { 227 + NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed"); 228 + ret = -EINVAL; 229 + goto out_release; 230 + } 231 + ksize = parm->nkeys * sizeof(struct tc_pedit_key); 232 + if (nla_len(pattr) < sizeof(*parm) + ksize) { 233 + NL_SET_ERR_MSG_ATTR(extack, pattr, "Length of TCA_PEDIT_PARMS or TCA_PEDIT_PARMS_EX pedit attribute is invalid"); 234 + ret = -EINVAL; 235 + goto out_release; 236 + } 237 + 238 + nparms = kzalloc(sizeof(*nparms), GFP_KERNEL); 239 + if (!nparms) { 240 + ret = -ENOMEM; 241 + goto out_release; 242 + } 243 + 244 + nparms->tcfp_keys_ex = 245 + tcf_pedit_keys_ex_parse(tb[TCA_PEDIT_KEYS_EX], parm->nkeys); 246 + if (IS_ERR(nparms->tcfp_keys_ex)) { 247 + ret = PTR_ERR(nparms->tcfp_keys_ex); 248 + goto out_free; 205 249 } 206 250 207 251 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); 208 252 if (err < 0) { 209 253 ret = err; 210 - goto out_release; 254 + goto out_free_ex; 211 255 } 212 256 213 257 nparms->tcfp_off_max_hint = 0; ··· 282 278 put_chain: 283 279 if (goto_ch) 284 280 tcf_chain_put_by_act(goto_ch); 285 - out_release: 286 - tcf_idr_release(*a, bind); 287 281 out_free_ex: 288 282 kfree(nparms->tcfp_keys_ex); 289 283 out_free: 290 284 kfree(nparms); 285 + out_release: 286 + tcf_idr_release(*a, bind); 291 287 return ret; 292 288 } 293 289
+9 -2
net/sched/act_sample.c
··· 55 55 sample_policy, NULL); 56 56 if (ret < 0) 57 57 return ret; 58 - if (!tb[TCA_SAMPLE_PARMS] || !tb[TCA_SAMPLE_RATE] || 59 - !tb[TCA_SAMPLE_PSAMPLE_GROUP]) 58 + 59 + if (!tb[TCA_SAMPLE_PARMS]) 60 60 return -EINVAL; 61 61 62 62 parm = nla_data(tb[TCA_SAMPLE_PARMS]); ··· 80 80 tcf_idr_release(*a, bind); 81 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 90 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); 84 91 if (err < 0) 85 92 goto release_idr;