batman-adv: Merge bugfixes from 2022.0 782/head
authorSven Eckelmann <sven@narfation.org>
Thu, 3 Feb 2022 19:12:06 +0000 (20:12 +0100)
committerSven Eckelmann <sven@narfation.org>
Thu, 3 Feb 2022 19:17:50 +0000 (20:17 +0100)
* allow netlink usage in unprivileged containers
* mcast: don't send link-local multicast to mcast routers

Signed-off-by: Sven Eckelmann <sven@narfation.org>
batman-adv/patches/0007-batman-adv-allow-netlink-usage-in-unprivileged-conta.patch [new file with mode: 0644]
batman-adv/patches/0008-batman-adv-mcast-don-t-send-link-local-multicast-to-.patch [new file with mode: 0644]

diff --git a/batman-adv/patches/0007-batman-adv-allow-netlink-usage-in-unprivileged-conta.patch b/batman-adv/patches/0007-batman-adv-allow-netlink-usage-in-unprivileged-conta.patch
new file mode 100644 (file)
index 0000000..83ebf5e
--- /dev/null
@@ -0,0 +1,182 @@
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+Date: Mon, 1 Nov 2021 21:46:17 +0100
+Subject: batman-adv: allow netlink usage in unprivileged containers
+
+Currently, creating a batman-adv interface in an unprivileged LXD
+container and attaching secondary interfaces to it with "ip" or "batctl"
+works fine. However all batctl debug and configuration commands
+fail:
+
+  root@container:~# batctl originators
+  Error received: Operation not permitted
+  root@container:~# batctl orig_interval
+  1000
+  root@container:~# batctl orig_interval 2000
+  root@container:~# batctl orig_interval
+  1000
+
+To fix this change the generic netlink permissions from GENL_ADMIN_PERM
+to GENL_UNS_ADMIN_PERM. This way a batman-adv interface is fully
+maintainable as root from within a user namespace, from an unprivileged
+container.
+
+All except one batman-adv netlink setting are per interface and do not
+leak information or change settings from the host system and are
+therefore save to retrieve or modify as root from within an unprivileged
+container.
+
+"batctl routing_algo" / BATADV_CMD_GET_ROUTING_ALGOS is the only
+exception: It provides the batman-adv kernel module wide default routing
+algorithm. However it is read-only from netlink and an unprivileged
+container is still not allowed to modify
+/sys/module/batman_adv/parameters/routing_algo. Instead it is advised to
+use the newly introduced "batctl if create routing_algo RA_NAME" /
+IFLA_BATADV_ALGO_NAME to set the routing algorithm on interface
+creation, which already works fine in an unprivileged container.
+
+Cc: Tycho Andersen <tycho@tycho.pizza>
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/055fa41b73ca8dae1c1ed41777e32a8f02e80c82
+
+--- /dev/null
++++ b/compat-include/uapi/linux/genetlink.h
+@@ -0,0 +1,22 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (C) B.A.T.M.A.N. contributors:
++ *
++ * Marek Lindner, Simon Wunderlich
++ *
++ * This file contains macros for maintaining compatibility with older versions
++ * of the Linux kernel.
++ */
++
++#ifndef _NET_BATMAN_ADV_COMPAT_UAPI_LINUX_GENETLINK_H_
++#define _NET_BATMAN_ADV_COMPAT_UAPI_LINUX_GENETLINK_H_
++
++#include <linux/version.h>
++#include_next <uapi/linux/genetlink.h>
++
++#if LINUX_VERSION_IS_LESS(4, 6, 0)
++
++#define GENL_UNS_ADMIN_PERM GENL_ADMIN_PERM
++
++#endif /* LINUX_VERSION_IS_LESS(4, 6, 0) */
++
++#endif /* _NET_BATMAN_ADV_COMPAT_UAPI_LINUX_GENETLINK_H_ */
+--- a/net/batman-adv/netlink.c
++++ b/net/batman-adv/netlink.c
+@@ -1369,21 +1369,21 @@ static const struct genl_ops batadv_netl
+       {
+               .cmd = BATADV_CMD_TP_METER,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .doit = batadv_netlink_tp_meter_start,
+               .internal_flags = BATADV_FLAG_NEED_MESH,
+       },
+       {
+               .cmd = BATADV_CMD_TP_METER_CANCEL,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .doit = batadv_netlink_tp_meter_cancel,
+               .internal_flags = BATADV_FLAG_NEED_MESH,
+       },
+       {
+               .cmd = BATADV_CMD_GET_ROUTING_ALGOS,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_algo_dump,
+       },
+       {
+@@ -1398,68 +1398,68 @@ static const struct genl_ops batadv_netl
+       {
+               .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_tt_local_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_tt_global_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_ORIGINATORS,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_orig_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_NEIGHBORS,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_hardif_neigh_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_GATEWAYS,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_gw_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_BLA_CLAIM,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_bla_claim_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_BLA_BACKBONE,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_bla_backbone_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_DAT_CACHE,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_dat_cache_dump,
+       },
+       {
+               .cmd = BATADV_CMD_GET_MCAST_FLAGS,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .dumpit = batadv_mcast_flags_dump,
+       },
+       {
+               .cmd = BATADV_CMD_SET_MESH,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .doit = batadv_netlink_set_mesh,
+               .internal_flags = BATADV_FLAG_NEED_MESH,
+       },
+       {
+               .cmd = BATADV_CMD_SET_HARDIF,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .doit = batadv_netlink_set_hardif,
+               .internal_flags = BATADV_FLAG_NEED_MESH |
+                                 BATADV_FLAG_NEED_HARDIF,
+@@ -1475,7 +1475,7 @@ static const struct genl_ops batadv_netl
+       {
+               .cmd = BATADV_CMD_SET_VLAN,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+-              .flags = GENL_ADMIN_PERM,
++              .flags = GENL_UNS_ADMIN_PERM,
+               .doit = batadv_netlink_set_vlan,
+               .internal_flags = BATADV_FLAG_NEED_MESH |
+                                 BATADV_FLAG_NEED_VLAN,
diff --git a/batman-adv/patches/0008-batman-adv-mcast-don-t-send-link-local-multicast-to-.patch b/batman-adv/patches/0008-batman-adv-mcast-don-t-send-link-local-multicast-to-.patch
new file mode 100644 (file)
index 0000000..ef01214
--- /dev/null
@@ -0,0 +1,165 @@
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+Date: Sat, 1 Jan 2022 06:27:13 +0100
+Subject: batman-adv: mcast: don't send link-local multicast to mcast routers
+
+The addition of routable multicast TX handling introduced a
+bug/regression for packets with a link-local multicast destination:
+These packets would be sent to all batman-adv nodes with a multicast
+router and to all batman-adv nodes with an old version without multicast
+router detection.
+
+This even disregards the batman-adv multicast fanout setting, which can
+potentially lead to an unwanted, high number of unicast transmissions or
+even congestion.
+
+Fixing this by avoiding to send link-local multicast packets to nodes in
+the multicast router list.
+
+Fixes: 3a8df00cd969 ("batman-adv: mcast: apply optimizations for routable packets, too")
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/ee013870947b9175847aa46a0686ca01dd480af4
+
+--- a/net/batman-adv/multicast.c
++++ b/net/batman-adv/multicast.c
+@@ -1380,6 +1380,7 @@ batadv_mcast_forw_rtr_node_get(struct ba
+  * @bat_priv: the bat priv with all the soft interface information
+  * @skb: The multicast packet to check
+  * @orig: an originator to be set to forward the skb to
++ * @is_routable: stores whether the destination is routable
+  *
+  * Return: the forwarding mode as enum batadv_forw_mode and in case of
+  * BATADV_FORW_SINGLE set the orig to the single originator the skb
+@@ -1387,17 +1388,16 @@ batadv_mcast_forw_rtr_node_get(struct ba
+  */
+ enum batadv_forw_mode
+ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
+-                     struct batadv_orig_node **orig)
++                     struct batadv_orig_node **orig, int *is_routable)
+ {
+       int ret, tt_count, ip_count, unsnoop_count, total_count;
+       bool is_unsnoopable = false;
+       unsigned int mcast_fanout;
+       struct ethhdr *ethhdr;
+-      int is_routable = 0;
+       int rtr_count = 0;
+       ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable,
+-                                         &is_routable);
++                                         is_routable);
+       if (ret == -ENOMEM)
+               return BATADV_FORW_NONE;
+       else if (ret < 0)
+@@ -1410,7 +1410,7 @@ batadv_mcast_forw_mode(struct batadv_pri
+       ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
+       unsnoop_count = !is_unsnoopable ? 0 :
+                       atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
+-      rtr_count = batadv_mcast_forw_rtr_count(bat_priv, is_routable);
++      rtr_count = batadv_mcast_forw_rtr_count(bat_priv, *is_routable);
+       total_count = tt_count + ip_count + unsnoop_count + rtr_count;
+@@ -1730,6 +1730,7 @@ batadv_mcast_forw_want_rtr(struct batadv
+  * @bat_priv: the bat priv with all the soft interface information
+  * @skb: the multicast packet to transmit
+  * @vid: the vlan identifier
++ * @is_routable: stores whether the destination is routable
+  *
+  * Sends copies of a frame with multicast destination to any node that signaled
+  * interest in it, that is either via the translation table or the according
+@@ -1742,7 +1743,7 @@ batadv_mcast_forw_want_rtr(struct batadv
+  * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise.
+  */
+ int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
+-                         unsigned short vid)
++                         unsigned short vid, int is_routable)
+ {
+       int ret;
+@@ -1758,12 +1759,16 @@ int batadv_mcast_forw_send(struct batadv
+               return ret;
+       }
++      if (!is_routable)
++              goto skip_mc_router;
++
+       ret = batadv_mcast_forw_want_rtr(bat_priv, skb, vid);
+       if (ret != NET_XMIT_SUCCESS) {
+               kfree_skb(skb);
+               return ret;
+       }
++skip_mc_router:
+       consume_skb(skb);
+       return ret;
+ }
+--- a/net/batman-adv/multicast.h
++++ b/net/batman-adv/multicast.h
+@@ -43,7 +43,8 @@ enum batadv_forw_mode {
+ enum batadv_forw_mode
+ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
+-                     struct batadv_orig_node **mcast_single_orig);
++                     struct batadv_orig_node **mcast_single_orig,
++                     int *is_routable);
+ int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
+                               struct sk_buff *skb,
+@@ -51,7 +52,7 @@ int batadv_mcast_forw_send_orig(struct b
+                               struct batadv_orig_node *orig_node);
+ int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
+-                         unsigned short vid);
++                         unsigned short vid, int is_routable);
+ void batadv_mcast_init(struct batadv_priv *bat_priv);
+@@ -68,7 +69,8 @@ void batadv_mcast_purge_orig(struct bata
+ static inline enum batadv_forw_mode
+ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
+-                     struct batadv_orig_node **mcast_single_orig)
++                     struct batadv_orig_node **mcast_single_orig,
++                     int *is_routable)
+ {
+       return BATADV_FORW_ALL;
+ }
+@@ -85,7 +87,7 @@ batadv_mcast_forw_send_orig(struct batad
+ static inline int
+ batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
+-                     unsigned short vid)
++                     unsigned short vid, int is_routable)
+ {
+       kfree_skb(skb);
+       return NET_XMIT_DROP;
+--- a/net/batman-adv/soft-interface.c
++++ b/net/batman-adv/soft-interface.c
+@@ -198,6 +198,7 @@ static netdev_tx_t batadv_interface_tx(s
+       int gw_mode;
+       enum batadv_forw_mode forw_mode = BATADV_FORW_SINGLE;
+       struct batadv_orig_node *mcast_single_orig = NULL;
++      int mcast_is_routable = 0;
+       int network_offset = ETH_HLEN;
+       __be16 proto;
+@@ -300,7 +301,8 @@ static netdev_tx_t batadv_interface_tx(s
+ send:
+               if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) {
+                       forw_mode = batadv_mcast_forw_mode(bat_priv, skb,
+-                                                         &mcast_single_orig);
++                                                         &mcast_single_orig,
++                                                         &mcast_is_routable);
+                       if (forw_mode == BATADV_FORW_NONE)
+                               goto dropped;
+@@ -365,7 +367,8 @@ send:
+                       ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid,
+                                                         mcast_single_orig);
+               } else if (forw_mode == BATADV_FORW_SOME) {
+-                      ret = batadv_mcast_forw_send(bat_priv, skb, vid);
++                      ret = batadv_mcast_forw_send(bat_priv, skb, vid,
++                                                   mcast_is_routable);
+               } else {
+                       if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
+                                                                 skb))