net/sched: cls_route: make netlink errors meaningful
authorPedro Tammela <pctammela@mojatatu.com>
Mon, 11 Sep 2023 21:50:16 +0000 (18:50 -0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 13 Sep 2023 11:38:52 +0000 (12:38 +0100)
Use netlink extended ack and parsing policies to return more meaningful
errors instead of the relying solely on errnos.

Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/cls_route.c

index 1e20bbd687f1df483be6952ebdf3b01b7745f1c6..1424bfeaca73ff986813a9440d444fee22c12bc9 100644 (file)
@@ -375,9 +375,9 @@ out:
 
 static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
        [TCA_ROUTE4_CLASSID]    = { .type = NLA_U32 },
-       [TCA_ROUTE4_TO]         = { .type = NLA_U32 },
-       [TCA_ROUTE4_FROM]       = { .type = NLA_U32 },
-       [TCA_ROUTE4_IIF]        = { .type = NLA_U32 },
+       [TCA_ROUTE4_TO]         = NLA_POLICY_MAX(NLA_U32, 0xFF),
+       [TCA_ROUTE4_FROM]       = NLA_POLICY_MAX(NLA_U32, 0xFF),
+       [TCA_ROUTE4_IIF]        = NLA_POLICY_MAX(NLA_U32, 0x7FFF),
 };
 
 static int route4_set_parms(struct net *net, struct tcf_proto *tp,
@@ -397,33 +397,37 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
                return err;
 
        if (tb[TCA_ROUTE4_TO]) {
-               if (new && handle & 0x8000)
+               if (new && handle & 0x8000) {
+                       NL_SET_ERR_MSG(extack, "Invalid handle");
                        return -EINVAL;
+               }
                to = nla_get_u32(tb[TCA_ROUTE4_TO]);
-               if (to > 0xFF)
-                       return -EINVAL;
                nhandle = to;
        }
 
+       if (tb[TCA_ROUTE4_FROM] && tb[TCA_ROUTE4_IIF]) {
+               NL_SET_ERR_MSG_ATTR(extack, tb[TCA_ROUTE4_FROM],
+                                   "'from' and 'fromif' are mutually exclusive");
+               return -EINVAL;
+       }
+
        if (tb[TCA_ROUTE4_FROM]) {
-               if (tb[TCA_ROUTE4_IIF])
-                       return -EINVAL;
                id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
-               if (id > 0xFF)
-                       return -EINVAL;
                nhandle |= id << 16;
        } else if (tb[TCA_ROUTE4_IIF]) {
                id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
-               if (id > 0x7FFF)
-                       return -EINVAL;
                nhandle |= (id | 0x8000) << 16;
        } else
                nhandle |= 0xFFFF << 16;
 
        if (handle && new) {
                nhandle |= handle & 0x7F00;
-               if (nhandle != handle)
+               if (nhandle != handle) {
+                       NL_SET_ERR_MSG_FMT(extack,
+                                          "Handle mismatch constructed: %x (expected: %x)",
+                                          handle, nhandle);
                        return -EINVAL;
+               }
        }
 
        if (!nhandle) {
@@ -478,7 +482,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
        struct route4_filter __rcu **fp;
        struct route4_filter *fold, *f1, *pfp, *f = NULL;
        struct route4_bucket *b;
-       struct nlattr *opt = tca[TCA_OPTIONS];
        struct nlattr *tb[TCA_ROUTE4_MAX + 1];
        unsigned int h, th;
        int err;
@@ -489,10 +492,12 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
                return -EINVAL;
        }
 
-       if (opt == NULL)
+       if (NL_REQ_ATTR_CHECK(extack, NULL, tca, TCA_OPTIONS)) {
+               NL_SET_ERR_MSG_MOD(extack, "Missing options");
                return -EINVAL;
+       }
 
-       err = nla_parse_nested_deprecated(tb, TCA_ROUTE4_MAX, opt,
+       err = nla_parse_nested_deprecated(tb, TCA_ROUTE4_MAX, tca[TCA_OPTIONS],
                                          route4_policy, NULL);
        if (err < 0)
                return err;