In a lot of places, we use this kind of comparison to detect if a
device has a lower link:
dev->ifindex != dev_get_iflink(dev)
This seems to be a leftover of the pre-netns days, when the ifindex
was unique over the whole system. Nowadays, with network namespaces,
it's very easy to create a device with the same ifindex as its lower
link:
ip netns add main
ip netns add peer
ip -net main link add dummy0 type dummy
ip -net main link add link dummy0 macvlan0 netns peer type macvlan
ip -net main link show type dummy
9: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop ...
ip -net peer link show type macvlan
9: macvlan0@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop ...
To detect if a device has a lower link, we can simply check the
existence of the dev->netdev_ops->ndo_get_iflink operation, instead of
checking its return value. In particular, I attempted to fix one of
these checks in commit feadc4b6cf42 ("rtnetlink: always put IFLA_LINK
for links with a link-netnsid"), but this patch isn't correct, since
tunnel devices can export IFLA_LINK_NETNSID without IFLA_LINK. That
patch needs to be reverted.
This series will fix all those bogus comparisons, and export missing
IFLA_LINK_NETNSID attributes in bridge and ipv6 dumps.
ipvlan and geneve are also missing the get_link_net operation, so
userspace can't know when those device are cross-netns. There are a
couple of other device types that have an ndo_get_iflink op but no
get_link_net (virt_wifi, ipoib), and should probably also have a
get_link_net.
Sabrina Dubroca (12):
ipvlan: add get_link_net
geneve: add get_link_net
Revert "rtnetlink: always put IFLA_LINK for links with a link-netnsid"
rtnetlink: always put IFLA_LINK for links with ndo_get_iflink
bridge: always put IFLA_LINK for ports with ndo_get_iflink
bridge: advertise IFLA_LINK_NETNSID when dumping bridge ports
ipv6: always put IFLA_LINK for devices with ndo_get_iflink
ipv6: advertise IFLA_LINK_NETNSID when dumping ipv6 addresses
net: link_watch: fix operstate when the link has the same index as the
device
net: link_watch: fix detection of urgent events
batman-adv: fix iflink detection in batadv_is_on_batman_iface
batman-adv: fix detection of lower link in batadv_get_real_netdevice
drivers/net/can/vxcan.c | 2 +-
drivers/net/geneve.c | 8 ++++++++
drivers/net/ipvlan/ipvlan_main.c | 9 +++++++++
drivers/net/veth.c | 2 +-
include/net/rtnetlink.h | 4 ++++
net/batman-adv/hard-interface.c | 4 ++--
net/bridge/br_netlink.c | 4 +++-
net/core/link_watch.c | 4 ++--
net/core/rtnetlink.c | 25 ++++++++++++-------------
net/ipv6/addrconf.c | 11 ++++++++++-
10 files changed, 52 insertions(+), 21 deletions(-)
--
2.28.0
On Monday, 28 February 2022 01:24:30 CET Leonardo Mörlein wrote:
> > This happens because macvtap doesn't provide
> >
>
> I think there are some missing words.
Correct.
"This happens because macvtap doesn't provide an implementation for
rtnl_link_ops->get_link_net" [1]
Kind regards,
Sven
[1] https://git.open-mesh.org/linux-merge.git/commit/7748449945e3fb63b64d57c5c0…
There is no need to call dev_get_iflink multiple times for the same
net_device in batadv_is_on_batman_iface. And since some of the
.ndo_get_iflink callbacks are dynamic (for example via RCUs like in
vxcan_get_iflink), it could easily happen that the returned values are not
stable. The pre-checks before __dev_get_by_index are then of course bogus.
Fixes: 3d48811b27f5 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface")
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
net/batman-adv/hard-interface.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 59d19097..774a26c5 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -149,22 +149,23 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
struct net *net = dev_net(net_dev);
struct net_device *parent_dev;
struct net *parent_net;
+ int iflink;
bool ret;
/* check if this is a batman-adv mesh interface */
if (batadv_softif_is_valid(net_dev))
return true;
+ iflink = dev_get_iflink(net_dev);
+
/* no more parents..stop recursion */
- if (dev_get_iflink(net_dev) == 0 ||
- dev_get_iflink(net_dev) == net_dev->ifindex)
+ if (iflink == 0 || iflink == net_dev->ifindex)
return false;
parent_net = batadv_getlink_net(net_dev, net);
/* recurse over the parent device */
- parent_dev = __dev_get_by_index((struct net *)parent_net,
- dev_get_iflink(net_dev));
+ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink);
/* if we got a NULL parent_dev there is something broken.. */
if (!parent_dev) {
pr_err("Cannot find parent device\n");
--
2.30.2
A client sending a alfred_change_interface_v0 packet to the alfred server
might have forgotten to 0-terminate the string. In this case, strstr in
unix_sock_change_iface might read outside of the available buffer.
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
unix_sock.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/unix_sock.c b/unix_sock.c
index bc39199..8c2b762 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -329,6 +329,8 @@ unix_sock_change_iface(struct globals *globals,
if (len < (int)(sizeof(*change_iface) - sizeof(change_iface->header)))
goto err;
+ change_iface->ifaces[sizeof(change_iface->ifaces) - 1] = '\0';
+
if (globals->opmode == OPMODE_SECONDARY) {
if (strstr(change_iface->ifaces, ",") != NULL) {
ret = -EINVAL;
--
2.30.2