From: Simon Wunderlich Date: Tue, 27 Oct 2020 16:07:28 +0000 (+0100) Subject: Merge pull request #624 from ecsv/batadv-for-18.06 X-Git-Url: http://git.openwrt.org/?p=feed%2Frouting.git;a=commitdiff_plain;h=refs%2Fheads%2Fopenwrt-18.06;hp=cad1fba86fa5fa787332d27e371a461afec0ad32 Merge pull request #624 from ecsv/batadv-for-18.06 batman-adv: Fix missing include for backported 2020.4 patch --- diff --git a/babeld/Makefile b/babeld/Makefile index 5cf136d..972862c 100644 --- a/babeld/Makefile +++ b/babeld/Makefile @@ -8,13 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=babeld -PKG_VERSION:=1.8.2 +PKG_VERSION:=1.8.5 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://www.irif.fr/~jch/software/files/ -PKG_MD5SUM:=eec395ade02524b3f351507a21742939 -PKG_HASH:=07edecb132386d5561a767482bc5200e04239b18e48c2f0f47ae1c78d60fe5dc +PKG_HASH:=202d99c275604507c6ce133710522f1ddfb62cb671c26f1ac2d3ab44af3d5bc4 PKG_LICENSE:=MIT include $(INCLUDE_DIR)/package.mk diff --git a/batctl/Makefile b/batctl/Makefile index 4e67512..ba83914 100644 --- a/batctl/Makefile +++ b/batctl/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=batctl PKG_VERSION:=2018.1 -PKG_RELEASE:=1 +PKG_RELEASE:=4 PKG_HASH:=27877d0da6916f88a6cecbbb3f3d23cc4558ef7c7294324bf4fd050ed606b553 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz diff --git a/batctl/patches/0001-batctl-Return-EXIT_FAILURE-when-throughputmeter-fail.patch b/batctl/patches/0001-batctl-Return-EXIT_FAILURE-when-throughputmeter-fail.patch new file mode 100644 index 0000000..87858f9 --- /dev/null +++ b/batctl/patches/0001-batctl-Return-EXIT_FAILURE-when-throughputmeter-fail.patch @@ -0,0 +1,37 @@ +From: Leonardo Mörlein +Date: Wed, 8 Apr 2020 23:49:03 +0200 +Subject: batctl: Return EXIT_FAILURE when throughputmeter failed + +The command returned a success even an error was shown during the +execution. + + $ (sudo batctl tp 77:77:77:77:77:77 && echo true) || echo false + Destination unreachable + true + +Instead it should indicate a failure when the kernel replied with a +non-success return_value: + + $ (sudo ./batctl tp 77:77:77:77:77:77 && echo true) || echo false + Destination unreachable + false + +Fixes: f109b3473f86 ("batctl: introduce throughput meter support") +Signed-off-by: Leonardo Mörlein +[sven@narfation.org: adjusted commit message] +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batctl.git/commit/df8bf5164b6904f61ae0b0db090fb5bb41b4f06d + +diff --git a/tp_meter.c b/tp_meter.c +index c7904857865c5b2a51cf30e7963394dd9b6c029c..403c88452b4ad56f4049f64829c6d2bdd015810a 100644 +--- a/tp_meter.c ++++ b/tp_meter.c +@@ -480,6 +480,7 @@ int tp_meter(char *mesh_iface, int argc, char **argv) + goto out; + } + ++ ret = EXIT_FAILURE; + switch (result.return_value) { + case BATADV_TP_REASON_DST_UNREACHABLE: + fprintf(stderr, "Destination unreachable\n"); diff --git a/batctl/patches/0002-batctl-fix-endianness-when-reading-radiotap-header.patch b/batctl/patches/0002-batctl-fix-endianness-when-reading-radiotap-header.patch new file mode 100644 index 0000000..2816149 --- /dev/null +++ b/batctl/patches/0002-batctl-fix-endianness-when-reading-radiotap-header.patch @@ -0,0 +1,38 @@ +From: Marek Lindner +Date: Wed, 29 Apr 2020 12:09:44 +0200 +Subject: batctl: fix endianness when reading radiotap header + +All radiotap header fields are specified in little endian byte-order. +Header length conversion is necessary on some platforms. + +Fixes: c6fcdb6dc9a9 ("batctl: add radiotap wifi packet decapsulation support") +Signed-off-by: Marek Lindner +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batctl.git/commit/440ae55a6ef96eb73ee628f9237915cf9fb26dee + +diff --git a/tcpdump.c b/tcpdump.c +index dc4ccd37c3ddf8650cb79737defd923fe9f33c64..c41500e21eda0abc1f024a3265c23fc3a4802d17 100644 +--- a/tcpdump.c ++++ b/tcpdump.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1048,10 +1049,10 @@ static int monitor_header_length(unsigned char *packet_buff, ssize_t buff_len, i + return -1; + + radiotap_hdr = (struct radiotap_header*)packet_buff; +- if (buff_len <= radiotap_hdr->it_len) ++ if (buff_len <= le16toh(radiotap_hdr->it_len)) + return -1; + else +- return radiotap_hdr->it_len; ++ return le16toh(radiotap_hdr->it_len); + } + + return -1; diff --git a/batctl/patches/0003-batctl-Only-remove-batadv-interface-on-hardif-reduct.patch b/batctl/patches/0003-batctl-Only-remove-batadv-interface-on-hardif-reduct.patch new file mode 100644 index 0000000..01cf039 --- /dev/null +++ b/batctl/patches/0003-batctl-Only-remove-batadv-interface-on-hardif-reduct.patch @@ -0,0 +1,49 @@ +From: Sven Eckelmann +Date: Sat, 13 Jun 2020 17:59:34 +0200 +Subject: batctl: Only remove batadv interface on hardif reduction + +A deletion of a hardif from a batadv meshif will also get a success reply +from the kernel when the hardif was never part of the batadv meshif. If the +batadv meshif had no attached hardifs before the removal was started, then +users are then not expecting that the batadv meshif is removed at all. + +Since the delete operation is not an atomic compare-and-swap operation, +just check first the number of attached interfaces and only start the +removal of the batadv meshif when the number attached hardifs was reduced. + +Fixes: 25022e0b154d ("batctl: Use rtnl to add/remove interfaces") +Reported-by: Matthias Schiffer +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batctl.git/commit/6d49a82cf58ee5ebd6235b6ddaca46febd42f876 + +diff --git a/interface.c b/interface.c +index 5951b471c6477e78ff557e97a7478ba774a0aa20..1ad36826fdb91a3e0254ed4dec758e7c383596e9 100644 +--- a/interface.c ++++ b/interface.c +@@ -305,6 +305,7 @@ int interface(char *mesh_iface, int argc, char **argv) + int ret; + unsigned int ifindex; + unsigned int ifmaster; ++ unsigned int pre_cnt; + const char *long_op; + unsigned int cnt; + int rest_argc; +@@ -421,6 +422,8 @@ int interface(char *mesh_iface, int argc, char **argv) + goto err; + } + ++ pre_cnt = count_interfaces(mesh_iface); ++ + for (i = 1; i < rest_argc; i++) { + ifindex = if_nametoindex(rest_argv[i]); + +@@ -450,7 +453,7 @@ int interface(char *mesh_iface, int argc, char **argv) + /* check if there is no interface left and then destroy mesh_iface */ + if (!manual_mode && rest_argv[0][0] == 'd') { + cnt = count_interfaces(mesh_iface); +- if (cnt == 0) ++ if (cnt == 0 && pre_cnt > 0) + destroy_interface(mesh_iface); + } + diff --git a/batctl/patches/0004-batctl-tcpdump-Fix-endianness-in-ICMPv6-Echo-Request.patch b/batctl/patches/0004-batctl-tcpdump-Fix-endianness-in-ICMPv6-Echo-Request.patch new file mode 100644 index 0000000..b7250af --- /dev/null +++ b/batctl/patches/0004-batctl-tcpdump-Fix-endianness-in-ICMPv6-Echo-Request.patch @@ -0,0 +1,39 @@ +From: Linus Lüssing +Date: Sun, 13 Sep 2020 23:30:19 +0200 +Subject: batctl: tcpdump: Fix endianness in ICMPv6 Echo Request/Reply parsing + +The ICMPv6 Echo Request/Reply sequence number and id as well as the +IPv6 header length are two byte long fields and therefore might need a +conversion on a little endian system. Otherwise the output will be +broken on such a machine. + +Fixes: 35b37756f4a3 ("add IPv6 support to tcpdump parser") +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batctl.git/commit/e42f73d0d2a04edfbed1b9d0ad9fd57af9e90faf + +diff --git a/tcpdump.c b/tcpdump.c +index c41500e21eda0abc1f024a3265c23fc3a4802d17..22847aecf887566ac62ff2084079683d0acf83aa 100644 +--- a/tcpdump.c ++++ b/tcpdump.c +@@ -551,13 +551,15 @@ static void dump_ipv6(unsigned char *packet_buff, ssize_t buff_len, + break; + case ICMP6_ECHO_REQUEST: + printf(" echo request, id: %d, seq: %d, length: %hu\n", +- icmphdr->icmp6_id, icmphdr->icmp6_seq, +- iphdr->ip6_plen); ++ ntohs(icmphdr->icmp6_id), ++ ntohs(icmphdr->icmp6_seq), ++ ntohs(iphdr->ip6_plen)); + break; + case ICMP6_ECHO_REPLY: + printf(" echo reply, id: %d, seq: %d, length: %hu\n", +- icmphdr->icmp6_id, icmphdr->icmp6_seq, +- iphdr->ip6_plen); ++ ntohs(icmphdr->icmp6_id), ++ ntohs(icmphdr->icmp6_seq), ++ ntohs(iphdr->ip6_plen)); + break; + case ICMP6_TIME_EXCEEDED: + printf(" time exceeded in-transit, length %zu\n", diff --git a/batman-adv/Makefile b/batman-adv/Makefile index f987b98..9df29a7 100644 --- a/batman-adv/Makefile +++ b/batman-adv/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=batman-adv PKG_VERSION:=2018.1 -PKG_RELEASE:=7 +PKG_RELEASE:=13 PKG_HASH:=b866b28dbbe5c9238abbdf5abbc30fc526dea56898ce4c1bd76d5c017843048b PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz diff --git a/batman-adv/patches/0032-batman-adv-Fix-duplicated-OGMs-on-NETDEV_UP.patch b/batman-adv/patches/0032-batman-adv-Fix-duplicated-OGMs-on-NETDEV_UP.patch new file mode 100644 index 0000000..e8902cd --- /dev/null +++ b/batman-adv/patches/0032-batman-adv-Fix-duplicated-OGMs-on-NETDEV_UP.patch @@ -0,0 +1,77 @@ +From: Sven Eckelmann +Date: Sun, 2 Jun 2019 10:57:31 +0200 +Subject: batman-adv: Fix duplicated OGMs on NETDEV_UP + +The state of slave interfaces are handled differently depending on whether +the interface is up or not. All active interfaces (IFF_UP) will transmit +OGMs. But for B.A.T.M.A.N. IV, also non-active interfaces are scheduling +(low TTL) OGMs on active interfaces. The code which setups and schedules +the OGMs must therefore already be called when the interfaces gets added as +slave interface and the transmit function must then check whether it has to +send out the OGM or not on the specific slave interface. + +But the commit 0d8468553c3c ("batman-adv: remove ogm_emit and ogm_schedule +API calls") moved the setup code from the enable function to the activate +function. The latter is called either when the added slave was already up +when batadv_hardif_enable_interface processed the new interface or when a +NETDEV_UP event was received for this slave interfac. As result, each +NETDEV_UP would schedule a new OGM worker for the interface and thus OGMs +would be send a lot more than expected. + +Fixes: 0d8468553c3c ("batman-adv: remove ogm_emit and ogm_schedule API calls") +Reported-by: Linus Lüssing +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/c92331e0df3c0c5645ee5a897eb018c5da5e4aa5 + +diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c +index 73bf6a93a3cf1141a34657bf1284893199e04db9..0b7b36fa0d5cd440ddef141ad27acfe7b20aee43 100644 +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -2485,7 +2485,7 @@ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1, + return ret; + } + +-static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface) ++static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface) + { + /* begin scheduling originator messages on that interface */ + batadv_iv_ogm_schedule(hard_iface); +@@ -2825,8 +2825,8 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb, + static struct batadv_algo_ops batadv_batman_iv __read_mostly = { + .name = "BATMAN_IV", + .iface = { +- .activate = batadv_iv_iface_activate, + .enable = batadv_iv_ogm_iface_enable, ++ .enabled = batadv_iv_iface_enabled, + .disable = batadv_iv_ogm_iface_disable, + .update_mac = batadv_iv_ogm_iface_update_mac, + .primary_set = batadv_iv_ogm_primary_iface_set, +diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c +index 08690d06b7be2b25ca3f009394763c7083c70644..36f0962040d16af4f9ed82629ff03ce85c83ed57 100644 +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -821,6 +821,9 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, + + batadv_hardif_recalc_extra_skbroom(soft_iface); + ++ if (bat_priv->algo_ops->iface.enabled) ++ bat_priv->algo_ops->iface.enabled(hard_iface); ++ + out: + return 0; + +diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h +index 6d07898d8d1a21007b3e68d5d2511b478110f659..86f37db7dd01592aff95ada5ba5441667971e1bc 100644 +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -2126,6 +2126,9 @@ struct batadv_algo_iface_ops { + /** @enable: init routing info when hard-interface is enabled */ + int (*enable)(struct batadv_hard_iface *hard_iface); + ++ /** @enabled: notification when hard-interface was enabled (optional) */ ++ void (*enabled)(struct batadv_hard_iface *hard_iface); ++ + /** @disable: de-init routing info when hard-interface is disabled */ + void (*disable)(struct batadv_hard_iface *hard_iface); + diff --git a/batman-adv/patches/0033-batman-adv-fix-uninit-value-in-batadv_netlink_get_if.patch b/batman-adv/patches/0033-batman-adv-fix-uninit-value-in-batadv_netlink_get_if.patch new file mode 100644 index 0000000..3b49860 --- /dev/null +++ b/batman-adv/patches/0033-batman-adv-fix-uninit-value-in-batadv_netlink_get_if.patch @@ -0,0 +1,58 @@ +From: Eric Dumazet +Date: Mon, 12 Aug 2019 04:57:27 -0700 +Subject: batman-adv: fix uninit-value in batadv_netlink_get_ifindex() + +batadv_netlink_get_ifindex() needs to make sure user passed +a correct u32 attribute. + +syzbot reported : +BUG: KMSAN: uninit-value in batadv_netlink_dump_hardif+0x70d/0x880 net/batman-adv/netlink.c:968 +CPU: 1 PID: 11705 Comm: syz-executor888 Not tainted 5.1.0+ #1 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x191/0x1f0 lib/dump_stack.c:113 + kmsan_report+0x130/0x2a0 mm/kmsan/kmsan.c:622 + __msan_warning+0x75/0xe0 mm/kmsan/kmsan_instr.c:310 + batadv_netlink_dump_hardif+0x70d/0x880 net/batman-adv/netlink.c:968 + genl_lock_dumpit+0xc6/0x130 net/netlink/genetlink.c:482 + netlink_dump+0xa84/0x1ab0 net/netlink/af_netlink.c:2253 + __netlink_dump_start+0xa3a/0xb30 net/netlink/af_netlink.c:2361 + genl_family_rcv_msg net/netlink/genetlink.c:550 [inline] + genl_rcv_msg+0xfc1/0x1a40 net/netlink/genetlink.c:627 + netlink_rcv_skb+0x431/0x620 net/netlink/af_netlink.c:2486 + genl_rcv+0x63/0x80 net/netlink/genetlink.c:638 + netlink_unicast_kernel net/netlink/af_netlink.c:1311 [inline] + netlink_unicast+0xf3e/0x1020 net/netlink/af_netlink.c:1337 + netlink_sendmsg+0x127e/0x12f0 net/netlink/af_netlink.c:1926 + sock_sendmsg_nosec net/socket.c:651 [inline] + sock_sendmsg net/socket.c:661 [inline] + ___sys_sendmsg+0xcc6/0x1200 net/socket.c:2260 + __sys_sendmsg net/socket.c:2298 [inline] + __do_sys_sendmsg net/socket.c:2307 [inline] + __se_sys_sendmsg+0x305/0x460 net/socket.c:2305 + __x64_sys_sendmsg+0x4a/0x70 net/socket.c:2305 + do_syscall_64+0xbc/0xf0 arch/x86/entry/common.c:291 + entry_SYSCALL_64_after_hwframe+0x63/0xe7 +RIP: 0033:0x440209 + +Fixes: 55d368c3a57e ("batman-adv: netlink: hardif query") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/9b470b8a2b9ef4ce68d6e95febd3a0574be1ac14 + +diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c +index 0d9459b69bdb812b1b68e28e6b68fec8ec95df2d..c32820963b8e706b4cdde10d46ec582bc51ec4eb 100644 +--- a/net/batman-adv/netlink.c ++++ b/net/batman-adv/netlink.c +@@ -118,7 +118,7 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) + { + struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype); + +- return attr ? nla_get_u32(attr) : 0; ++ return (attr && nla_len(attr) == sizeof(u32)) ? nla_get_u32(attr) : 0; + } + + /** diff --git a/batman-adv/patches/0034-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch b/batman-adv/patches/0034-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch new file mode 100644 index 0000000..a6fc524 --- /dev/null +++ b/batman-adv/patches/0034-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch @@ -0,0 +1,74 @@ +From: Sven Eckelmann +Date: Fri, 23 Aug 2019 14:34:27 +0200 +Subject: batman-adv: Only read OGM tvlv_len after buffer len check + +Multiple batadv_ogm_packet can be stored in an skbuff. The functions +batadv_iv_ogm_send_to_if()/batadv_iv_ogm_receive() use +batadv_iv_ogm_aggr_packet() to check if there is another additional +batadv_ogm_packet in the skb or not before they continue processing the +packet. + +The length for such an OGM is BATADV_OGM_HLEN + +batadv_ogm_packet->tvlv_len. The check must first check that at least +BATADV_OGM_HLEN bytes are available before it accesses tvlv_len (which is +part of the header. Otherwise it might try read outside of the currently +available skbuff to get the content of tvlv_len. + +Fixes: 0b6aa0d43767 ("batman-adv: tvlv - basic infrastructure") +Reported-by: syzbot+355cab184197dbbfa384@syzkaller.appspotmail.com +Signed-off-by: Sven Eckelmann +Acked-by: Antonio Quartulli + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/07b6051ebcfaa7ea89b4f278eca2ff4070d29e56 + +diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c +index 0b7b36fa0d5cd440ddef141ad27acfe7b20aee43..36f244125d24c800d35249af7639d39a516588d4 100644 +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -463,17 +463,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv) + * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached + * @buff_pos: current position in the skb + * @packet_len: total length of the skb +- * @tvlv_len: tvlv length of the previously considered OGM ++ * @ogm_packet: potential OGM in buffer + * + * Return: true if there is enough space for another OGM, false otherwise. + */ +-static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, +- __be16 tvlv_len) ++static bool ++batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, ++ const struct batadv_ogm_packet *ogm_packet) + { + int next_buff_pos = 0; + +- next_buff_pos += buff_pos + BATADV_OGM_HLEN; +- next_buff_pos += ntohs(tvlv_len); ++ /* check if there is enough space for the header */ ++ next_buff_pos += buff_pos + sizeof(*ogm_packet); ++ if (next_buff_pos > packet_len) ++ return false; ++ ++ /* check if there is enough space for the optional TVLV */ ++ next_buff_pos += ntohs(ogm_packet->tvlv_len); + + return (next_buff_pos <= packet_len) && + (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); +@@ -501,7 +507,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, + + /* adjust all flags and log packets */ + while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, +- batadv_ogm_packet->tvlv_len)) { ++ batadv_ogm_packet)) { + /* we might have aggregated direct link packets with an + * ordinary base packet + */ +@@ -1852,7 +1858,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, + + /* unpack the aggregated packets and process them one by one */ + while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), +- ogm_packet->tvlv_len)) { ++ ogm_packet)) { + batadv_iv_ogm_process(skb, ogm_offset, if_incoming); + + ogm_offset += BATADV_OGM_HLEN; diff --git a/batman-adv/patches/0035-batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch b/batman-adv/patches/0035-batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch new file mode 100644 index 0000000..81c0fef --- /dev/null +++ b/batman-adv/patches/0035-batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch @@ -0,0 +1,62 @@ +From: Sven Eckelmann +Date: Fri, 23 Aug 2019 14:34:28 +0200 +Subject: batman-adv: Only read OGM2 tvlv_len after buffer len check + +Multiple batadv_ogm2_packet can be stored in an skbuff. The functions +batadv_v_ogm_send_to_if() uses batadv_v_ogm_aggr_packet() to check if there +is another additional batadv_ogm2_packet in the skb or not before they +continue processing the packet. + +The length for such an OGM2 is BATADV_OGM2_HLEN + +batadv_ogm2_packet->tvlv_len. The check must first check that at least +BATADV_OGM2_HLEN bytes are available before it accesses tvlv_len (which is +part of the header. Otherwise it might try read outside of the currently +available skbuff to get the content of tvlv_len. + +Fixes: 667996ebeab4 ("batman-adv: OGMv2 - implement originators logic") +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/18f77da3761c5550f42a2d131f0fe5cac62e022d + +diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c +index 2948b41b06d47c0ee32649fa410b323f39c36151..d241ccc0ca0278173853512c8aa4bfb8b041f996 100644 +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -643,17 +643,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv, + * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated + * @buff_pos: current position in the skb + * @packet_len: total length of the skb +- * @tvlv_len: tvlv length of the previously considered OGM ++ * @ogm2_packet: potential OGM2 in buffer + * + * Return: true if there is enough space for another OGM, false otherwise. + */ +-static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, +- __be16 tvlv_len) ++static bool ++batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, ++ const struct batadv_ogm2_packet *ogm2_packet) + { + int next_buff_pos = 0; + +- next_buff_pos += buff_pos + BATADV_OGM2_HLEN; +- next_buff_pos += ntohs(tvlv_len); ++ /* check if there is enough space for the header */ ++ next_buff_pos += buff_pos + sizeof(*ogm2_packet); ++ if (next_buff_pos > packet_len) ++ return false; ++ ++ /* check if there is enough space for the optional TVLV */ ++ next_buff_pos += ntohs(ogm2_packet->tvlv_len); + + return (next_buff_pos <= packet_len) && + (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); +@@ -830,7 +836,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb, + ogm_packet = (struct batadv_ogm2_packet *)skb->data; + + while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb), +- ogm_packet->tvlv_len)) { ++ ogm_packet)) { + batadv_v_ogm_process(skb, ogm_offset, if_incoming); + + ogm_offset += BATADV_OGM2_HLEN; diff --git a/batman-adv/patches/0036-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch b/batman-adv/patches/0036-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch new file mode 100644 index 0000000..b4afbf3 --- /dev/null +++ b/batman-adv/patches/0036-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch @@ -0,0 +1,119 @@ +From: Sven Eckelmann +Date: Thu, 3 Oct 2019 17:02:01 +0200 +Subject: batman-adv: Avoid free/alloc race when handling OGM2 buffer + +A B.A.T.M.A.N. V virtual interface has an OGM2 packet buffer which is +initialized using data from the RTNL lock protected netdevice notifier and +other rtnetlink related hooks. It is sent regularly via various slave +interfaces of the batadv virtual interface and in this process also +modified (realloced) to integrate additional state information via TVLV +containers. + +It must be avoided that the worker item is executed without a common lock +with the netdevice notifier/rtnetlink helpers. Otherwise it can either +happen that half modified data is sent out or the functions modifying the +OGM2 buffer try to access already freed memory regions. + +Fixes: 632835348e65 ("batman-adv: OGMv2 - add basic infrastructure") +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/14ee24576213ff02272b7f8d975c7c61d5448aa2 + +diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c +index d241ccc0ca0278173853512c8aa4bfb8b041f996..a9f949501ff3c354d38e3ad333901310391f27d8 100644 +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -128,14 +129,12 @@ static void batadv_v_ogm_send_to_if(struct sk_buff *skb, + } + + /** +- * batadv_v_ogm_send() - periodic worker broadcasting the own OGM +- * @work: work queue item ++ * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM ++ * @bat_priv: the bat priv with all the soft interface information + */ +-static void batadv_v_ogm_send(struct work_struct *work) ++static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv) + { + struct batadv_hard_iface *hard_iface; +- struct batadv_priv_bat_v *bat_v; +- struct batadv_priv *bat_priv; + struct batadv_ogm2_packet *ogm_packet; + struct sk_buff *skb, *skb_tmp; + unsigned char *ogm_buff; +@@ -143,8 +142,7 @@ static void batadv_v_ogm_send(struct work_struct *work) + u16 tvlv_len = 0; + int ret; + +- bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); +- bat_priv = container_of(bat_v, struct batadv_priv, bat_v); ++ ASSERT_RTNL(); + + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) + goto out; +@@ -235,6 +233,22 @@ static void batadv_v_ogm_send(struct work_struct *work) + return; + } + ++/** ++ * batadv_v_ogm_send() - periodic worker broadcasting the own OGM ++ * @work: work queue item ++ */ ++static void batadv_v_ogm_send(struct work_struct *work) ++{ ++ struct batadv_priv_bat_v *bat_v; ++ struct batadv_priv *bat_priv; ++ ++ rtnl_lock(); ++ bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); ++ bat_priv = container_of(bat_v, struct batadv_priv, bat_v); ++ batadv_v_ogm_send_softif(bat_priv); ++ rtnl_unlock(); ++} ++ + /** + * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V + * @hard_iface: the interface to prepare +@@ -261,6 +275,8 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface) + struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface); + struct batadv_ogm2_packet *ogm_packet; + ++ ASSERT_RTNL(); ++ + if (!bat_priv->bat_v.ogm_buff) + return; + +@@ -869,6 +885,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv) + unsigned char *ogm_buff; + u32 random_seqno; + ++ ASSERT_RTNL(); ++ + bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN; + ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC); + if (!ogm_buff) +diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h +index 86f37db7dd01592aff95ada5ba5441667971e1bc..3392198ff146ba77d320104663e97ab21559d556 100644 +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -1479,10 +1479,10 @@ struct batadv_softif_vlan { + * struct batadv_priv_bat_v - B.A.T.M.A.N. V per soft-interface private data + */ + struct batadv_priv_bat_v { +- /** @ogm_buff: buffer holding the OGM packet */ ++ /** @ogm_buff: buffer holding the OGM packet. rtnl protected */ + unsigned char *ogm_buff; + +- /** @ogm_buff_len: length of the OGM packet buffer */ ++ /** @ogm_buff_len: length of the OGM packet buffer. rtnl protected */ + int ogm_buff_len; + + /** @ogm_seqno: OGM sequence number - used to identify each OGM */ diff --git a/batman-adv/patches/0037-batman-adv-Avoid-free-alloc-race-when-handling-OGM-b.patch b/batman-adv/patches/0037-batman-adv-Avoid-free-alloc-race-when-handling-OGM-b.patch new file mode 100644 index 0000000..67f635c --- /dev/null +++ b/batman-adv/patches/0037-batman-adv-Avoid-free-alloc-race-when-handling-OGM-b.patch @@ -0,0 +1,136 @@ +From: Sven Eckelmann +Date: Thu, 3 Oct 2019 17:02:01 +0200 +Subject: batman-adv: Avoid free/alloc race when handling OGM buffer + +Each slave interface of an B.A.T.M.A.N. IV virtual interface has an OGM +packet buffer which is initialized using data from the RTNL lock protected +netdevice notifier and other rtnetlink related hooks. It is sent regularly +via various slave interfaces of the batadv virtual interface and in this +process also modified (realloced) to integrate additional state information +via TVLV containers. + +It must be avoided that the worker item is executed without a common lock +with the netdevice notifier/rtnetlink helpers. Otherwise it can either +happen that half modified/freed data is sent out or functions modifying the +OGM buffer try to access already freed memory regions. + +Reported-by: syzbot+0cc629f19ccb8534935b@syzkaller.appspotmail.com +Fixes: ea6f8d42a595 ("batman-adv: move /proc interface handling to /sys") +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/9b8ceef26c697d0c8319748428944c3339a498dc + +diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c +index 36f244125d24c800d35249af7639d39a516588d4..5b2ef12cfabb24ccbe2c1848cfff4d1ded9bd0b0 100644 +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -379,6 +380,8 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) + unsigned char *ogm_buff; + u32 random_seqno; + ++ ASSERT_RTNL(); ++ + /* randomize initial seqno to avoid collision */ + get_random_bytes(&random_seqno, sizeof(random_seqno)); + atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno); +@@ -403,6 +406,8 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) + + static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) + { ++ ASSERT_RTNL(); ++ + kfree(hard_iface->bat_iv.ogm_buff); + hard_iface->bat_iv.ogm_buff = NULL; + } +@@ -412,6 +417,8 @@ static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) + struct batadv_ogm_packet *batadv_ogm_packet; + unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; + ++ ASSERT_RTNL(); ++ + batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; + ether_addr_copy(batadv_ogm_packet->orig, + hard_iface->net_dev->dev_addr); +@@ -425,6 +432,8 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) + struct batadv_ogm_packet *batadv_ogm_packet; + unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; + ++ ASSERT_RTNL(); ++ + batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; + batadv_ogm_packet->ttl = BATADV_TTL; + } +@@ -935,6 +944,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) + u16 tvlv_len = 0; + unsigned long send_time; + ++ ASSERT_RTNL(); ++ + if (hard_iface->if_status == BATADV_IF_NOT_IN_USE || + hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) + return; +@@ -1791,16 +1802,12 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, + batadv_orig_node_put(orig_node); + } + +-static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) ++static void ++batadv_iv_send_outstanding_forw_packet(struct batadv_forw_packet *forw_packet) + { +- struct delayed_work *delayed_work; +- struct batadv_forw_packet *forw_packet; + struct batadv_priv *bat_priv; + bool dropped = false; + +- delayed_work = to_delayed_work(work); +- forw_packet = container_of(delayed_work, struct batadv_forw_packet, +- delayed_work); + bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); + + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) { +@@ -1829,6 +1836,20 @@ static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) + batadv_forw_packet_free(forw_packet, dropped); + } + ++static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) ++{ ++ struct delayed_work *delayed_work; ++ struct batadv_forw_packet *forw_packet; ++ ++ delayed_work = to_delayed_work(work); ++ forw_packet = container_of(delayed_work, struct batadv_forw_packet, ++ delayed_work); ++ ++ rtnl_lock(); ++ batadv_iv_send_outstanding_forw_packet(forw_packet); ++ rtnl_unlock(); ++} ++ + static int batadv_iv_ogm_receive(struct sk_buff *skb, + struct batadv_hard_iface *if_incoming) + { +diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h +index 3392198ff146ba77d320104663e97ab21559d556..49e4e6cb506f192e85e96e8b3e68be3fdc2dca57 100644 +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -82,10 +82,10 @@ enum batadv_dhcp_recipient { + * struct batadv_hard_iface_bat_iv - per hard-interface B.A.T.M.A.N. IV data + */ + struct batadv_hard_iface_bat_iv { +- /** @ogm_buff: buffer holding the OGM packet */ ++ /** @ogm_buff: buffer holding the OGM packet. rtnl protected */ + unsigned char *ogm_buff; + +- /** @ogm_buff_len: length of the OGM packet buffer */ ++ /** @ogm_buff_len: length of the OGM packet buffer. rtnl protected */ + int ogm_buff_len; + + /** @ogm_seqno: OGM sequence number - used to identify each OGM */ diff --git a/batman-adv/patches/0038-batman-adv-Introduce-own-OGM2-buffer-mutex.patch b/batman-adv/patches/0038-batman-adv-Introduce-own-OGM2-buffer-mutex.patch new file mode 100644 index 0000000..0a0d32e --- /dev/null +++ b/batman-adv/patches/0038-batman-adv-Introduce-own-OGM2-buffer-mutex.patch @@ -0,0 +1,138 @@ +From: Sven Eckelmann +Date: Sun, 13 Oct 2019 21:03:06 +0200 +Subject: batman-adv: Introduce own OGM2 buffer mutex + +Only a single function is currently automatically locked by the rtnl_lock +because (unlike B.A.T.M.A.N. IV) the OGM2 buffer is independent of the hard +interfaces on which it will be transmitted. A private mutex can be used +instead to avoid unnecessary delays which would have been introduced by the +global lock. + +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/8069c581f9097f1f9398f2d49047a1dab8093821 + +diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c +index a9f949501ff3c354d38e3ad333901310391f27d8..bf9ea404abe7cbe1dd2113881856cd35b718b7d1 100644 +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -29,11 +29,12 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include + #include +-#include + #include + #include + #include +@@ -142,7 +143,7 @@ static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv) + u16 tvlv_len = 0; + int ret; + +- ASSERT_RTNL(); ++ lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex); + + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) + goto out; +@@ -242,11 +243,12 @@ static void batadv_v_ogm_send(struct work_struct *work) + struct batadv_priv_bat_v *bat_v; + struct batadv_priv *bat_priv; + +- rtnl_lock(); + bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work); + bat_priv = container_of(bat_v, struct batadv_priv, bat_v); ++ ++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + batadv_v_ogm_send_softif(bat_priv); +- rtnl_unlock(); ++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); + } + + /** +@@ -275,13 +277,15 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface) + struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface); + struct batadv_ogm2_packet *ogm_packet; + +- ASSERT_RTNL(); +- ++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); + if (!bat_priv->bat_v.ogm_buff) +- return; ++ goto unlock; + + ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff; + ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr); ++ ++unlock: ++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); + } + + /** +@@ -885,8 +889,6 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv) + unsigned char *ogm_buff; + u32 random_seqno; + +- ASSERT_RTNL(); +- + bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN; + ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC); + if (!ogm_buff) +@@ -905,6 +907,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv) + atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno); + INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send); + ++ mutex_init(&bat_priv->bat_v.ogm_buff_mutex); ++ + return 0; + } + +@@ -916,7 +920,11 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv) + { + cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq); + ++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); ++ + kfree(bat_priv->bat_v.ogm_buff); + bat_priv->bat_v.ogm_buff = NULL; + bat_priv->bat_v.ogm_buff_len = 0; ++ ++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); + } +diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h +index 49e4e6cb506f192e85e96e8b3e68be3fdc2dca57..44c423447fe163eb3b9df5ec5cf229bed6b8d65b 100644 +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include /* for linux/wait.h */ +@@ -1479,15 +1480,18 @@ struct batadv_softif_vlan { + * struct batadv_priv_bat_v - B.A.T.M.A.N. V per soft-interface private data + */ + struct batadv_priv_bat_v { +- /** @ogm_buff: buffer holding the OGM packet. rtnl protected */ ++ /** @ogm_buff: buffer holding the OGM packet */ + unsigned char *ogm_buff; + +- /** @ogm_buff_len: length of the OGM packet buffer. rtnl protected */ ++ /** @ogm_buff_len: length of the OGM packet buffer */ + int ogm_buff_len; + + /** @ogm_seqno: OGM sequence number - used to identify each OGM */ + atomic_t ogm_seqno; + ++ /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */ ++ struct mutex ogm_buff_mutex; ++ + /** @ogm_wq: workqueue used to schedule OGM transmissions */ + struct delayed_work ogm_wq; + }; diff --git a/batman-adv/patches/0039-batman-adv-Avoid-OGM-workqueue-synchronous-cancel-de.patch b/batman-adv/patches/0039-batman-adv-Avoid-OGM-workqueue-synchronous-cancel-de.patch new file mode 100644 index 0000000..1b0a1de --- /dev/null +++ b/batman-adv/patches/0039-batman-adv-Avoid-OGM-workqueue-synchronous-cancel-de.patch @@ -0,0 +1,262 @@ +From: Sven Eckelmann +Date: Sun, 13 Oct 2019 21:03:07 +0200 +Subject: batman-adv: Avoid OGM workqueue synchronous cancel deadlock + +batadv_forw_packet_list_free can be called when an interface is being +disabled. Under this circumstance, the rntl_lock will be held and while it +calls cancel_delayed_work_sync. + +cancel_delayed_work_sync will stop the execution of the current context +when the work item is currently processed. It can now happen that the +cancel_delayed_work_sync was called when rtnl_lock was already called in +batadv_iv_send_outstanding_bat_ogm_packet or when it was in the process of +calling it. In this case, batadv_iv_send_outstanding_bat_ogm_packet waits +for the lock and cancel_delayed_work_sync (which holds the rtnl_lock) is +waiting for batadv_iv_send_outstanding_bat_ogm_packet to finish. + +This can only be avoided by not using (conflicting) blocking locks while +cancel_delayed_work_sync is called. It also has the benefit that the +ogm scheduling functionality can avoid unnecessary delays which can be +introduced by a global lock. + +Fixes: 9b8ceef26c69 ("batman-adv: Avoid free/alloc race when handling OGM buffer") +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/d3be478f1aa27b47f61c4a62e18eb063d47c9168 + +diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c +index 5b2ef12cfabb24ccbe2c1848cfff4d1ded9bd0b0..f5941837c3ad463f276cffdb25f9b6cd87af0e92 100644 +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -42,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -380,7 +380,7 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) + unsigned char *ogm_buff; + u32 random_seqno; + +- ASSERT_RTNL(); ++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + + /* randomize initial seqno to avoid collision */ + get_random_bytes(&random_seqno, sizeof(random_seqno)); +@@ -388,8 +388,10 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) + + hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN; + ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC); +- if (!ogm_buff) ++ if (!ogm_buff) { ++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); + return -ENOMEM; ++ } + + hard_iface->bat_iv.ogm_buff = ogm_buff; + +@@ -401,41 +403,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) + batadv_ogm_packet->reserved = 0; + batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; + ++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); ++ + return 0; + } + + static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) + { +- ASSERT_RTNL(); ++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + + kfree(hard_iface->bat_iv.ogm_buff); + hard_iface->bat_iv.ogm_buff = NULL; ++ ++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); + } + + static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) + { + struct batadv_ogm_packet *batadv_ogm_packet; +- unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; ++ void *ogm_buff; + +- ASSERT_RTNL(); ++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + +- batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; ++ ogm_buff = hard_iface->bat_iv.ogm_buff; ++ if (!ogm_buff) ++ goto unlock; ++ ++ batadv_ogm_packet = ogm_buff; + ether_addr_copy(batadv_ogm_packet->orig, + hard_iface->net_dev->dev_addr); + ether_addr_copy(batadv_ogm_packet->prev_sender, + hard_iface->net_dev->dev_addr); ++ ++unlock: ++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); + } + + static void + batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) + { + struct batadv_ogm_packet *batadv_ogm_packet; +- unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; ++ void *ogm_buff; + +- ASSERT_RTNL(); ++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); + +- batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; ++ ogm_buff = hard_iface->bat_iv.ogm_buff; ++ if (!ogm_buff) ++ goto unlock; ++ ++ batadv_ogm_packet = ogm_buff; + batadv_ogm_packet->ttl = BATADV_TTL; ++ ++unlock: ++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); + } + + /* when do we schedule our own ogm to be sent */ +@@ -933,7 +953,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) + } + } + +-static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) ++/** ++ * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer ++ * @hard_iface: interface whose ogm buffer should be transmitted ++ */ ++static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) + { + struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff; +@@ -944,11 +968,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) + u16 tvlv_len = 0; + unsigned long send_time; + +- ASSERT_RTNL(); +- +- if (hard_iface->if_status == BATADV_IF_NOT_IN_USE || +- hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) +- return; ++ lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex); + + /* the interface gets activated here to avoid race conditions between + * the moment of activating the interface in +@@ -1016,6 +1036,17 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) + batadv_hardif_put(primary_if); + } + ++static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) ++{ ++ if (hard_iface->if_status == BATADV_IF_NOT_IN_USE || ++ hard_iface->if_status == BATADV_IF_TO_BE_REMOVED) ++ return; ++ ++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex); ++ batadv_iv_ogm_schedule_buff(hard_iface); ++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex); ++} ++ + /** + * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an + * originator +@@ -1802,12 +1833,16 @@ static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, + batadv_orig_node_put(orig_node); + } + +-static void +-batadv_iv_send_outstanding_forw_packet(struct batadv_forw_packet *forw_packet) ++static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) + { ++ struct delayed_work *delayed_work; ++ struct batadv_forw_packet *forw_packet; + struct batadv_priv *bat_priv; + bool dropped = false; + ++ delayed_work = to_delayed_work(work); ++ forw_packet = container_of(delayed_work, struct batadv_forw_packet, ++ delayed_work); + bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); + + if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) { +@@ -1836,20 +1871,6 @@ batadv_iv_send_outstanding_forw_packet(struct batadv_forw_packet *forw_packet) + batadv_forw_packet_free(forw_packet, dropped); + } + +-static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work) +-{ +- struct delayed_work *delayed_work; +- struct batadv_forw_packet *forw_packet; +- +- delayed_work = to_delayed_work(work); +- forw_packet = container_of(delayed_work, struct batadv_forw_packet, +- delayed_work); +- +- rtnl_lock(); +- batadv_iv_send_outstanding_forw_packet(forw_packet); +- rtnl_unlock(); +-} +- + static int batadv_iv_ogm_receive(struct sk_buff *skb, + struct batadv_hard_iface *if_incoming) + { +diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c +index 36f0962040d16af4f9ed82629ff03ce85c83ed57..c4e0435c952db87c89727633c184320820812cda 100644 +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -933,6 +934,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) + INIT_LIST_HEAD(&hard_iface->list); + INIT_HLIST_HEAD(&hard_iface->neigh_list); + ++ mutex_init(&hard_iface->bat_iv.ogm_buff_mutex); + spin_lock_init(&hard_iface->neigh_list_lock); + kref_init(&hard_iface->refcount); + +diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h +index 44c423447fe163eb3b9df5ec5cf229bed6b8d65b..85f52dc42e17f7ed550f13048a2e2bd9d372196b 100644 +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -83,14 +83,17 @@ enum batadv_dhcp_recipient { + * struct batadv_hard_iface_bat_iv - per hard-interface B.A.T.M.A.N. IV data + */ + struct batadv_hard_iface_bat_iv { +- /** @ogm_buff: buffer holding the OGM packet. rtnl protected */ ++ /** @ogm_buff: buffer holding the OGM packet */ + unsigned char *ogm_buff; + +- /** @ogm_buff_len: length of the OGM packet buffer. rtnl protected */ ++ /** @ogm_buff_len: length of the OGM packet buffer */ + int ogm_buff_len; + + /** @ogm_seqno: OGM sequence number - used to identify each OGM */ + atomic_t ogm_seqno; ++ ++ /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */ ++ struct mutex ogm_buff_mutex; + }; + + /** diff --git a/batman-adv/patches/0040-batman-adv-Fix-DAT-candidate-selection-on-little-end.patch b/batman-adv/patches/0040-batman-adv-Fix-DAT-candidate-selection-on-little-end.patch new file mode 100644 index 0000000..05b0636 --- /dev/null +++ b/batman-adv/patches/0040-batman-adv-Fix-DAT-candidate-selection-on-little-end.patch @@ -0,0 +1,43 @@ +From: Sven Eckelmann +Date: Thu, 28 Nov 2019 12:43:49 +0100 +Subject: batman-adv: Fix DAT candidate selection on little endian systems + +The distributed arp table is using a DHT to store and retrieve MAC address +information for an IP address. This is done using unicast messages to +selected peers. The potential peers are looked up using the IP address and +the VID. + +While the IP address is always stored in big endian byte order, it is not +the case of the VID. It can (depending on the host system) either be big +endian or little endian. The host must therefore always convert it to big +endian to ensure that all devices calculate the same peers for the same +lookup data. + +Fixes: 3e26722bc9f2 ("batman-adv: make the Distributed ARP Table vlan aware") +Signed-off-by: Sven Eckelmann +Acked-by: Antonio Quartulli + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/728aea06f38e0e4d70f4f7d43698187f7f7055c5 + +diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c +index a60bacf7120be88ba7626cf0a87dd34eef0a2eec..21783805a3afd974cebc7e640249402d637d731a 100644 +--- a/net/batman-adv/distributed-arp-table.c ++++ b/net/batman-adv/distributed-arp-table.c +@@ -251,6 +251,7 @@ static u32 batadv_hash_dat(const void *data, u32 size) + u32 hash = 0; + const struct batadv_dat_entry *dat = data; + const unsigned char *key; ++ __be16 vid; + u32 i; + + key = (const unsigned char *)&dat->ip; +@@ -260,7 +261,8 @@ static u32 batadv_hash_dat(const void *data, u32 size) + hash ^= (hash >> 6); + } + +- key = (const unsigned char *)&dat->vid; ++ vid = htons(dat->vid); ++ key = (__force const unsigned char *)&vid; + for (i = 0; i < sizeof(dat->vid); i++) { + hash += key[i]; + hash += (hash << 10); diff --git a/batman-adv/patches/0041-batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch b/batman-adv/patches/0041-batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch new file mode 100644 index 0000000..a039a22 --- /dev/null +++ b/batman-adv/patches/0041-batman-adv-Don-t-schedule-OGM-for-disabled-interface.patch @@ -0,0 +1,37 @@ +From: Sven Eckelmann +Date: Sun, 16 Feb 2020 13:02:06 +0100 +Subject: batman-adv: Don't schedule OGM for disabled interface + +A transmission scheduling for an interface which is currently dropped by +batadv_iv_ogm_iface_disable could still be in progress. The B.A.T.M.A.N. V +is simply cancelling the workqueue item in an synchronous way but this is +not possible with B.A.T.M.A.N. IV because the OGM submissions are +intertwined. + +Instead it has to stop submitting the OGM when it detect that the buffer +pointer is set to NULL. + +Reported-by: syzbot+a98f2016f40b9cd3818a@syzkaller.appspotmail.com +Reported-by: syzbot+ac36b6a33c28a491e929@syzkaller.appspotmail.com +Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol") +Signed-off-by: Sven Eckelmann +Cc: Hillf Danton +Signed-off-by: Simon Wunderlich + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/a089c55ca004b396d340baae58abe9a79f32cc0f + +diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c +index f5941837c3ad463f276cffdb25f9b6cd87af0e92..0b052ff51bdeb36f7eac9abca927e267533d2930 100644 +--- a/net/batman-adv/bat_iv_ogm.c ++++ b/net/batman-adv/bat_iv_ogm.c +@@ -970,6 +970,10 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) + + lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex); + ++ /* interface already disabled by batadv_iv_ogm_iface_disable */ ++ if (!*ogm_buff) ++ return; ++ + /* the interface gets activated here to avoid race conditions between + * the moment of activating the interface in + * hardif_activate_interface() where the originator mac is set and diff --git a/batman-adv/patches/0042-batman-adv-fix-batadv_nc_random_weight_tq.patch b/batman-adv/patches/0042-batman-adv-fix-batadv_nc_random_weight_tq.patch new file mode 100644 index 0000000..d3f356b --- /dev/null +++ b/batman-adv/patches/0042-batman-adv-fix-batadv_nc_random_weight_tq.patch @@ -0,0 +1,59 @@ +From: George Spelvin +Date: Sun, 8 Mar 2020 09:44:59 -0400 +Subject: batman-adv: fix batadv_nc_random_weight_tq + +and change to pseudorandom numbers, as this is a traffic dithering +operation that doesn't need crypto-grade. + +The previous code operated in 4 steps: + +1. Generate a random byte 0 <= rand_tq <= 255 +2. Multiply it by BATADV_TQ_MAX_VALUE - tq +3. Divide by 255 (= BATADV_TQ_MAX_VALUE) +4. Return BATADV_TQ_MAX_VALUE - rand_tq + +This would apperar to scale (BATADV_TQ_MAX_VALUE - tq) by a random +value between 0/255 and 255/255. + +But! The intermediate value between steps 3 and 4 is stored in a u8 +variable. So it's truncated, and most of the time, is less than 255, after +which the division produces 0. Specifically, if tq is odd, the product is +always even, and can never be 255. If tq is even, there's exactly one +random byte value that will produce a product byte of 255. + +Thus, the return value is 255 (511/512 of the time) or 254 (1/512 +of the time). + +If we assume that the truncation is a bug, and the code is meant to scale +the input, a simpler way of looking at it is that it's returning a random +value between tq and BATADV_TQ_MAX_VALUE, inclusive. + +Well, we have an optimized function for doing just that. + +Fixes: c3289f3650d3 ("batman-adv: network coding - code and transmit packets if possible") +Signed-off-by: George Spelvin +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/db48c60b0edb995450ee846157364bd09bb23762 + +diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c +index 34caf129a9bf5531360f798be6a7059bad26a50f..7f1be5a287575d51ffd5b4e7ecf540b8fd7de700 100644 +--- a/net/batman-adv/network-coding.c ++++ b/net/batman-adv/network-coding.c +@@ -1021,15 +1021,8 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, + */ + static u8 batadv_nc_random_weight_tq(u8 tq) + { +- u8 rand_val, rand_tq; +- +- get_random_bytes(&rand_val, sizeof(rand_val)); +- + /* randomize the estimated packet loss (max TQ - estimated TQ) */ +- rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq); +- +- /* normalize the randomized packet loss */ +- rand_tq /= BATADV_TQ_MAX_VALUE; ++ u8 rand_tq = prandom_u32_max(BATADV_TQ_MAX_VALUE + 1 - tq); + + /* convert to (randomized) estimated tq again */ + return BATADV_TQ_MAX_VALUE - rand_tq; diff --git a/batman-adv/patches/0043-batman-adv-Fix-refcnt-leak-in-batadv_show_throughput.patch b/batman-adv/patches/0043-batman-adv-Fix-refcnt-leak-in-batadv_show_throughput.patch new file mode 100644 index 0000000..f6c45df --- /dev/null +++ b/batman-adv/patches/0043-batman-adv-Fix-refcnt-leak-in-batadv_show_throughput.patch @@ -0,0 +1,38 @@ +From: Xiyu Yang +Date: Wed, 15 Apr 2020 16:31:50 +0800 +Subject: batman-adv: Fix refcnt leak in batadv_show_throughput_override + +batadv_show_throughput_override() invokes batadv_hardif_get_by_netdev(), +which gets a batadv_hard_iface object from net_dev with increased refcnt +and its reference is assigned to a local pointer 'hard_iface'. + +When batadv_show_throughput_override() returns, "hard_iface" becomes +invalid, so the refcount should be decreased to keep refcount balanced. + +The issue happens in the normal path of +batadv_show_throughput_override(), which forgets to decrease the refcnt +increased by batadv_hardif_get_by_netdev() before the function returns, +causing a refcnt leak. + +Fix this issue by calling batadv_hardif_put() before the +batadv_show_throughput_override() returns in the normal path. + +Fixes: c513176e4b7a ("batman-adv: add throughput override attribute to hard_ifaces") +Signed-off-by: Xiyu Yang +Signed-off-by: Xin Tan +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/f301bfed59b146a63471d0f147b767d7cafede6f + +diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c +index 09427fc6494a157554d8b19f3481a878a9f97bba..7f7de0b16aa7ab70986735fbd9b42fd02de8a924 100644 +--- a/net/batman-adv/sysfs.c ++++ b/net/batman-adv/sysfs.c +@@ -1126,6 +1126,7 @@ static ssize_t batadv_show_throughput_override(struct kobject *kobj, + + tp_override = atomic_read(&hard_iface->bat_v.throughput_override); + ++ batadv_hardif_put(hard_iface); + return sprintf(buff, "%u.%u MBit\n", tp_override / 10, + tp_override % 10); + } diff --git a/batman-adv/patches/0044-batman-adv-Fix-refcnt-leak-in-batadv_store_throughpu.patch b/batman-adv/patches/0044-batman-adv-Fix-refcnt-leak-in-batadv_store_throughpu.patch new file mode 100644 index 0000000..bf93520 --- /dev/null +++ b/batman-adv/patches/0044-batman-adv-Fix-refcnt-leak-in-batadv_store_throughpu.patch @@ -0,0 +1,39 @@ +From: Xiyu Yang +Date: Wed, 15 Apr 2020 16:35:21 +0800 +Subject: batman-adv: Fix refcnt leak in batadv_store_throughput_override + +batadv_show_throughput_override() invokes batadv_hardif_get_by_netdev(), +which gets a batadv_hard_iface object from net_dev with increased refcnt +and its reference is assigned to a local pointer 'hard_iface'. + +When batadv_store_throughput_override() returns, "hard_iface" becomes +invalid, so the refcount should be decreased to keep refcount balanced. + +The issue happens in one error path of +batadv_store_throughput_override(). When batadv_parse_throughput() +returns NULL, the refcnt increased by batadv_hardif_get_by_netdev() is +not decreased, causing a refcnt leak. + +Fix this issue by jumping to "out" label when batadv_parse_throughput() +returns NULL. + +Fixes: c513176e4b7a ("batman-adv: add throughput override attribute to hard_ifaces") +Signed-off-by: Xiyu Yang +Signed-off-by: Xin Tan +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/b69cd8bdbfd6fa7e61878c2fa9e6637406f40dd9 + +diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c +index 7f7de0b16aa7ab70986735fbd9b42fd02de8a924..976b038e53bf934332a39bad8a5509ca1aac0add 100644 +--- a/net/batman-adv/sysfs.c ++++ b/net/batman-adv/sysfs.c +@@ -1093,7 +1093,7 @@ static ssize_t batadv_store_throughput_override(struct kobject *kobj, + ret = batadv_parse_throughput(net_dev, buff, "throughput_override", + &tp_override); + if (!ret) +- return count; ++ goto out; + + old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override); + if (old_tp_override == tp_override) diff --git a/batman-adv/patches/0045-batman-adv-Fix-refcnt-leak-in-batadv_v_ogm_process.patch b/batman-adv/patches/0045-batman-adv-Fix-refcnt-leak-in-batadv_v_ogm_process.patch new file mode 100644 index 0000000..cf16c46 --- /dev/null +++ b/batman-adv/patches/0045-batman-adv-Fix-refcnt-leak-in-batadv_v_ogm_process.patch @@ -0,0 +1,39 @@ +From: Xiyu Yang +Date: Mon, 20 Apr 2020 13:37:20 +0800 +Subject: batman-adv: Fix refcnt leak in batadv_v_ogm_process + +batadv_v_ogm_process() invokes batadv_hardif_neigh_get(), which returns +a reference of the neighbor object to "hardif_neigh" with increased +refcount. + +When batadv_v_ogm_process() returns, "hardif_neigh" becomes invalid, so +the refcount should be decreased to keep refcount balanced. + +The reference counting issue happens in one exception handling paths of +batadv_v_ogm_process(). When batadv_v_ogm_orig_get() fails to get the +orig node and returns NULL, the refcnt increased by +batadv_hardif_neigh_get() is not decreased, causing a refcnt leak. + +Fix this issue by jumping to "out" label when batadv_v_ogm_orig_get() +fails to get the orig node. + +Fixes: 667996ebeab4 ("batman-adv: OGMv2 - implement originators logic") +Signed-off-by: Xiyu Yang +Signed-off-by: Xin Tan +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/4515f5e6a4ccbe1c563b05f2d487eb9eef3c9740 + +diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c +index bf9ea404abe7cbe1dd2113881856cd35b718b7d1..0458de53cb64b2da51de492ffa27f33068351cc8 100644 +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -735,7 +735,7 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset, + + orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig); + if (!orig_node) +- return; ++ goto out; + + neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming, + ethhdr->h_source); diff --git a/batman-adv/patches/0046-batman-adv-Avoid-uninitialized-chaddr-when-handling-.patch b/batman-adv/patches/0046-batman-adv-Avoid-uninitialized-chaddr-when-handling-.patch new file mode 100644 index 0000000..43a4150 --- /dev/null +++ b/batman-adv/patches/0046-batman-adv-Avoid-uninitialized-chaddr-when-handling-.patch @@ -0,0 +1,42 @@ +From: Sven Eckelmann +Date: Wed, 22 Jul 2020 20:49:23 +0200 +Subject: batman-adv: Avoid uninitialized chaddr when handling DHCP + +The gateway client code can try to optimize the delivery of DHCP packets to +avoid broadcasting them through the whole mesh. But also transmissions to +the client can be optimized by looking up the destination via the chaddr of +the DHCP packet. + +But the chaddr is currently only done when chaddr is fully inside the +non-paged area of the skbuff. Otherwise it will not be initialized and the +unoptimized path should have been taken. + +But the implementation didn't handle this correctly. It didn't retrieve the +correct chaddr but still tried to perform the TT lookup with this +uninitialized memory. + +Reported-by: syzbot+ab16e463b903f5a37036@syzkaller.appspotmail.com +Fixes: 2d5b555644b2 ("batman-adv: send every DHCP packet as bat-unicast") +Signed-off-by: Sven Eckelmann +Acked-by: Antonio Quartulli +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/fcdf008ffd749246632d1f9423163af5dc3f8c7f + +diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c +index 140c61a3f1ecfec4fe23c5ddca19e18e2e86fd56..0c59fefc137196899f97e0fa7882cf55ceebe34c 100644 +--- a/net/batman-adv/gateway_client.c ++++ b/net/batman-adv/gateway_client.c +@@ -714,8 +714,10 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, + + chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET; + /* store the client address if the message is going to a client */ +- if (ret == BATADV_DHCP_TO_CLIENT && +- pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) { ++ if (ret == BATADV_DHCP_TO_CLIENT) { ++ if (!pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) ++ return BATADV_DHCP_NO; ++ + /* check if the DHCP packet carries an Ethernet DHCP */ + p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET; + if (*p != BATADV_DHCP_HTYPE_ETHERNET) diff --git a/batman-adv/patches/0047-batman-adv-Fix-own-OGM-check-in-aggregated-OGMs.patch b/batman-adv/patches/0047-batman-adv-Fix-own-OGM-check-in-aggregated-OGMs.patch new file mode 100644 index 0000000..1b6f152 --- /dev/null +++ b/batman-adv/patches/0047-batman-adv-Fix-own-OGM-check-in-aggregated-OGMs.patch @@ -0,0 +1,59 @@ +From: Linus Lüssing +Date: Fri, 31 Jul 2020 00:22:55 +0200 +Subject: batman-adv: Fix own OGM check in aggregated OGMs + +The own OGM check is currently misplaced and can lead to the following +issues: + +For one thing we might receive an aggregated OGM from a neighbor node +which has our own OGM in the first place. We would then not only skip +our own OGM but erroneously also any other, following OGM in the +aggregate. + +For another, we might receive an OGM aggregate which has our own OGM in +a place other then the first one. Then we would wrongly not skip this +OGM, leading to populating the orginator and gateway table with ourself. + +The latter seems to not only be a cosmetic issue, but there were reports +that this causes issues with various subsystems of batman-adv, too. For +instance there were reports about issues with DAT and either disabling +DAT or aggregation seemed to solve it. + +Fixing these issues by applying the own OGM check not on the first OGM +in an aggregate but for each OGM in an aggregate instead. + +Fixes: 667996ebeab ("batman-adv: OGMv2 - implement originators logic") +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/d41cc7cb62c184b2fb8ab97fda45815918200001 + +diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c +index 0458de53cb64b2da51de492ffa27f33068351cc8..04a620fd13014463ed0c7c047f3a61a05d862e39 100644 +--- a/net/batman-adv/bat_v_ogm.c ++++ b/net/batman-adv/bat_v_ogm.c +@@ -716,6 +716,12 @@ static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset, + ntohl(ogm_packet->seqno), ogm_throughput, ogm_packet->ttl, + ogm_packet->version, ntohs(ogm_packet->tvlv_len)); + ++ if (batadv_is_my_mac(bat_priv, ogm_packet->orig)) { ++ batadv_dbg(BATADV_DBG_BATMAN, bat_priv, ++ "Drop packet: originator packet from ourself\n"); ++ return; ++ } ++ + /* If the throughput metric is 0, immediately drop the packet. No need + * to create orig_node / neigh_node for an unusable route. + */ +@@ -843,11 +849,6 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb, + if (batadv_is_my_mac(bat_priv, ethhdr->h_source)) + goto free_skb; + +- ogm_packet = (struct batadv_ogm2_packet *)skb->data; +- +- if (batadv_is_my_mac(bat_priv, ogm_packet->orig)) +- goto free_skb; +- + batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX); + batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES, + skb->len + ETH_HLEN); diff --git a/batman-adv/patches/0048-batman-adv-bla-use-netif_rx_ni-when-not-in-interrupt.patch b/batman-adv/patches/0048-batman-adv-bla-use-netif_rx_ni-when-not-in-interrupt.patch new file mode 100644 index 0000000..2705afa --- /dev/null +++ b/batman-adv/patches/0048-batman-adv-bla-use-netif_rx_ni-when-not-in-interrupt.patch @@ -0,0 +1,31 @@ +From: Jussi Kivilinna +Date: Tue, 18 Aug 2020 17:46:10 +0300 +Subject: batman-adv: bla: use netif_rx_ni when not in interrupt context + +batadv_bla_send_claim() gets called from worker thread context through +batadv_bla_periodic_work(), thus netif_rx_ni needs to be used in that +case. This fixes "NOHZ: local_softirq_pending 08" log messages seen +when batman-adv is enabled. + +Fixes: a9ce0dc43e2c ("batman-adv: add basic bridge loop avoidance code") +Signed-off-by: Jussi Kivilinna +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/3747f81a1380b65740fc52fc71c7a3af4c6e49de + +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index 0842080a71f4ac89b3fbebc4b95c6c27d1cc4254..ed8259ff0dc7ba129825a369a757b37cc62ce829 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -450,7 +450,10 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac, + batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, + skb->len + ETH_HLEN); + +- netif_rx(skb); ++ if (in_interrupt()) ++ netif_rx(skb); ++ else ++ netif_rx_ni(skb); + out: + if (primary_if) + batadv_hardif_put(primary_if); diff --git a/batman-adv/patches/0049-batman-adv-bla-fix-type-misuse-for-backbone_gw-hash-.patch b/batman-adv/patches/0049-batman-adv-bla-fix-type-misuse-for-backbone_gw-hash-.patch new file mode 100644 index 0000000..9a98294 --- /dev/null +++ b/batman-adv/patches/0049-batman-adv-bla-fix-type-misuse-for-backbone_gw-hash-.patch @@ -0,0 +1,41 @@ +From: Linus Lüssing +Date: Thu, 27 Aug 2020 17:34:48 +0200 +Subject: batman-adv: bla: fix type misuse for backbone_gw hash indexing + +It seems that due to a copy & paste error the void pointer +in batadv_choose_backbone_gw() is cast to the wrong type. + +Fixing this by using "struct batadv_bla_backbone_gw" instead of "struct +batadv_bla_claim" which better matches the caller's side. + +For now it seems that we were lucky because the two structs both have +their orig/vid and addr/vid in the beginning. However I stumbled over +this issue when I was trying to add some debug variables in front of +"orig" in batadv_backbone_gw, which caused hash lookups to fail. + +Fixes: 7e15c9305ce0 ("batman-adv: don't rely on positions in struct for hashing") +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/398a706cd46c1fc085aef56ae8ed11f76e182bd1 + +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index ed8259ff0dc7ba129825a369a757b37cc62ce829..9dc574f5659e2bce97bd7e0f3793f8c1edf1fbd5 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -96,11 +96,12 @@ static inline u32 batadv_choose_claim(const void *data, u32 size) + */ + static inline u32 batadv_choose_backbone_gw(const void *data, u32 size) + { +- const struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data; ++ const struct batadv_bla_backbone_gw *gw; + u32 hash = 0; + +- hash = jhash(&claim->addr, sizeof(claim->addr), hash); +- hash = jhash(&claim->vid, sizeof(claim->vid), hash); ++ gw = (struct batadv_bla_backbone_gw *)data; ++ hash = jhash(&gw->orig, sizeof(gw->orig), hash); ++ hash = jhash(&gw->vid, sizeof(gw->vid), hash); + + return hash % size; + } diff --git a/batman-adv/patches/0050-batman-adv-mcast-TT-fix-wrongly-dropped-or-rerouted-.patch b/batman-adv/patches/0050-batman-adv-mcast-TT-fix-wrongly-dropped-or-rerouted-.patch new file mode 100644 index 0000000..0e121df --- /dev/null +++ b/batman-adv/patches/0050-batman-adv-mcast-TT-fix-wrongly-dropped-or-rerouted-.patch @@ -0,0 +1,45 @@ +From: Linus Lüssing +Date: Fri, 4 Sep 2020 20:28:00 +0200 +Subject: batman-adv: mcast/TT: fix wrongly dropped or rerouted packets + +The unicast packet rerouting code makes several assumptions. For +instance it assumes that there is always exactly one destination in the +TT. This breaks for multicast frames in a unicast packets in several ways: + +For one thing if there is actually no TT entry and the destination node +was selected due to the multicast tvlv flags it announced. Then an +intermediate node will wrongly drop the packet. + +For another thing if there is a TT entry but the TTVN of this entry is +newer than the originally addressed destination node: Then the +intermediate node will wrongly redirect the packet, leading to +duplicated multicast packets at a multicast listener and missing +packets at other multicast listeners or multicast routers. + +Fixing this by not applying the unicast packet rerouting to batman-adv +unicast packets with a multicast payload. We are not able to detect a +roaming multicast listener at the moment and will just continue to send +the multicast frame to both the new and old destination for a while in +case of such a roaming multicast listener. + +Fixes: cea194d90b11 ("batman-adv: improved client announcement mechanism") +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/22e740c5e6c9342e0f5028beb3d14b84a018d113 + +diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c +index cc3ed93a6d513dffd4711cac50545d65ef7d640e..98af41e3810dcdf96edad8dff89d4d2b624c5d7f 100644 +--- a/net/batman-adv/routing.c ++++ b/net/batman-adv/routing.c +@@ -838,6 +838,10 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, + vid = batadv_get_vid(skb, hdr_len); + ethhdr = (struct ethhdr *)(skb->data + hdr_len); + ++ /* do not reroute multicast frames in a unicast header */ ++ if (is_multicast_ether_addr(ethhdr->h_dest)) ++ return true; ++ + /* check if the destination client was served by this node and it is now + * roaming. In this case, it means that the node has got a ROAM_ADV + * message and that it knows the new destination in the mesh to re-route diff --git a/batman-adv/patches/0051-batman-adv-Add-missing-include-for-in_interrupt.patch b/batman-adv/patches/0051-batman-adv-Add-missing-include-for-in_interrupt.patch new file mode 100644 index 0000000..abadd1b --- /dev/null +++ b/batman-adv/patches/0051-batman-adv-Add-missing-include-for-in_interrupt.patch @@ -0,0 +1,26 @@ +From: Sven Eckelmann +Date: Mon, 14 Sep 2020 13:58:16 +0200 +Subject: batman-adv: Add missing include for in_interrupt() + +The fix for receiving (internally generated) bla packets outside the +interrupt context introduced the usage of in_interrupt(). But this +functionality is only defined in linux/preempt.h which was not included +with the same patch. + +Fixes: 3747f81a1380 ("batman-adv: bla: use netif_rx_ni when not in interrupt context") +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/6ea99cd9c82b2d1bc4a313fe9006bcf5d956380e + +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index 9dc574f5659e2bce97bd7e0f3793f8c1edf1fbd5..26f590ba31d49a85143f67f1c002a25dc007b594 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/batman-adv/patches/0052-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch b/batman-adv/patches/0052-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch new file mode 100644 index 0000000..07e7d27 --- /dev/null +++ b/batman-adv/patches/0052-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch @@ -0,0 +1,144 @@ +From: Linus Lüssing +Date: Tue, 15 Sep 2020 09:54:08 +0200 +Subject: batman-adv: mcast: fix duplicate mcast packets in BLA backbone from LAN + +Scenario: +* Multicast frame send from a BLA backbone (multiple nodes with + their bat0 bridged together, with BLA enabled) + +Issue: +* BLA backbone nodes receive the frame multiple times on bat0 + +For multicast frames received via batman-adv broadcast packets the +originator of the broadcast packet is checked before decapsulating and +forwarding the frame to bat0 (batadv_bla_is_backbone_gw()-> +batadv_recv_bcast_packet()). If it came from a node which shares the +same BLA backbone with us then it is not forwarded to bat0 to avoid a +loop. + +When sending a multicast frame in a non-4-address batman-adv unicast +packet we are currently missing this check - and cannot do so because +the batman-adv unicast packet has no originator address field. + +However, we can simply fix this on the sender side by only sending the +multicast frame via unicasts to interested nodes which do not share the +same BLA backbone with us. This also nicely avoids some unnecessary +transmissions on mesh side. + +Note that no infinite loop was observed, probably because of dropping +via batadv_interface_tx()->batadv_bla_tx(). However the duplicates still +utterly confuse switches/bridges, ICMPv6 duplicate address detection and +neighbor discovery and therefore leads to long delays before being able +to establish TCP connections, for instance. And it also leads to the Linux +bridge printing messages like: +"br-lan: received packet on eth1 with own address as source address ..." + +Fixes: 405cc1e5a81e ("batman-adv: Modified forwarding behaviour for multicast packets") +Signed-off-by: Linus Lüssing +Acked-by: Simon Wunderlich +Signed-off-by: Sven Eckelmann + +Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/3c39a2455a5be02ecceeaf1a15976bddd611392e + +diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c +index 39640d3d6fbdf8244344db6e79f2d769eb0972d9..764c304ffa5f6dc976050fa6b6f6e0891981c4f4 100644 +--- a/net/batman-adv/multicast.c ++++ b/net/batman-adv/multicast.c +@@ -62,10 +62,12 @@ + #include + #include + ++#include "bridge_loop_avoidance.h" + #include "hard-interface.h" + #include "hash.h" + #include "log.h" + #include "netlink.h" ++#include "send.h" + #include "soft-interface.h" + #include "translation-table.h" + #include "tvlv.h" +@@ -1027,6 +1029,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, + } + } + ++/** ++ * batadv_mcast_forw_send_orig() - send a multicast packet to an originator ++ * @bat_priv: the bat priv with all the soft interface information ++ * @skb: the multicast packet to send ++ * @vid: the vlan identifier ++ * @orig_node: the originator to send the packet to ++ * ++ * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. ++ */ ++int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, ++ struct sk_buff *skb, ++ unsigned short vid, ++ struct batadv_orig_node *orig_node) ++{ ++ /* Avoid sending multicast-in-unicast packets to other BLA ++ * gateways - they already got the frame from the LAN side ++ * we share with them. ++ * TODO: Refactor to take BLA into account earlier, to avoid ++ * reducing the mcast_fanout count. ++ */ ++ if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid)) { ++ dev_kfree_skb(skb); ++ return NET_XMIT_SUCCESS; ++ } ++ ++ return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0, ++ orig_node, vid); ++} ++ + /** + * batadv_mcast_want_unsnoop_update() - update unsnoop counter and list + * @bat_priv: the bat priv with all the soft interface information +diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h +index 3b04ab13f0eb1044454315c04e75a22ce4351afd..6f9f3813fc59a8e8798b71297c8d8f9ef50b5e72 100644 +--- a/net/batman-adv/multicast.h ++++ b/net/batman-adv/multicast.h +@@ -51,6 +51,11 @@ enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, + struct batadv_orig_node **mcast_single_orig); + ++int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, ++ struct sk_buff *skb, ++ unsigned short vid, ++ struct batadv_orig_node *orig_node); ++ + void batadv_mcast_init(struct batadv_priv *bat_priv); + + int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset); +@@ -78,6 +83,16 @@ static inline int batadv_mcast_init(struct batadv_priv *bat_priv) + return 0; + } + ++static inline int ++batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, ++ struct sk_buff *skb, ++ unsigned short vid, ++ struct batadv_orig_node *orig_node) ++{ ++ kfree_skb(skb); ++ return NET_XMIT_DROP; ++} ++ + static inline int + batadv_mcast_mesh_info_put(struct sk_buff *msg, struct batadv_priv *bat_priv) + { +diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c +index 97e28907a0acbb3d64d8ceebf7b1df13dc396300..267f6e6c802f1a7d3eb41a0f3aa2142ca3b21414 100644 +--- a/net/batman-adv/soft-interface.c ++++ b/net/batman-adv/soft-interface.c +@@ -367,9 +367,8 @@ static int batadv_interface_tx(struct sk_buff *skb, + goto dropped; + ret = batadv_send_skb_via_gw(bat_priv, skb, vid); + } else if (mcast_single_orig) { +- ret = batadv_send_skb_unicast(bat_priv, skb, +- BATADV_UNICAST, 0, +- mcast_single_orig, vid); ++ ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid, ++ mcast_single_orig); + } else { + if (batadv_dat_snoop_outgoing_arp_request(bat_priv, + skb)) diff --git a/batman-adv/patches/0053-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch b/batman-adv/patches/0053-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch new file mode 100644 index 0000000..284e2da --- /dev/null +++ b/batman-adv/patches/0053-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch @@ -0,0 +1,156 @@ +From: Linus Lüssing +Date: Tue, 15 Sep 2020 09:54:09 +0200 +Subject: batman-adv: mcast: fix duplicate mcast packets in BLA backbone from mesh + +Scenario: +* Multicast frame send from mesh to a BLA backbone (multiple nodes + with their bat0 bridged together, with BLA enabled) + +Issue: +* BLA backbone nodes receive the frame multiple times on bat0, + once from mesh->bat0 and once from each backbone_gw from LAN + +For unicast, a node will send only to the best backbone gateway +according to the TQ. However for multicast we currently cannot determine +if multiple destination nodes share the same backbone if they don't share +the same backbone with us. So we need to keep sending the unicasts to +all backbone gateways and let the backbone gateways decide which one +will forward the frame. We can use the CLAIM mechanism to make this +decision. + +One catch: The batman-adv gateway feature for DHCP packets potentially +sends multicast packets in the same batman-adv unicast header as the +multicast optimizations code. And we are not allowed to drop those even +if we did not claim the source address of the sender, as for such +packets there is only this one multicast-in-unicast packet. + +How can we distinguish the two cases? + +The gateway feature uses a batman-adv unicast 4 address header. While +the multicast-to-unicasts feature uses a simple, 3 address batman-adv +unicast header. So let's use this to distinguish. + +Fixes: e32470167379 ("batman-adv: check incoming packet type for bla") +Signed-off-by: Linus Lüssing +Acked-by: Simon Wunderlich +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/d7665cf8a824c41c61c6e2110ab63d37eb7a8ef7 + +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index 26f590ba31d49a85143f67f1c002a25dc007b594..4dc67a0d081c06507aba87f7bec03488817791b2 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -1827,7 +1827,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb, + * @bat_priv: the bat priv with all the soft interface information + * @skb: the frame to be checked + * @vid: the VLAN ID of the frame +- * @is_bcast: the packet came in a broadcast packet type. ++ * @packet_type: the batman packet type this frame came in + * + * batadv_bla_rx avoidance checks if: + * * we have to race for a claim +@@ -1839,7 +1839,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb, + * further process the skb. + */ + bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, +- unsigned short vid, bool is_bcast) ++ unsigned short vid, int packet_type) + { + struct batadv_bla_backbone_gw *backbone_gw; + struct ethhdr *ethhdr; +@@ -1861,9 +1861,24 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, + goto handled; + + if (unlikely(atomic_read(&bat_priv->bla.num_requests))) +- /* don't allow broadcasts while requests are in flight */ +- if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) +- goto handled; ++ /* don't allow multicast packets while requests are in flight */ ++ if (is_multicast_ether_addr(ethhdr->h_dest)) ++ /* Both broadcast flooding or multicast-via-unicasts ++ * delivery might send to multiple backbone gateways ++ * sharing the same LAN and therefore need to coordinate ++ * which backbone gateway forwards into the LAN, ++ * by claiming the payload source address. ++ * ++ * Broadcast flooding and multicast-via-unicasts ++ * delivery use the following two batman packet types. ++ * Note: explicitly exclude BATADV_UNICAST_4ADDR, ++ * as the DHCP gateway feature will send explicitly ++ * to only one BLA gateway, so the claiming process ++ * should be avoided there. ++ */ ++ if (packet_type == BATADV_BCAST || ++ packet_type == BATADV_UNICAST) ++ goto handled; + + ether_addr_copy(search_claim.addr, ethhdr->h_source); + search_claim.vid = vid; +@@ -1898,13 +1913,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, + goto allow; + } + +- /* if it is a broadcast ... */ +- if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) { ++ /* if it is a multicast ... */ ++ if (is_multicast_ether_addr(ethhdr->h_dest) && ++ (packet_type == BATADV_BCAST || packet_type == BATADV_UNICAST)) { + /* ... drop it. the responsible gateway is in charge. + * +- * We need to check is_bcast because with the gateway ++ * We need to check packet type because with the gateway + * feature, broadcasts (like DHCP requests) may be sent +- * using a unicast packet type. ++ * using a unicast 4 address packet type. See comment above. + */ + goto handled; + } else { +diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h +index 71f95a3e4d3f335890408685432f18e5d7411a76..af28fdb01467ce290c2a00d0741f01a6e4f347ee 100644 +--- a/net/batman-adv/bridge_loop_avoidance.h ++++ b/net/batman-adv/bridge_loop_avoidance.h +@@ -48,7 +48,7 @@ static inline bool batadv_bla_is_loopdetect_mac(const uint8_t *mac) + + #ifdef CONFIG_BATMAN_ADV_BLA + bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, +- unsigned short vid, bool is_bcast); ++ unsigned short vid, int packet_type); + bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, + unsigned short vid); + bool batadv_bla_is_backbone_gw(struct sk_buff *skb, +@@ -79,7 +79,7 @@ bool batadv_bla_check_claim(struct batadv_priv *bat_priv, u8 *addr, + + static inline bool batadv_bla_rx(struct batadv_priv *bat_priv, + struct sk_buff *skb, unsigned short vid, +- bool is_bcast) ++ int packet_type) + { + return false; + } +diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c +index 267f6e6c802f1a7d3eb41a0f3aa2142ca3b21414..82582abd92485b68254789fb6e2108ae5e547dd6 100644 +--- a/net/batman-adv/soft-interface.c ++++ b/net/batman-adv/soft-interface.c +@@ -425,10 +425,10 @@ void batadv_interface_rx(struct net_device *soft_iface, + struct vlan_ethhdr *vhdr; + struct ethhdr *ethhdr; + unsigned short vid; +- bool is_bcast; ++ int packet_type; + + batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data; +- is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST); ++ packet_type = batadv_bcast_packet->packet_type; + + skb_pull_rcsum(skb, hdr_size); + skb_reset_mac_header(skb); +@@ -471,7 +471,7 @@ void batadv_interface_rx(struct net_device *soft_iface, + /* Let the bridge loop avoidance check the packet. If will + * not handle it, we can safely push it up. + */ +- if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) ++ if (batadv_bla_rx(bat_priv, skb, vid, packet_type)) + goto out; + + if (orig_node) diff --git a/batman-adv/patches/0054-batman-adv-mcast-fix-duplicate-mcast-packets-from-BL.patch b/batman-adv/patches/0054-batman-adv-mcast-fix-duplicate-mcast-packets-from-BL.patch new file mode 100644 index 0000000..598150d --- /dev/null +++ b/batman-adv/patches/0054-batman-adv-mcast-fix-duplicate-mcast-packets-from-BL.patch @@ -0,0 +1,190 @@ +From: Linus Lüssing +Date: Tue, 15 Sep 2020 09:54:10 +0200 +Subject: batman-adv: mcast: fix duplicate mcast packets from BLA backbone to mesh + +Scenario: +* Multicast frame send from BLA backbone gateways (multiple nodes + with their bat0 bridged together, with BLA enabled) sharing the same + LAN to nodes in the mesh + +Issue: +* Nodes receive the frame multiple times on bat0 from the mesh, + once from each foreign BLA backbone gateway which shares the same LAN + with another + +For multicast frames via batman-adv broadcast packets coming from the +same BLA backbone but from different backbone gateways duplicates are +currently detected via a CRC history of previously received packets. + +However this CRC so far was not performed for multicast frames received +via batman-adv unicast packets. Fixing this by appyling the same check +for such packets, too. + +Room for improvements in the future: Ideally we would introduce the +possibility to not only claim a client, but a complete originator, too. +This would allow us to only send a multicast-in-unicast packet from a BLA +backbone gateway claiming the node and by that avoid potential redundant +transmissions in the first place. + +Fixes: e5cf86d30a9b ("batman-adv: add broadcast duplicate check") +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/c5cb6a670cc3070d9d5c5562f95fa75faac767ba + +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index 4dc67a0d081c06507aba87f7bec03488817791b2..4996bd7b8256557bddaf8ebe87cc606def588adf 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -1594,13 +1594,16 @@ int batadv_bla_init(struct batadv_priv *bat_priv) + } + + /** +- * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup. ++ * batadv_bla_check_duplist() - Check if a frame is in the broadcast dup. + * @bat_priv: the bat priv with all the soft interface information +- * @skb: contains the bcast_packet to be checked ++ * @skb: contains the multicast packet to be checked ++ * @payload_ptr: pointer to position inside the head buffer of the skb ++ * marking the start of the data to be CRC'ed ++ * @orig: originator mac address, NULL if unknown + * +- * check if it is on our broadcast list. Another gateway might +- * have sent the same packet because it is connected to the same backbone, +- * so we have to remove this duplicate. ++ * Check if it is on our broadcast list. Another gateway might have sent the ++ * same packet because it is connected to the same backbone, so we have to ++ * remove this duplicate. + * + * This is performed by checking the CRC, which will tell us + * with a good chance that it is the same packet. If it is furthermore +@@ -1609,19 +1612,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv) + * + * Return: true if a packet is in the duplicate list, false otherwise. + */ +-bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, +- struct sk_buff *skb) ++static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv, ++ struct sk_buff *skb, u8 *payload_ptr, ++ const u8 *orig) + { +- int i, curr; +- __be32 crc; +- struct batadv_bcast_packet *bcast_packet; + struct batadv_bcast_duplist_entry *entry; + bool ret = false; +- +- bcast_packet = (struct batadv_bcast_packet *)skb->data; ++ int i, curr; ++ __be32 crc; + + /* calculate the crc ... */ +- crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1)); ++ crc = batadv_skb_crc32(skb, payload_ptr); + + spin_lock_bh(&bat_priv->bla.bcast_duplist_lock); + +@@ -1640,8 +1641,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, + if (entry->crc != crc) + continue; + +- if (batadv_compare_eth(entry->orig, bcast_packet->orig)) +- continue; ++ /* are the originators both known and not anonymous? */ ++ if (orig && !is_zero_ether_addr(orig) && ++ !is_zero_ether_addr(entry->orig)) { ++ /* If known, check if the new frame came from ++ * the same originator: ++ * We are safe to take identical frames from the ++ * same orig, if known, as multiplications in ++ * the mesh are detected via the (orig, seqno) pair. ++ * So we can be a bit more liberal here and allow ++ * identical frames from the same orig which the source ++ * host might have sent multiple times on purpose. ++ */ ++ if (batadv_compare_eth(entry->orig, orig)) ++ continue; ++ } + + /* this entry seems to match: same crc, not too old, + * and from another gw. therefore return true to forbid it. +@@ -1657,7 +1671,14 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, + entry = &bat_priv->bla.bcast_duplist[curr]; + entry->crc = crc; + entry->entrytime = jiffies; +- ether_addr_copy(entry->orig, bcast_packet->orig); ++ ++ /* known originator */ ++ if (orig) ++ ether_addr_copy(entry->orig, orig); ++ /* anonymous originator */ ++ else ++ eth_zero_addr(entry->orig); ++ + bat_priv->bla.bcast_duplist_curr = curr; + + out: +@@ -1666,6 +1687,48 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, + return ret; + } + ++/** ++ * batadv_bla_check_ucast_duplist() - Check if a frame is in the broadcast dup. ++ * @bat_priv: the bat priv with all the soft interface information ++ * @skb: contains the multicast packet to be checked, decapsulated from a ++ * unicast_packet ++ * ++ * Check if it is on our broadcast list. Another gateway might have sent the ++ * same packet because it is connected to the same backbone, so we have to ++ * remove this duplicate. ++ * ++ * Return: true if a packet is in the duplicate list, false otherwise. ++ */ ++static bool batadv_bla_check_ucast_duplist(struct batadv_priv *bat_priv, ++ struct sk_buff *skb) ++{ ++ return batadv_bla_check_duplist(bat_priv, skb, (u8 *)skb->data, NULL); ++} ++ ++/** ++ * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup. ++ * @bat_priv: the bat priv with all the soft interface information ++ * @skb: contains the bcast_packet to be checked ++ * ++ * Check if it is on our broadcast list. Another gateway might have sent the ++ * same packet because it is connected to the same backbone, so we have to ++ * remove this duplicate. ++ * ++ * Return: true if a packet is in the duplicate list, false otherwise. ++ */ ++bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, ++ struct sk_buff *skb) ++{ ++ struct batadv_bcast_packet *bcast_packet; ++ u8 *payload_ptr; ++ ++ bcast_packet = (struct batadv_bcast_packet *)skb->data; ++ payload_ptr = (u8 *)(bcast_packet + 1); ++ ++ return batadv_bla_check_duplist(bat_priv, skb, payload_ptr, ++ bcast_packet->orig); ++} ++ + /** + * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for + * the VLAN identified by vid. +@@ -1880,6 +1943,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, + packet_type == BATADV_UNICAST) + goto handled; + ++ /* potential duplicates from foreign BLA backbone gateways via ++ * multicast-in-unicast packets ++ */ ++ if (is_multicast_ether_addr(ethhdr->h_dest) && ++ packet_type == BATADV_UNICAST && ++ batadv_bla_check_ucast_duplist(bat_priv, skb)) ++ goto handled; ++ + ether_addr_copy(search_claim.addr, ethhdr->h_source); + search_claim.vid = vid; + claim = batadv_claim_hash_find(bat_priv, &search_claim); diff --git a/bird/Makefile b/bird/Makefile index b44114e..37627c9 100644 --- a/bird/Makefile +++ b/bird/Makefile @@ -1,4 +1,4 @@ -# +# # Copyright (C) 2009-2016 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. @@ -7,12 +7,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bird -PKG_VERSION:=1.6.3 +PKG_VERSION:=1.6.8 PKG_RELEASE:=1 PKG_SOURCE:=bird-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=ftp://bird.network.cz/pub/bird -PKG_MD5SUM:=39c51cf57c3ba8b5978b2a657ffa2f647ec7f3ae643e91cf42ee5cb070cf7e7c +PKG_HASH:=6c61ab5d2ef59d2559a8735b8252b5a0238013b43e5fb8a96c5d9d06e7bc00b2 PKG_BUILD_DEPENDS:=ncurses readline PKG_MAINTAINER:=Álvaro Fernández Rojas @@ -22,19 +22,19 @@ include $(INCLUDE_DIR)/package.mk define Package/bird/Default TITLE:=The BIRD Internet Routing Daemon - URL:=http://bird.network.cz/ + URL:=https://bird.network.cz/ DEPENDS:=+libpthread endef define Package/birdc/Default TITLE:=The BIRD command-line client - URL:=http://bird.network.cz/ + URL:=https://bird.network.cz/ DEPENDS:= +libreadline +libncurses endef define Package/birdcl/Default TITLE:=The BIRD lightweight command-line client - URL:=http://bird.network.cz/ + URL:=https://bird.network.cz/ endef define Package/bird/Default/description1 diff --git a/nodogsplash/Makefile b/nodogsplash/Makefile index e6127ad..3079fd4 100644 --- a/nodogsplash/Makefile +++ b/nodogsplash/Makefile @@ -7,12 +7,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nodogsplash PKG_FIXUP:=autoreconf -PKG_VERSION:=3.2.1 -PKG_RELEASE:=2 +PKG_VERSION:=4.0.3 +PKG_RELEASE:=1 PKG_SOURCE_URL:=https://codeload.github.com/nodogsplash/nodogsplash/tar.gz/v$(PKG_VERSION)? PKG_SOURCE:=nodogsplash-$(PKG_VERSION).tar.gz -PKG_HASH:=16da76ecf7820cd8b32081237e05b24a7d2d8a9db8a47242badc7937d6cf1ae8 +PKG_HASH:=cae212fe7f3c1be8ff5a294a97ab414798f03425635407e18f069e7e4670b250 PKG_BUILD_DIR:=$(BUILD_DIR)/nodogsplash-$(PKG_VERSION) PKG_MAINTAINER:=Moritz Warning @@ -41,17 +41,26 @@ define Package/nodogsplash/description endef define Package/nodogsplash/install - $(CP) ./files/* $(1)/ $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/nodogsplash $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ndsctl $(1)/usr/bin/ $(INSTALL_DIR) $(1)/etc/nodogsplash/htdocs/images + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/usr/lib/nodogsplash $(CP) $(PKG_BUILD_DIR)/resources/splash.html $(1)/etc/nodogsplash/htdocs/ $(CP) $(PKG_BUILD_DIR)/resources/splash.css $(1)/etc/nodogsplash/htdocs/ $(CP) $(PKG_BUILD_DIR)/resources/status.html $(1)/etc/nodogsplash/htdocs/ $(CP) $(PKG_BUILD_DIR)/resources/splash.jpg $(1)/etc/nodogsplash/htdocs/images/ + $(CP) $(PKG_BUILD_DIR)/openwrt/nodogsplash/files/etc/config/nodogsplash $(1)/etc/config/ + $(CP) $(PKG_BUILD_DIR)/openwrt/nodogsplash/files/etc/init.d/nodogsplash $(1)/etc/init.d/ + $(CP) $(PKG_BUILD_DIR)/openwrt/nodogsplash/files/etc/uci-defaults/40_nodogsplash $(1)/etc/uci-defaults/ + $(CP) $(PKG_BUILD_DIR)/openwrt/nodogsplash/files/usr/lib/nodogsplash/restart.sh $(1)/usr/lib/nodogsplash/ + $(CP) $(PKG_BUILD_DIR)/forward_authentication_service/PreAuth/demo-preauth.sh $(1)/usr/lib/nodogsplash/login.sh + $(CP) $(PKG_BUILD_DIR)/forward_authentication_service/fas-aes/fas-aes.php $(1)/etc/nodogsplash/ endef define Package/nodogsplash/postrm diff --git a/nodogsplash/files/etc/config/nodogsplash b/nodogsplash/files/etc/config/nodogsplash deleted file mode 100644 index 714d9bf..0000000 --- a/nodogsplash/files/etc/config/nodogsplash +++ /dev/null @@ -1,144 +0,0 @@ - -# The options available here are an adaptation of the settings used in nodogsplash.conf. -# See https://github.com/nodogsplash/nodogsplash/blob/master/resources/nodogsplash.conf - -config nodogsplash - # Set to 0 to disable nodogsplash - option enabled 1 - - # Set to 0 to disable hook that makes nodogsplash restart when the firewall restarts. - # This hook is needed as a restart of Firewall overwrites nodogsplash iptables entries. - option fwhook_enabled '1' - - # Serve the file splash.html from this directory - option webroot '/etc/nodogsplash/htdocs' - - # Use plain configuration file - #option config '/etc/nodogsplash/nodogsplash.conf' - - # Use this option to set the device nogogsplash will bind to. - # The value may be an interface section in /etc/config/network or a device name such as br-lan. - option gatewayinterface 'br-lan' - - option gatewayname 'OpenWrt Nodogsplash' - option maxclients '250' - - # Enables debug output (0-7) - #option debuglevel '7' - - # Client timeouts in minutes - option preauthidletimeout '30' - option authidletimeout '120' - # Session Timeout is the interval after which clients are forced out (a value of 0 means never) - option sessiontimeout '1200' - - # The interval in seconds at which nodogsplash checks client timeout status - option checkinterval '600' - - # Enable BinAuth Support. - # If set, a program is called with several parameters on authentication (request) and deauthentication. - # Request for authentication: - # $ auth_client '' '' - # - # The username and password values may be empty strings and are URL encoded. - # The program is expected to output the number of seconds the client - # is to be authenticated. Zero or negative seconds will cause the authentification request - # to be rejected. The same goes for an exit code that is not 0. - # The output may contain a user specific download and upload limit in KBit/s: - # - # - # Called on authentication or deauthentication: - # $ <*auth|*deauth> - # - # "client_auth": Client authenticated via this script. - # "client_deauth": Client deauthenticated by the client via splash page. - # "idle_deauth": Client was deauthenticated because of inactivity. - # "timeout_deauth": Client was deauthenticated because the session timed out. - # "ndsctl_auth": Client was authenticated manually by the ndsctl tool. - # "ndsctl_deauth": Client was deauthenticated by the ndsctl tool. - # "shutdown_deauth": Client was deauthenticated by Nodogsplash terminating. - # - # Values session_start and session_start are in seconds since 1970 or 0 for unknown/unlimited. - # - #option binauth '/bin/myauth.sh' - - # Enable Forwarding Authentication Service (FAS) - # If set redirection is changed from splash.html to a FAS (provided by the system administrator) - # The value is the IP port number of the FAS - #option fasport '80' - - # Option: fasremoteip - # Default: GatewayAddress (the IP of NDS) - # If set, this is the remote ip address of the FAS. - #option fasremoteip '46.32.240.41' - - # Option: faspath - # Default: / - # This is the path from the FAS Web Root to the FAS login page - # (not the file system root). - #option faspath '/onboard-wifi.net/nodog/fas.php' - - # Option: fas_secure_enabled - # Default: 1 - # If set to "1", authaction and the client token are not revealed and it is the responsibility - # of the FAS to request the token from NDSCTL. - # If set to "0", the client token is sent to the FAS in clear text in the query string of the - # redirect along with authaction and redir. - #option fas_secure_enabled '0' - - # Your router may have several interfaces, and you - # probably want to keep them private from the network/gatewayinterface. - # If so, you should block the entire subnets on those interfaces, e.g.: - #list authenticated_users 'block to 192.168.0.0/16' - #list authenticated_users 'block to 10.0.0.0/8' - - # Typical ports you will probably want to open up. - #list authenticated_users 'allow tcp port 22' - #list authenticated_users 'allow tcp port 53' - #list authenticated_users 'allow udp port 53' - #list authenticated_users 'allow tcp port 80' - #list authenticated_users 'allow tcp port 443' - # Or for happy customers allow all - list authenticated_users 'allow all' - - # For preauthenticated users to resolve IP addresses in their - # initial request not using the router itself as a DNS server, - # Leave commented to help prevent DNS tunnelling - #list preauthenticated_users 'allow tcp port 53' - #list preauthenticated_users 'allow udp port 53' - - # Allow ports for SSH/Telnet/DNS/DHCP/HTTP/HTTPS - list users_to_router 'allow tcp port 22' - list users_to_router 'allow tcp port 23' - list users_to_router 'allow tcp port 53' - list users_to_router 'allow udp port 53' - list users_to_router 'allow udp port 67' - list users_to_router 'allow tcp port 80' - - # MAC addresses that are / are not allowed to access the splash page - # Value is either 'allow' or 'block'. The allowedmac or blockedmac list is used. - #option macmechanism 'allow' - #list allowedmac '00:00:C0:01:D0:0D' - #list allowedmac '00:00:C0:01:D0:1D' - #list blockedmac '00:00:C0:01:D0:2D' - - # MAC addresses that do not need to authenticate - #list trustedmac '00:00:C0:01:D0:1D' - - # Nodogsplash uses specific HEXADECIMAL values to mark packets used by iptables as a bitwise mask. - # This mask can conflict with the requirements of other packages such as mwan3, sqm etc - # Any values set here are interpreted as in hex format. - # - # List: fw_mark_authenticated - # Default: 30000 (0011|0000|0000|0000|0000 binary) - # - # List: fw_mark_trusted - # Default: 20000 (0010|0000|0000|0000|0000 binary) - # - # List: fw_mark_blocked - # Default: 10000 (0001|0000|0000|0000|0000 binary) - # - #list fw_mark_authenticated '30000' - #list fw_mark_trusted '20000' - #list fw_mark_blocked '10000' - diff --git a/nodogsplash/files/etc/init.d/nodogsplash b/nodogsplash/files/etc/init.d/nodogsplash deleted file mode 100755 index 3c3335c..0000000 --- a/nodogsplash/files/etc/init.d/nodogsplash +++ /dev/null @@ -1,200 +0,0 @@ -#!/bin/sh /etc/rc.common - -# -# Startup/shutdown script for nodogsplash captive portal -# - -START=95 -STOP=95 - -USE_PROCD=1 - -IPT=/usr/sbin/iptables -WD_DIR=/usr/bin -# -s -d 5 runs in background, with level 5 (not so verbose) messages to syslog -# -f -d 7 runs in foreground, with level 7 (verbose) debug messages to terminal -OPTIONS="-s -f -d 5" -CONFIG="" - - -addline() { - append CONFIG "$1" "$N" -} - -setup_mac_lists() { - local cfg="$1" - local macs="" - local val - - append_mac() { - append macs "$1" "," - } - - config_get val "$cfg" macmechanism - if [ -z "$val" ]; then - # Check if we have AllowedMACList or BlockedMACList defined they will be ignored - config_get val "$cfg" allowedmac - if [ -n "$val" ]; then - echo "Ignoring allowedmac - macmechanism not \"allow\"" >&2 - fi - - config_get val "$cfg" blockedmac - if [ -n "$val" ]; then - echo "Ignoring blockedmac - macmechanism not \"block\"" >&2 - fi - elif [ "$val" = "allow" ]; then - config_list_foreach "$cfg" allowedmac append_mac - addline "AllowedMACList $macs" - elif [ "$val" = "block" ]; then - config_list_foreach "$cfg" blockedmac append_mac - addline "BlockedMACList $macs" - else - echo "Invalid macmechanism '$val' - allow or block are valid." >&2 - exit 1 - fi - - macs="" - config_list_foreach "$cfg" trustedmac append_mac - if [ -n "$macs" ]; then - addline "TrustedMACList $macs" - fi -} - -setup_firewall() { - local cfg="$1" - local uci_name - local val - - append_firewall() { - addline " FirewallRule $1" - } - - for rule in authenticated-users preauthenticated-users users-to-router trusted-users trusted-users-to-router; do - # uci does not allow dashes - uci_name=${rule//-/_} - addline "FirewallRuleSet $rule {" - config_list_foreach "$cfg" "$uci_name" append_firewall - addline "}" - config_get val "$cfg" "policy_${uci_name}" - if [ -n "$val" ]; then - addline "EmptyRuleSetPolicy $rule $val" - fi - done -} - -wait_for_interface() { - local ifname="$1" - local timeout=10 - - for i in $(seq $timeout); do - if [ $(ip -4 addr show dev $ifname 2> /dev/null | grep -c inet) -ne 0 ]; then - break - fi - sleep 1 - if [ $i = $timeout ]; then - echo "Interface $ifname not detected." >&2 - exit 1 - fi - done -} - -generate_uci_config() { - local cfg="$1" - local val - local ifname - local download - local upload - - # Init config file content - CONFIG="# auto-generated config file from /etc/config/nodogsplash" - - config_get val "$cfg" config - if [ -n "$val" ]; then - if [ ! -f "$val" ]; then - echo "Configuration file '$file' doesn't exist." >&2 - exit 1 - fi - addline "$(cat $val)" - fi - - config_get ifname "$cfg" gatewayinterface - if [ -z "$ifname" ]; then - config_get ifname "$cfg" network - fi - - # Get device name if interface name is a section name in /etc/config/network - if network_get_device tmp "$ifname"; then - ifname="$tmp" - fi - - if [ -z "$ifname" ]; then - echo "Option network or gatewayinterface missing." >&2 - exit 1 - fi - - wait_for_interface "$ifname" - - addline "GatewayInterface $ifname" - - for option in binauth fasport fasremoteip faspath fas_secure_enabled \ - daemon debuglevel maxclients gatewayname gatewayinterface gatewayiprange \ - gatewayaddress gatewayport webroot splashpage statuspage imagesdir pagesdir \ - redirecturl sessiontimeout preauthidletimeout authidletimeout checkinterval \ - setmss mssvalue trafficcontrol downloadlimit uploadlimit \ - syslogfacility ndsctlsocket fw_mark_authenticated \ - fw_mark_blocked fw_mark_trusted - do - config_get val "$cfg" "$option" - - if [ -n "$val" ]; then - addline "$option $val" - fi - done - - config_get download "$cfg" downloadlimit - config_get upload "$cfg" uploadlimit - - if [ -n "$upload" -o -n "$download" ]; then - addline "TrafficControl yes" - fi - - setup_mac_lists "$cfg" - setup_firewall "$cfg" - - echo "$CONFIG" > "/tmp/etc/nodogsplash_$cfg.conf" -} - -# setup configuration and start instance -create_instance() { - local cfg="$1" - local val - - config_get_bool val "$cfg" enabled 0 - [ $val -gt 0 ] || return 0 - - generate_uci_config "$cfg" - - procd_open_instance $cfg - procd_set_param command /usr/bin/nodogsplash -c "/tmp/etc/nodogsplash_$cfg.conf" $OPTIONS - procd_set_param respawn - procd_set_param file "/tmp/etc/nodogsplash_$cfg.conf" - procd_close_instance -} - -start_service() { - # For network_get_device() - include /lib/functions - - # For nodogsplash.conf file - mkdir -p /tmp/etc/ - - config_load nodogsplash - config_foreach create_instance nodogsplash -} - -stop_service() { - # When procd terminates nodogsplash, it does not exit fast enough. - # Otherwise procd will restart nodogsplash twice. First time starting - # nodogsplash fails, second time it succeeds. - sleep 1 -} diff --git a/nodogsplash/files/etc/uci-defaults/40_nodogsplash b/nodogsplash/files/etc/uci-defaults/40_nodogsplash deleted file mode 100644 index c4f461a..0000000 --- a/nodogsplash/files/etc/uci-defaults/40_nodogsplash +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF - delete firewall.nodogsplash - set firewall.nodogsplash=include - set firewall.nodogsplash.type=script - set firewall.nodogsplash.path=/usr/lib/nodogsplash/restart.sh - commit firewall -EOF diff --git a/nodogsplash/files/usr/lib/nodogsplash/restart.sh b/nodogsplash/files/usr/lib/nodogsplash/restart.sh deleted file mode 100755 index e67f11d..0000000 --- a/nodogsplash/files/usr/lib/nodogsplash/restart.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -# Check if nodogsplash is running -if ndsctl status &> /dev/null; then - if [ "$(uci -q get nodogsplash.@nodogsplash[0].fwhook_enabled)" = "1" ]; then - /etc/init.d/nodogsplash restart - fi -fi diff --git a/nodogsplash/patches/0001-fix-invalid-pointer-when-clock-is-turned-back.patch b/nodogsplash/patches/0001-fix-invalid-pointer-when-clock-is-turned-back.patch deleted file mode 100644 index 9ea55d0..0000000 --- a/nodogsplash/patches/0001-fix-invalid-pointer-when-clock-is-turned-back.patch +++ /dev/null @@ -1,51 +0,0 @@ -From af548c1f885e46309baa6aa175a3822fd16afb2a Mon Sep 17 00:00:00 2001 -From: Moritz Warning -Date: Thu, 14 Mar 2019 17:19:40 +0100 -Subject: [PATCH] fix invalid pointer when clock is turned back - ---- - src/util.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/util.c b/src/util.c -index 621062d..77228bf 100644 ---- a/src/util.c -+++ b/src/util.c -@@ -362,14 +362,14 @@ format_duration(time_t from, time_t to, char buf[64]) - { - int days, hours, minutes, seconds; - long long int secs; -+ const char *neg = ""; - - if (from <= to) { - secs = to - from; - } else { - secs = from - to; - // Prepend minus sign -- buf[0] = '-'; -- buf += 1; -+ neg = "-"; - } - - days = secs / (24 * 60 * 60); -@@ -381,13 +381,13 @@ format_duration(time_t from, time_t to, char buf[64]) - seconds = secs; - - if (days > 0) { -- sprintf(buf, "%dd %dh %dm %ds", days, hours, minutes, seconds); -+ snprintf(buf, 64, "%s%dd %dh %dm %ds", neg, days, hours, minutes, seconds); - } else if (hours > 0) { -- sprintf(buf, "%dh %dm %ds", hours, minutes, seconds); -+ snprintf(buf, 64, "%s%dh %dm %ds", neg, hours, minutes, seconds); - } else if (minutes > 0) { -- sprintf(buf, "%dm %ds", minutes, seconds); -+ snprintf(buf, 64, "%s%dm %ds", neg, minutes, seconds); - } else { -- sprintf(buf, "%ds", seconds); -+ snprintf(buf, 64, "%s%ds", neg, seconds); - } - - return buf; --- -2.20.1 - diff --git a/pimbd/Makefile b/pimbd/Makefile index 9f97107..a091119 100644 --- a/pimbd/Makefile +++ b/pimbd/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=pimbd -PKG_SOURCE_VERSION:=68f5fc803119e4b33a88b35c096f4d6ac28b6de5 -PKG_VERSION:=2015-08-18-$(PKG_SOURCE_VERSION) +PKG_SOURCE_VERSION:=dbf4e5913b06e3160f506df15e6a047a403a5f21 +PKG_VERSION:=2018-06-19-$(PKG_SOURCE_VERSION) PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git @@ -17,7 +17,8 @@ include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/cmake.mk # Spammy debug builds for now -CMAKE_OPTIONS += -DL_LEVEL=7 +CMAKE_OPTIONS += -DL_LEVEL=7 \ + -DWITH_LIBUBOX=1 define Package/pimbd SECTION:=net diff --git a/quagga/Makefile b/quagga/Makefile index f8963e0..5681a5b 100644 --- a/quagga/Makefile +++ b/quagga/Makefile @@ -8,12 +8,21 @@ include $(TOPDIR)/rules.mk PKG_NAME:=quagga -PKG_VERSION:=1.1.0 +PKG_VERSION:=1.1.1 PKG_RELEASE:=1 -PKG_MD5SUM:=daa303871e07ea5856aae6fd79e89722 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=http://download.savannah.gnu.org/releases/quagga/ +PKG_SOURCE_URL:=https://download.savannah.gnu.org/releases/quagga/ +PKG_HASH:=b5a94e5bdad3062e04595a5692b8cc435f0a85102f75dfdca0a06d093b4ef63f + +PKG_MAINTAINER:=Vasilis Tsiligiannis +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING + +PKG_BUILD_PARALLEL:=1 +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + PKG_CONFIG_DEPENDS:= \ CONFIG_IPV6 \ CONFIG_PACKAGE_quagga-watchquagga \ @@ -26,10 +35,6 @@ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_quagga-ripd \ CONFIG_PACKAGE_quagga-ripngd \ CONFIG_PACKAGE_quagga-vtysh -PKG_BUILD_PARALLEL:=1 -PKG_FIXUP:=autoreconf -PKG_INSTALL:=1 -PKG_LICENSE:=GPL-2.0 include $(INCLUDE_DIR)/package.mk @@ -37,10 +42,9 @@ define Package/quagga/Default SECTION:=net CATEGORY:=Network SUBMENU:=Routing and Redirection - DEPENDS:=quagga TITLE:=The Quagga Software Routing Suite - URL:=http://www.quagga.net - MAINTAINER:=Vasilis Tsiligiannis + URL:=https://www.quagga.net + DEPENDS:=quagga endef define Package/quagga diff --git a/quagga/patches/001-bgpd-Fix-AS_PATH-size-calculation-for-long-paths.patch b/quagga/patches/001-bgpd-Fix-AS_PATH-size-calculation-for-long-paths.patch new file mode 100644 index 0000000..3ecbc0e --- /dev/null +++ b/quagga/patches/001-bgpd-Fix-AS_PATH-size-calculation-for-long-paths.patch @@ -0,0 +1,28 @@ +From: Andreas Jaggi +Date: Mon, 2 Oct 2017 19:38:43 +0530 +Subject: bgpd: Fix AS_PATH size calculation for long paths +Origin: http://git.savannah.gnu.org/cgit/quagga.git/commit?id=7a42b78be9a4108d98833069a88e6fddb9285008 +Bug-Debian: https://bugs.debian.org/879474 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-16227 + +If you have an AS_PATH with more entries than +what can be written into a single AS_SEGMENT_MAX +it needs to be broken up. The code that noticed +that the AS_PATH needs to be broken up was not +correctly calculating the size of the resulting +message. This patch addresses this issue. +--- + bgpd/bgp_aspath.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/bgpd/bgp_aspath.c ++++ b/bgpd/bgp_aspath.c +@@ -903,7 +903,7 @@ aspath_put (struct stream *s, struct asp + assegment_header_put (s, seg->type, AS_SEGMENT_MAX); + assegment_data_put (s, seg->as, AS_SEGMENT_MAX, use32bit); + written += AS_SEGMENT_MAX; +- bytes += ASSEGMENT_SIZE (written, use32bit); ++ bytes += ASSEGMENT_SIZE (AS_SEGMENT_MAX, use32bit); + } + + /* write the final segment, probably is also the first */ diff --git a/quagga/patches/002-Quagga-2018-0543.patch b/quagga/patches/002-Quagga-2018-0543.patch new file mode 100644 index 0000000..1f77143 --- /dev/null +++ b/quagga/patches/002-Quagga-2018-0543.patch @@ -0,0 +1,58 @@ +From cc2e6770697e343f4af534114ab7e633d5beabec Mon Sep 17 00:00:00 2001 +From: Paul Jakma +Date: Wed, 3 Jan 2018 23:57:33 +0000 +Subject: bgpd/security: invalid attr length sends NOTIFY with data overrun + +Security issue: Quagga-2018-0543 + +See: https://www.quagga.net/security/Quagga-2018-0543.txt + +* bgpd/bgp_attr.c: (bgp_attr_parse) An invalid attribute length is correctly + checked, and a NOTIFY prepared. The NOTIFY can include the incorrect + received data with the NOTIFY, for debug purposes. Commit + c69698704806a9ac5 modified the code to do that just, and also send the + malformed attr with the NOTIFY. However, the invalid attribute length was + used as the length of the data to send back. + + The result is a read past the end of data, which is then written to the + NOTIFY message and sent to the peer. + + A configured BGP peer can use this bug to read up to 64 KiB of memory from + the bgpd process, or crash the process if the invalid read is caught by + some means (unmapped page and SEGV, or other mechanism) resulting in a DoS. + + This bug _ought_ /not/ be exploitable by anything other than the connected + BGP peer, assuming the underlying TCP transport is secure. For no BGP + peer should send on an UPDATE with this attribute. Quagga will not, as + Quagga always validates the attr header length, regardless of type. + + However, it is possible that there are BGP implementations that do not + check lengths on some attributes (e.g. optional/transitive ones of a type + they do not recognise), and might pass such malformed attrs on. If such + implementations exists and are common, then this bug might be triggerable + by BGP speakers further hops away. Those peers will not receive the + NOTIFY (unless they sit on a shared medium), however they might then be + able to trigger a DoS. + + Fix: use the valid bound to calculate the length. + +--- a/bgpd/bgp_attr.c ++++ b/bgpd/bgp_attr.c +@@ -2079,6 +2079,8 @@ bgp_attr_parse (struct peer *peer, struc + memset (seen, 0, BGP_ATTR_BITMAP_SIZE); + + /* End pointer of BGP attribute. */ ++ assert (size <= stream_get_size (BGP_INPUT (peer))); ++ assert (size <= stream_get_endp (BGP_INPUT (peer))); + endp = BGP_INPUT_PNT (peer) + size; + + /* Get attributes to the end of attribute length. */ +@@ -2160,7 +2162,7 @@ bgp_attr_parse (struct peer *peer, struc + bgp_notify_send_with_data (peer, + BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, +- startp, attr_endp - startp); ++ startp, endp - startp); + return BGP_ATTR_PARSE_ERROR; + } + diff --git a/quagga/patches/003-Quagga-2018-1114.patch b/quagga/patches/003-Quagga-2018-1114.patch new file mode 100644 index 0000000..a4b91c5 --- /dev/null +++ b/quagga/patches/003-Quagga-2018-1114.patch @@ -0,0 +1,99 @@ +From e69b535f92eafb599329bf725d9b4c6fd5d7fded Mon Sep 17 00:00:00 2001 +From: Paul Jakma +Date: Sat, 6 Jan 2018 19:52:10 +0000 +Subject: bgpd/security: Fix double free of unknown attribute + +Security issue: Quagga-2018-1114 +See: https://www.quagga.net/security/Quagga-2018-1114.txt + +It is possible for bgpd to double-free an unknown attribute. This can happen +via bgp_update_receive receiving an UPDATE with an invalid unknown attribute. +bgp_update_receive then will call bgp_attr_unintern_sub and bgp_attr_flush, +and the latter may try free an already freed unknown attr. + +* bgpd/bgp_attr.c: (transit_unintern) Take a pointer to the caller's storage + for the (struct transit *), so that transit_unintern can NULL out the + caller's reference if the (struct transit) is freed. + (cluster_unintern) By inspection, appears to have a similar issue. + (bgp_attr_unintern_sub) adjust for above. + +--- a/bgpd/bgp_attr.c ++++ b/bgpd/bgp_attr.c +@@ -186,15 +186,17 @@ cluster_intern (struct cluster_list *clu + } + + void +-cluster_unintern (struct cluster_list *cluster) ++cluster_unintern (struct cluster_list **cluster) + { +- if (cluster->refcnt) +- cluster->refcnt--; ++ struct cluster_list *c = *cluster; ++ if (c->refcnt) ++ c->refcnt--; + +- if (cluster->refcnt == 0) ++ if (c->refcnt == 0) + { +- hash_release (cluster_hash, cluster); +- cluster_free (cluster); ++ hash_release (cluster_hash, c); ++ cluster_free (c); ++ *cluster = NULL; + } + } + +@@ -344,15 +346,18 @@ transit_intern (struct transit *transit) + } + + void +-transit_unintern (struct transit *transit) ++transit_unintern (struct transit **transit) + { +- if (transit->refcnt) +- transit->refcnt--; ++ struct transit *t = *transit; ++ ++ if (t->refcnt) ++ t->refcnt--; + +- if (transit->refcnt == 0) ++ if (t->refcnt == 0) + { +- hash_release (transit_hash, transit); +- transit_free (transit); ++ hash_release (transit_hash, t); ++ transit_free (t); ++ *transit = NULL; + } + } + +@@ -793,11 +798,11 @@ bgp_attr_unintern_sub (struct attr *attr + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)); + + if (attr->extra->cluster) +- cluster_unintern (attr->extra->cluster); ++ cluster_unintern (&attr->extra->cluster); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST)); + + if (attr->extra->transit) +- transit_unintern (attr->extra->transit); ++ transit_unintern (&attr->extra->transit); + } + } + +--- a/bgpd/bgp_attr.h ++++ b/bgpd/bgp_attr.h +@@ -184,10 +184,10 @@ extern unsigned long int attr_unknown_co + + /* Cluster list prototypes. */ + extern int cluster_loop_check (struct cluster_list *, struct in_addr); +-extern void cluster_unintern (struct cluster_list *); ++extern void cluster_unintern (struct cluster_list **); + + /* Transit attribute prototypes. */ +-void transit_unintern (struct transit *); ++void transit_unintern (struct transit **); + + /* Below exported for unit-test purposes only */ + struct bgp_attr_parser_args { diff --git a/quagga/patches/004-Quagga-2018-1550.patch b/quagga/patches/004-Quagga-2018-1550.patch new file mode 100644 index 0000000..4bd3da8 --- /dev/null +++ b/quagga/patches/004-Quagga-2018-1550.patch @@ -0,0 +1,104 @@ +From 9e5251151894aefdf8e9392a2371615222119ad8 Mon Sep 17 00:00:00 2001 +From: Paul Jakma +Date: Sat, 6 Jan 2018 22:31:52 +0000 +Subject: bgpd/security: debug print of received NOTIFY data can over-read msg + array + +Security issue: Quagga-2018-1550 +See: https://www.quagga.net/security/Quagga-2018-1550.txt + +* bgpd/bgp_debug.c: (struct message) Nearly every one of the NOTIFY + code/subcode message arrays has their corresponding size variables off + by one, as most have 1 as first index. + + This means (bgp_notify_print) can cause mes_lookup to overread the (struct + message) by 1 pointer value if given an unknown index. + + Fix the bgp_notify_..._msg_max variables to use the compiler to calculate + the correct sizes. + +--- a/bgpd/bgp_debug.c ++++ b/bgpd/bgp_debug.c +@@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Pla + #include "log.h" + #include "sockunion.h" + #include "filter.h" ++#include "memory.h" + + #include "bgpd/bgpd.h" + #include "bgpd/bgp_aspath.h" +@@ -73,7 +74,8 @@ const struct message bgp_status_msg[] = + { Clearing, "Clearing" }, + { Deleted, "Deleted" }, + }; +-const int bgp_status_msg_max = BGP_STATUS_MAX; ++#define BGP_DEBUG_MSG_MAX(msg) const int msg ## _max = array_size (msg) ++BGP_DEBUG_MSG_MAX (bgp_status_msg); + + /* BGP message type string. */ + const char *bgp_type_str[] = +@@ -84,7 +86,8 @@ const char *bgp_type_str[] = + "NOTIFICATION", + "KEEPALIVE", + "ROUTE-REFRESH", +- "CAPABILITY" ++ "CAPABILITY", ++ NULL, + }; + + /* message for BGP-4 Notify */ +@@ -98,15 +101,15 @@ static const struct message bgp_notify_m + { BGP_NOTIFY_CEASE, "Cease"}, + { BGP_NOTIFY_CAPABILITY_ERR, "CAPABILITY Message Error"}, + }; +-static const int bgp_notify_msg_max = BGP_NOTIFY_MAX; ++BGP_DEBUG_MSG_MAX (bgp_notify_msg); + + static const struct message bgp_notify_head_msg[] = + { + { BGP_NOTIFY_HEADER_NOT_SYNC, "/Connection Not Synchronized"}, + { BGP_NOTIFY_HEADER_BAD_MESLEN, "/Bad Message Length"}, +- { BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type"} ++ { BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type"}, + }; +-static const int bgp_notify_head_msg_max = BGP_NOTIFY_HEADER_MAX; ++BGP_DEBUG_MSG_MAX (bgp_notify_head_msg); + + static const struct message bgp_notify_open_msg[] = + { +@@ -119,7 +122,7 @@ static const struct message bgp_notify_o + { BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, "/Unacceptable Hold Time"}, + { BGP_NOTIFY_OPEN_UNSUP_CAPBL, "/Unsupported Capability"}, + }; +-static const int bgp_notify_open_msg_max = BGP_NOTIFY_OPEN_MAX; ++BGP_DEBUG_MSG_MAX (bgp_notify_open_msg); + + static const struct message bgp_notify_update_msg[] = + { +@@ -136,7 +139,7 @@ static const struct message bgp_notify_u + { BGP_NOTIFY_UPDATE_INVAL_NETWORK, "/Invalid Network Field"}, + { BGP_NOTIFY_UPDATE_MAL_AS_PATH, "/Malformed AS_PATH"}, + }; +-static const int bgp_notify_update_msg_max = BGP_NOTIFY_UPDATE_MAX; ++BGP_DEBUG_MSG_MAX (bgp_notify_update_msg); + + static const struct message bgp_notify_cease_msg[] = + { +@@ -150,7 +153,7 @@ static const struct message bgp_notify_c + { BGP_NOTIFY_CEASE_COLLISION_RESOLUTION, "/Connection collision resolution"}, + { BGP_NOTIFY_CEASE_OUT_OF_RESOURCE, "/Out of Resource"}, + }; +-static const int bgp_notify_cease_msg_max = BGP_NOTIFY_CEASE_MAX; ++BGP_DEBUG_MSG_MAX (bgp_notify_cease_msg); + + static const struct message bgp_notify_capability_msg[] = + { +@@ -159,7 +162,7 @@ static const struct message bgp_notify_c + { BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length"}, + { BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"}, + }; +-static const int bgp_notify_capability_msg_max = BGP_NOTIFY_CAPABILITY_MAX; ++BGP_DEBUG_MSG_MAX (bgp_notify_capability_msg); + + /* Origin strings. */ + const char *bgp_origin_str[] = {"i","e","?"}; diff --git a/quagga/patches/005-Quagga-2018-1975.patch b/quagga/patches/005-Quagga-2018-1975.patch new file mode 100644 index 0000000..5e0c6ee --- /dev/null +++ b/quagga/patches/005-Quagga-2018-1975.patch @@ -0,0 +1,32 @@ +From ce07207c50a3d1f05d6dd49b5294282e59749787 Mon Sep 17 00:00:00 2001 +From: Paul Jakma +Date: Sat, 6 Jan 2018 21:20:51 +0000 +Subject: bgpd/security: fix infinite loop on certain invalid OPEN messages + +Security issue: Quagga-2018-1975 +See: https://www.quagga.net/security/Quagga-2018-1975.txt + +* bgpd/bgp_packet.c: (bgp_capability_msg_parse) capability parser can infinite + loop due to checks that issue 'continue' without bumping the input + pointer. + +--- a/bgpd/bgp_packet.c ++++ b/bgpd/bgp_packet.c +@@ -2251,7 +2251,8 @@ bgp_capability_msg_parse (struct peer *p + + end = pnt + length; + +- while (pnt < end) ++ /* XXX: Streamify this */ ++ for (; pnt < end; pnt += hdr->length + 3) + { + /* We need at least action, capability code and capability length. */ + if (pnt + 3 > end) +@@ -2339,7 +2340,6 @@ bgp_capability_msg_parse (struct peer *p + zlog_warn ("%s unrecognized capability code: %d - ignored", + peer->host, hdr->code); + } +- pnt += hdr->length + 3; + } + return 0; + } diff --git a/quagga/patches/150-no-cross-fs-link.patch b/quagga/patches/150-no-cross-fs-link.patch index 8445103..18078bc 100644 --- a/quagga/patches/150-no-cross-fs-link.patch +++ b/quagga/patches/150-no-cross-fs-link.patch @@ -1,6 +1,6 @@ --- a/lib/command.c +++ b/lib/command.c -@@ -3198,6 +3198,13 @@ DEFUN (config_write_file, +@@ -3200,6 +3200,13 @@ DEFUN (config_write_file, VTY_NEWLINE); goto finished; } @@ -14,7 +14,7 @@ if (link (config_file, config_file_sav) != 0) { vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav, -@@ -3211,7 +3218,23 @@ DEFUN (config_write_file, +@@ -3213,7 +3220,23 @@ DEFUN (config_write_file, VTY_NEWLINE); goto finished; }