net: sched: cls_matchall: Undo tcf_bind_filter in case of failure after mall_set_parms
authorVictor Nogueira <victor@mojatatu.com>
Thu, 13 Jul 2023 18:05:10 +0000 (15:05 -0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Jul 2023 06:33:38 +0000 (07:33 +0100)
In case an error occurred after mall_set_parms executed successfully, we
must undo the tcf_bind_filter call it issues.

Fix that by calling tcf_unbind_filter in err_replace_hw_filter label.

Fixes: ec2507d2a306 ("net/sched: cls_matchall: Fix error path")
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/cls_matchall.c

index fa3bbd1..c4ed11d 100644 (file)
@@ -159,26 +159,6 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
        [TCA_MATCHALL_FLAGS]            = { .type = NLA_U32 },
 };
 
-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, u32 fl_flags,
-                         struct netlink_ext_ack *extack)
-{
-       int err;
-
-       err = tcf_exts_validate_ex(net, tp, tb, est, &head->exts, flags,
-                                  fl_flags, extack);
-       if (err < 0)
-               return err;
-
-       if (tb[TCA_MATCHALL_CLASSID]) {
-               head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
-               tcf_bind_filter(tp, &head->res, base);
-       }
-       return 0;
-}
-
 static int mall_change(struct net *net, struct sk_buff *in_skb,
                       struct tcf_proto *tp, unsigned long base,
                       u32 handle, struct nlattr **tca,
@@ -187,6 +167,7 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
        struct nlattr *tb[TCA_MATCHALL_MAX + 1];
+       bool bound_to_filter = false;
        struct cls_mall_head *new;
        u32 userflags = 0;
        int err;
@@ -226,11 +207,17 @@ 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, new->flags, extack);
-       if (err)
+       err = tcf_exts_validate_ex(net, tp, tb, tca[TCA_RATE],
+                                  &new->exts, flags, new->flags, extack);
+       if (err < 0)
                goto err_set_parms;
 
+       if (tb[TCA_MATCHALL_CLASSID]) {
+               new->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
+               tcf_bind_filter(tp, &new->res, base);
+               bound_to_filter = true;
+       }
+
        if (!tc_skip_hw(new->flags)) {
                err = mall_replace_hw_filter(tp, new, (unsigned long)new,
                                             extack);
@@ -246,6 +233,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
        return 0;
 
 err_replace_hw_filter:
+       if (bound_to_filter)
+               tcf_unbind_filter(tp, &new->res);
 err_set_parms:
        free_percpu(new->pf);
 err_alloc_percpu: