From: Sven Eckelmann Date: Fri, 13 Dec 2019 21:11:22 +0000 (+0100) Subject: batman-adv: Merge bugfixes from 2019.5 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=0d22982f3067652e3e3d98bc5a8380ed409bc2fc;p=feed%2Frouting.git batman-adv: Merge bugfixes from 2019.5 * fix DAT candidate selection on little endian systems Signed-off-by: Sven Eckelmann --- diff --git a/batman-adv/Makefile b/batman-adv/Makefile index ae43490..20bcf0a 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:=8 +PKG_RELEASE:=9 PKG_HASH:=b866b28dbbe5c9238abbdf5abbc30fc526dea56898ce4c1bd76d5c017843048b PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz diff --git a/batman-adv/patches/0010-batman-adv-fix-uninit-value-in-batadv_netlink_get_if.patch b/batman-adv/patches/0010-batman-adv-fix-uninit-value-in-batadv_netlink_get_if.patch deleted file mode 100644 index 3b49860..0000000 --- a/batman-adv/patches/0010-batman-adv-fix-uninit-value-in-batadv_netlink_get_if.patch +++ /dev/null @@ -1,58 +0,0 @@ -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/0011-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch b/batman-adv/patches/0011-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch deleted file mode 100644 index 6ba3239..0000000 --- a/batman-adv/patches/0011-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch +++ /dev/null @@ -1,74 +0,0 @@ -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 73bf6a93a3cf1141a34657bf1284893199e04db9..3db8a0278046c0a9f4d2604f0067ba4efe3ef588 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/0012-batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch b/batman-adv/patches/0012-batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch deleted file mode 100644 index 81c0fef..0000000 --- a/batman-adv/patches/0012-batman-adv-Only-read-OGM2-tvlv_len-after-buffer-len-.patch +++ /dev/null @@ -1,62 +0,0 @@ -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/0013-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch b/batman-adv/patches/0013-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch deleted file mode 100644 index ff4866f..0000000 --- a/batman-adv/patches/0013-batman-adv-Avoid-free-alloc-race-when-handling-OGM2-.patch +++ /dev/null @@ -1,119 +0,0 @@ -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 476b052ad9824d4cbcd6218dce40b603e3400fd2..8eaec92aff8919f0c6ca6b05be22e592b7ae0e1a 100644 ---- a/net/batman-adv/types.h -+++ b/net/batman-adv/types.h -@@ -1474,10 +1474,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/0014-batman-adv-Avoid-free-alloc-race-when-handling-OGM-b.patch b/batman-adv/patches/0014-batman-adv-Avoid-free-alloc-race-when-handling-OGM-b.patch deleted file mode 100644 index d07d693..0000000 --- a/batman-adv/patches/0014-batman-adv-Avoid-free-alloc-race-when-handling-OGM-b.patch +++ /dev/null @@ -1,136 +0,0 @@ -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 3db8a0278046c0a9f4d2604f0067ba4efe3ef588..cb27949f4086643ebd018a0a01ab0b848ce5123f 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 8eaec92aff8919f0c6ca6b05be22e592b7ae0e1a..d43f1ec4532d1fda1d50061e581f4770a6037739 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/0015-batman-adv-Introduce-own-OGM2-buffer-mutex.patch b/batman-adv/patches/0015-batman-adv-Introduce-own-OGM2-buffer-mutex.patch deleted file mode 100644 index afe1853..0000000 --- a/batman-adv/patches/0015-batman-adv-Introduce-own-OGM2-buffer-mutex.patch +++ /dev/null @@ -1,138 +0,0 @@ -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 d43f1ec4532d1fda1d50061e581f4770a6037739..05542a32f8c9c00b9d0cd7dbbab60cb773724613 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 */ -@@ -1474,15 +1475,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/0016-batman-adv-Avoid-OGM-workqueue-synchronous-cancel-de.patch b/batman-adv/patches/0016-batman-adv-Avoid-OGM-workqueue-synchronous-cancel-de.patch deleted file mode 100644 index 9dc85a7..0000000 --- a/batman-adv/patches/0016-batman-adv-Avoid-OGM-workqueue-synchronous-cancel-de.patch +++ /dev/null @@ -1,262 +0,0 @@ -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 cb27949f4086643ebd018a0a01ab0b848ce5123f..b87bf2e511e0cd702a94594b8ddfe107ee17cef2 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 2f0d42f2f913e74cf10c0c6ce89320434994cac5..48123e9e3a6d221a9033bc2949e19a306e973546 100644 ---- a/net/batman-adv/hard-interface.c -+++ b/net/batman-adv/hard-interface.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -929,6 +930,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 05542a32f8c9c00b9d0cd7dbbab60cb773724613..c843a69677d1e0eefaf6a1432541052b7cd2965a 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/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);