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

Commit b1215198 authored by Alvin Šipraga's avatar Alvin Šipraga Committed by Greg Kroah-Hartman
Browse files

macvlan: validate setting of multiple remote source MAC addresses



[ Upstream commit 8b61fba503904acae24aeb2bd5569b4d6544d48f ]

Remote source MAC addresses can be set on a 'source mode' macvlan
interface via the IFLA_MACVLAN_MACADDR_DATA attribute. This commit
tightens the validation of these MAC addresses to match the validation
already performed when setting or adding a single MAC address via the
IFLA_MACVLAN_MACADDR attribute.

iproute2 uses IFLA_MACVLAN_MACADDR_DATA for its 'macvlan macaddr set'
command, and IFLA_MACVLAN_MACADDR for its 'macvlan macaddr add' command,
which demonstrates the inconsistent behaviour that this commit
addresses:

 # ip link add link eth0 name macvlan0 type macvlan mode source
 # ip link set link dev macvlan0 type macvlan macaddr add 01:00:00:00:00:00
 RTNETLINK answers: Cannot assign requested address
 # ip link set link dev macvlan0 type macvlan macaddr set 01:00:00:00:00:00
 # ip -d link show macvlan0
 5: macvlan0@eth0: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 ...
     link/ether 2e:ac:fd:2d:69:f8 brd ff:ff:ff:ff:ff:ff promiscuity 0
     macvlan mode source remotes (1) 01:00:00:00:00:00 numtxqueues 1 ...

With this change, the 'set' command will (rightly) fail in the same way
as the 'add' command.

Signed-off-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 2d1a5f56
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -1230,6 +1230,9 @@ static void macvlan_port_destroy(struct net_device *dev)
static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
			    struct netlink_ext_ack *extack)
{
	struct nlattr *nla, *head;
	int rem, len;

	if (tb[IFLA_ADDRESS]) {
		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
			return -EINVAL;
@@ -1277,6 +1280,20 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
			return -EADDRNOTAVAIL;
	}

	if (data[IFLA_MACVLAN_MACADDR_DATA]) {
		head = nla_data(data[IFLA_MACVLAN_MACADDR_DATA]);
		len = nla_len(data[IFLA_MACVLAN_MACADDR_DATA]);

		nla_for_each_attr(nla, head, len, rem) {
			if (nla_type(nla) != IFLA_MACVLAN_MACADDR ||
			    nla_len(nla) != ETH_ALEN)
				return -EINVAL;

			if (!is_valid_ether_addr(nla_data(nla)))
				return -EADDRNOTAVAIL;
		}
	}

	if (data[IFLA_MACVLAN_MACADDR_COUNT])
		return -EINVAL;

@@ -1333,10 +1350,6 @@ static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode,
		len = nla_len(data[IFLA_MACVLAN_MACADDR_DATA]);

		nla_for_each_attr(nla, head, len, rem) {
			if (nla_type(nla) != IFLA_MACVLAN_MACADDR ||
			    nla_len(nla) != ETH_ALEN)
				continue;

			addr = nla_data(nla);
			ret = macvlan_hash_add_source(vlan, addr);
			if (ret)