Skip to content

Commit 26a2219

Browse files
vbnogueiradavem330
authored andcommitted
net: sched: cls_bpf: Undo tcf_bind_filter in case of an error
If cls_bpf_offload errors out, we must also undo tcf_bind_filter that was done before the error. Fix that by calling tcf_unbind_filter in errout_parms. Fixes: eadb414 ("net: cls_bpf: add support for marking filters as hardware-only") Signed-off-by: Victor Nogueira <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Reviewed-by: Pedro Tammela <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e8d3d78 commit 26a2219

File tree

1 file changed

+47
-52
lines changed

1 file changed

+47
-52
lines changed

net/sched/cls_bpf.c

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -406,66 +406,19 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
406406
return 0;
407407
}
408408

409-
static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
410-
struct cls_bpf_prog *prog, unsigned long base,
411-
struct nlattr **tb, struct nlattr *est, u32 flags,
412-
struct netlink_ext_ack *extack)
413-
{
414-
bool is_bpf, is_ebpf, have_exts = false;
415-
u32 gen_flags = 0;
416-
int ret;
417-
418-
is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
419-
is_ebpf = tb[TCA_BPF_FD];
420-
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
421-
return -EINVAL;
422-
423-
ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, flags,
424-
extack);
425-
if (ret < 0)
426-
return ret;
427-
428-
if (tb[TCA_BPF_FLAGS]) {
429-
u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
430-
431-
if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT)
432-
return -EINVAL;
433-
434-
have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
435-
}
436-
if (tb[TCA_BPF_FLAGS_GEN]) {
437-
gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
438-
if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
439-
!tc_flags_valid(gen_flags))
440-
return -EINVAL;
441-
}
442-
443-
prog->exts_integrated = have_exts;
444-
prog->gen_flags = gen_flags;
445-
446-
ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
447-
cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
448-
if (ret < 0)
449-
return ret;
450-
451-
if (tb[TCA_BPF_CLASSID]) {
452-
prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
453-
tcf_bind_filter(tp, &prog->res, base);
454-
}
455-
456-
return 0;
457-
}
458-
459409
static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
460410
struct tcf_proto *tp, unsigned long base,
461411
u32 handle, struct nlattr **tca,
462412
void **arg, u32 flags,
463413
struct netlink_ext_ack *extack)
464414
{
465415
struct cls_bpf_head *head = rtnl_dereference(tp->root);
416+
bool is_bpf, is_ebpf, have_exts = false;
466417
struct cls_bpf_prog *oldprog = *arg;
467418
struct nlattr *tb[TCA_BPF_MAX + 1];
419+
bool bound_to_filter = false;
468420
struct cls_bpf_prog *prog;
421+
u32 gen_flags = 0;
469422
int ret;
470423

471424
if (tca[TCA_OPTIONS] == NULL)
@@ -504,11 +457,51 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
504457
goto errout;
505458
prog->handle = handle;
506459

507-
ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], flags,
508-
extack);
460+
is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
461+
is_ebpf = tb[TCA_BPF_FD];
462+
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) {
463+
ret = -EINVAL;
464+
goto errout_idr;
465+
}
466+
467+
ret = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &prog->exts,
468+
flags, extack);
469+
if (ret < 0)
470+
goto errout_idr;
471+
472+
if (tb[TCA_BPF_FLAGS]) {
473+
u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
474+
475+
if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) {
476+
ret = -EINVAL;
477+
goto errout_idr;
478+
}
479+
480+
have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
481+
}
482+
if (tb[TCA_BPF_FLAGS_GEN]) {
483+
gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
484+
if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
485+
!tc_flags_valid(gen_flags)) {
486+
ret = -EINVAL;
487+
goto errout_idr;
488+
}
489+
}
490+
491+
prog->exts_integrated = have_exts;
492+
prog->gen_flags = gen_flags;
493+
494+
ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
495+
cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
509496
if (ret < 0)
510497
goto errout_idr;
511498

499+
if (tb[TCA_BPF_CLASSID]) {
500+
prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
501+
tcf_bind_filter(tp, &prog->res, base);
502+
bound_to_filter = true;
503+
}
504+
512505
ret = cls_bpf_offload(tp, prog, oldprog, extack);
513506
if (ret)
514507
goto errout_parms;
@@ -530,6 +523,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
530523
return 0;
531524

532525
errout_parms:
526+
if (bound_to_filter)
527+
tcf_unbind_filter(tp, &prog->res);
533528
cls_bpf_free_parms(prog);
534529
errout_idr:
535530
if (!oldprog)

0 commit comments

Comments
 (0)