Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8dfbda19 authored by David Ahern's avatar David Ahern Committed by David S. Miller
Browse files

rtnetlink: Move input checking for rtnl_fdb_dump to helper



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: default avatarDavid Ahern <dsahern@gmail.com>
Acked-by: default avatarChristian Brauner <christian@brauner.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c77b9364
Loading
Loading
Loading
Loading
+33 −20
Original line number Diff line number Diff line
@@ -3799,22 +3799,13 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb,
}
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,21 +3814,43 @@ 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);
		if (!br_dev)