rtnetlink: Move input checking for rtnl_fdb_dump to helper
authorDavid Ahern <dsahern@gmail.com>
Mon, 8 Oct 2018 03:16:43 +0000 (20:16 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 8 Oct 2018 17:39:05 +0000 (10:39 -0700)
Move the existing input checking for rtnl_fdb_dump into a helper,
valid_fdb_dump_legacy. This function will retain the current
logic that works around the 2 headers that userspace has been
allowed to send up to this point.

Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Christian Brauner <christian@brauner.io>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/rtnetlink.c

index f6d2609cfa9fb75f19d84072293d3389b237fe51..c7509c789fb6ab16404d8b4c6f1756fed85e6e51 100644 (file)
@@ -3799,22 +3799,13 @@ out:
 }
 EXPORT_SYMBOL(ndo_dflt_fdb_dump);
 
-static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+static int valid_fdb_dump_legacy(const struct nlmsghdr *nlh,
+                                int *br_idx, int *brport_idx,
+                                struct netlink_ext_ack *extack)
 {
-       struct net_device *dev;
+       struct ifinfomsg *ifm = nlmsg_data(nlh);
        struct nlattr *tb[IFLA_MAX+1];
-       struct net_device *br_dev = NULL;
-       const struct net_device_ops *ops = NULL;
-       const struct net_device_ops *cops = NULL;
-       struct ifinfomsg *ifm = nlmsg_data(cb->nlh);
-       struct net *net = sock_net(skb->sk);
-       struct hlist_head *head;
-       int brport_idx = 0;
-       int br_idx = 0;
-       int h, s_h;
-       int idx = 0, s_idx;
-       int err = 0;
-       int fidx = 0;
+       int err;
 
        /* A hack to preserve kernel<->userspace interface.
         * Before Linux v4.12 this code accepted ndmsg since iproute2 v3.3.0.
@@ -3823,20 +3814,42 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
         * Fortunately these sizes don't conflict with the size of ifinfomsg
         * with an optional attribute.
         */
-       if (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) &&
-           (nlmsg_len(cb->nlh) != sizeof(struct ndmsg) +
+       if (nlmsg_len(nlh) != sizeof(struct ndmsg) &&
+           (nlmsg_len(nlh) != sizeof(struct ndmsg) +
             nla_attr_size(sizeof(u32)))) {
-               err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb,
-                                 IFLA_MAX, ifla_policy, cb->extack);
+               err = nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
+                                 ifla_policy, extack);
                if (err < 0) {
                        return -EINVAL;
                } else if (err == 0) {
                        if (tb[IFLA_MASTER])
-                               br_idx = nla_get_u32(tb[IFLA_MASTER]);
+                               *br_idx = nla_get_u32(tb[IFLA_MASTER]);
                }
 
-               brport_idx = ifm->ifi_index;
+               *brport_idx = ifm->ifi_index;
        }
+       return 0;
+}
+
+static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net_device *dev;
+       struct net_device *br_dev = NULL;
+       const struct net_device_ops *ops = NULL;
+       const struct net_device_ops *cops = NULL;
+       struct net *net = sock_net(skb->sk);
+       struct hlist_head *head;
+       int brport_idx = 0;
+       int br_idx = 0;
+       int h, s_h;
+       int idx = 0, s_idx;
+       int err = 0;
+       int fidx = 0;
+
+       err = valid_fdb_dump_legacy(cb->nlh, &br_idx, &brport_idx,
+                                   cb->extack);
+       if (err < 0)
+               return err;
 
        if (br_idx) {
                br_dev = __dev_get_by_index(net, br_idx);