From 22cdd1d78ea257a0c70a08bf301315f9fecd6f60 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 16 Mar 2018 19:52:36 +0100 Subject: [PATCH] batman-adv: add pending patches Fixes checksum failures on TT version updates. Fixes #1321 --- .../0004-batman-adv-add-pending-patches.patch | 484 ++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100644 patches/packages/routing/0004-batman-adv-add-pending-patches.patch diff --git a/patches/packages/routing/0004-batman-adv-add-pending-patches.patch b/patches/packages/routing/0004-batman-adv-add-pending-patches.patch new file mode 100644 index 00000000..caded3b0 --- /dev/null +++ b/patches/packages/routing/0004-batman-adv-add-pending-patches.patch @@ -0,0 +1,484 @@ +From: Matthias Schiffer +Date: Fri, 16 Mar 2018 19:46:36 +0100 +Subject: batman-adv: add pending patches + +Fixes checksum failures on TT version updates. + +diff --git a/batman-adv/patches/1001-batman-adv-update-data-pointers-after-skb_cow.patch b/batman-adv/patches/1001-batman-adv-update-data-pointers-after-skb_cow.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..eee1714d2526b8e989504139cc9eae79a6999436 +--- /dev/null ++++ b/batman-adv/patches/1001-batman-adv-update-data-pointers-after-skb_cow.patch +@@ -0,0 +1,62 @@ ++From b512c268fbe9f9d61eadc579457d6b825fcf3638 Mon Sep 17 00:00:00 2001 ++Message-Id: ++From: Matthias Schiffer ++Date: Wed, 14 Mar 2018 18:14:27 +0100 ++Subject: [PATCH 1001/1003] batman-adv: update data pointers after skb_cow() ++ ++batadv_check_unicast_ttvn() calls skb_cow(), so pointers into the SKB data ++must be (re)set after calling it. The ethhdr variable is dropped ++altogether. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ net/batman-adv/routing.c | 10 +++++----- ++ 1 file changed, 5 insertions(+), 5 deletions(-) ++ ++diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c ++index 289df027ecdd..0f10c565ac85 100644 ++--- a/net/batman-adv/routing.c +++++ b/net/batman-adv/routing.c ++@@ -968,14 +968,10 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ struct batadv_orig_node *orig_node = NULL, *orig_node_gw = NULL; ++ int check, hdr_size = sizeof(*unicast_packet); ++ enum batadv_subtype subtype; ++- struct ethhdr *ethhdr; ++ int ret = NET_RX_DROP; ++ bool is4addr, is_gw; ++ ++ unicast_packet = (struct batadv_unicast_packet *)skb->data; ++- unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; ++- ethhdr = eth_hdr(skb); ++- ++ is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR; ++ /* the caller function should have already pulled 2 bytes */ ++ if (is4addr) ++@@ -995,12 +991,14 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size)) ++ goto free_skb; ++ +++ unicast_packet = (struct batadv_unicast_packet *)skb->data; +++ ++ /* packet for me */ ++ if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) { ++ /* If this is a unicast packet from another backgone gw, ++ * drop it. ++ */ ++- orig_addr_gw = ethhdr->h_source; +++ orig_addr_gw = eth_hdr(skb)->h_source; ++ orig_node_gw = batadv_orig_hash_find(bat_priv, orig_addr_gw); ++ if (orig_node_gw) { ++ is_gw = batadv_bla_is_backbone_gw(skb, orig_node_gw, ++@@ -1015,6 +1013,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ } ++ ++ if (is4addr) { +++ unicast_4addr_packet = +++ (struct batadv_unicast_4addr_packet *)skb->data; ++ subtype = unicast_4addr_packet->subtype; ++ batadv_dat_inc_counter(bat_priv, subtype); ++ ++-- ++2.16.2 ++ +diff --git a/batman-adv/patches/1002-batman-adv-fix-header-size-check-in-batadv_dbg_arp.patch b/batman-adv/patches/1002-batman-adv-fix-header-size-check-in-batadv_dbg_arp.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..efb0a00f5cf0f9f43a1147ab380c4a4e2a122a54 +--- /dev/null ++++ b/batman-adv/patches/1002-batman-adv-fix-header-size-check-in-batadv_dbg_arp.patch +@@ -0,0 +1,34 @@ ++From 3cc8fb9bb6b983a5b7972af2fd803041095d8c90 Mon Sep 17 00:00:00 2001 ++Message-Id: <3cc8fb9bb6b983a5b7972af2fd803041095d8c90.1521225964.git.mschiffer@universe-factory.net> ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Thu, 15 Mar 2018 12:41:56 +0100 ++Subject: [PATCH 1002/1003] batman-adv: fix header size check in ++ batadv_dbg_arp() ++ ++Checking for 0 is insufficient: when an SKB without a batadv header, but ++with a VLAN header is received, hdr_size will be 4, making the following ++code interpret the Ethernet header as a batadv header. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ net/batman-adv/distributed-arp-table.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c ++index 19b15de455ab..b7ca4a311b91 100644 ++--- a/net/batman-adv/distributed-arp-table.c +++++ b/net/batman-adv/distributed-arp-table.c ++@@ -393,7 +393,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, ++ batadv_arp_hw_src(skb, hdr_size), &ip_src, ++ batadv_arp_hw_dst(skb, hdr_size), &ip_dst); ++ ++- if (hdr_size == 0) +++ if (hdr_size < sizeof(struct batadv_unicast_packet)) ++ return; ++ ++ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; ++-- ++2.16.2 ++ +diff --git a/batman-adv/patches/1003-batman-adv-do-not-modify-batadv-packet-header-before.patch b/batman-adv/patches/1003-batman-adv-do-not-modify-batadv-packet-header-before.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..e5420db8bff08b25b05dc6a166dc7d745493492a +--- /dev/null ++++ b/batman-adv/patches/1003-batman-adv-do-not-modify-batadv-packet-header-before.patch +@@ -0,0 +1,178 @@ ++From c09f296ac6e85467147096e656d12ddf05713216 Mon Sep 17 00:00:00 2001 ++Message-Id: ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Thu, 15 Mar 2018 13:16:56 +0100 ++Subject: [PATCH 1003/1003] batman-adv: do not modify batadv packet header ++ before pulling it ++ ++batadv_check_unicast_ttvn() may modify the batadv header, leading to ++checksum errors in the following processing of the packet. ++ ++Rather than fixing up the checksum, simply pull the batadv header before ++modifying it (and push it back in case the packet is rerouted). ++ ++Signed-off-by: Matthias Schiffer ++--- ++ net/batman-adv/routing.c | 38 +++++++++++++++++++++----------------- ++ net/batman-adv/soft-interface.c | 10 ++-------- ++ net/batman-adv/soft-interface.h | 2 +- ++ 3 files changed, 24 insertions(+), 26 deletions(-) ++ ++diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c ++index 0f10c565ac85..37b87fce685b 100644 ++--- a/net/batman-adv/routing.c +++++ b/net/batman-adv/routing.c ++@@ -824,16 +824,16 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, ++ int is_old_ttvn; ++ ++ /* check if there is enough data before accessing it */ ++- if (!pskb_may_pull(skb, hdr_len + ETH_HLEN)) +++ if (!pskb_may_pull(skb, ETH_HLEN)) ++ return false; ++ ++ /* create a copy of the skb (in case of for re-routing) to modify it. */ ++- if (skb_cow(skb, sizeof(*unicast_packet)) < 0) +++ if (skb_cow_head(skb, ETH_HLEN + hdr_len) < 0) ++ return false; ++ ++- unicast_packet = (struct batadv_unicast_packet *)skb->data; ++- vid = batadv_get_vid(skb, hdr_len); ++- ethhdr = (struct ethhdr *)(skb->data + hdr_len); +++ unicast_packet = (struct batadv_unicast_packet *)(skb->data - hdr_len); +++ vid = batadv_get_vid(skb, 0); +++ ethhdr = (struct ethhdr *)skb->data; ++ ++ /* 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 ++@@ -985,13 +985,16 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ */ ++ if (check == -EREMOTE) ++ batadv_nc_skb_store_sniffed_unicast(bat_priv, skb); ++- ++ if (check < 0) ++ goto free_skb; +++ +++ /* batadv_check_unicast_packet has checked if we may pull */ +++ skb_pull_rcsum(skb, hdr_size); +++ ++ if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size)) ++ goto free_skb; ++ ++- unicast_packet = (struct batadv_unicast_packet *)skb->data; +++ unicast_packet = (struct batadv_unicast_packet *)(skb->data - hdr_size); ++ ++ /* packet for me */ ++ if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) { ++@@ -1001,8 +1004,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ orig_addr_gw = eth_hdr(skb)->h_source; ++ orig_node_gw = batadv_orig_hash_find(bat_priv, orig_addr_gw); ++ if (orig_node_gw) { ++- is_gw = batadv_bla_is_backbone_gw(skb, orig_node_gw, ++- hdr_size); +++ is_gw = batadv_bla_is_backbone_gw(skb, orig_node_gw, 0); ++ batadv_orig_node_put(orig_node_gw); ++ if (is_gw) { ++ batadv_dbg(BATADV_DBG_BLA, bat_priv, ++@@ -1014,7 +1016,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ ++ if (is4addr) { ++ unicast_4addr_packet = ++- (struct batadv_unicast_4addr_packet *)skb->data; +++ (struct batadv_unicast_4addr_packet *) +++ unicast_packet; ++ subtype = unicast_4addr_packet->subtype; ++ batadv_dat_inc_counter(bat_priv, subtype); ++ ++@@ -1031,15 +1034,12 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ } ++ } ++ ++- if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, ++- hdr_size)) +++ if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, 0)) ++ goto rx_success; ++- if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, ++- hdr_size)) +++ if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, 0)) ++ goto rx_success; ++ ++- batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, ++- orig_node); +++ batadv_interface_rx(recv_if->soft_iface, skb, false, orig_node); ++ ++ rx_success: ++ if (orig_node) ++@@ -1048,6 +1048,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, ++ return NET_RX_SUCCESS; ++ } ++ +++ skb_push_rcsum(skb, hdr_size); +++ ++ ret = batadv_route_unicast_packet(skb, recv_if); ++ /* skb was consumed */ ++ skb = NULL; ++@@ -1273,8 +1275,10 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, ++ if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) ++ goto rx_success; ++ +++ skb_pull_rcsum(skb, hdr_size); +++ ++ /* broadcast for me */ ++- batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, orig_node); +++ batadv_interface_rx(recv_if->soft_iface, skb, true, orig_node); ++ ++ rx_success: ++ ret = NET_RX_SUCCESS; ++diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c ++index edeffcb9f3a2..370770759bb8 100644 ++--- a/net/batman-adv/soft-interface.c +++++ b/net/batman-adv/soft-interface.c ++@@ -400,7 +400,7 @@ static int batadv_interface_tx(struct sk_buff *skb, ++ * batadv_interface_rx() - receive ethernet frame on local batman-adv interface ++ * @soft_iface: local interface which will receive the ethernet frame ++ * @skb: ethernet frame for @soft_iface ++- * @hdr_size: size of already parsed batman-adv header +++ * @is_bcast: true if the received frame is a batman-adv broadcast ++ * @orig_node: originator from which the batman-adv packet was sent ++ * ++ * Sends a ethernet frame to the receive path of the local @soft_iface. ++@@ -414,20 +414,14 @@ static int batadv_interface_tx(struct sk_buff *skb, ++ * isolated clients. ++ */ ++ void batadv_interface_rx(struct net_device *soft_iface, ++- struct sk_buff *skb, int hdr_size, +++ struct sk_buff *skb, bool is_bcast, ++ struct batadv_orig_node *orig_node) ++ { ++- struct batadv_bcast_packet *batadv_bcast_packet; ++ struct batadv_priv *bat_priv = netdev_priv(soft_iface); ++ struct vlan_ethhdr *vhdr; ++ struct ethhdr *ethhdr; ++ unsigned short vid; ++- bool is_bcast; ++ ++- batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data; ++- is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST); ++- ++- skb_pull_rcsum(skb, hdr_size); ++ skb_reset_mac_header(skb); ++ ++ /* clean the netfilter state now that the batman-adv header has been ++diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h ++index daf87f07fadd..53071d45093a 100644 ++--- a/net/batman-adv/soft-interface.h +++++ b/net/batman-adv/soft-interface.h ++@@ -30,7 +30,7 @@ struct sk_buff; ++ ++ int batadv_skb_head_push(struct sk_buff *skb, unsigned int len); ++ void batadv_interface_rx(struct net_device *soft_iface, ++- struct sk_buff *skb, int hdr_size, +++ struct sk_buff *skb, bool is_bcast, ++ struct batadv_orig_node *orig_node); ++ struct net_device *batadv_softif_create(struct net *net, const char *name); ++ void batadv_softif_destroy_sysfs(struct net_device *soft_iface); ++-- ++2.16.2 ++ +diff --git a/batman-adv/patches/900-unaligned-access.patch b/batman-adv/patches/900-unaligned-access.patch +deleted file mode 100644 +index eb067329bc5e9f112b56d03c20c612fb1fd1e32d..0000000000000000000000000000000000000000 +--- a/batman-adv/patches/900-unaligned-access.patch ++++ /dev/null +@@ -1,87 +0,0 @@ +-From: Matthias Schiffer +-Date: Wed, 24 Jan 2018 11:21:37 +0000 (+0100) +-Subject: batman-adv: always assume 2-byte packet alignment +-X-Git-Url: https://git.open-mesh.org/batman-adv.git/commitdiff_plain/0509fc0c128ba2891770305c57c9b6a3a61ea7bd +- +-batman-adv: always assume 2-byte packet alignment +- +-NIC drivers generally try to ensure that the "network header" is aligned +-to a 4-byte boundary. This is not always possible: When Ethernet frames are +-encapsulated in other packets with 4-byte aligned headers, the inner +-Ethernet header will have 4-byte alignment, and in consequence, the inner +-network header is aligned to 2, but not to 4 bytes. +- +-Most parts of batman-adv only care about 2-byte alignment; in particular, +-no unaligned accesses occur in performance-critical paths that handle +-actual payload data. This is not true for OGM handling: the seqno and crc +-fields are accessed as 32-bit values. To avoid these unaligned accesses, +-this patch reduces the expected packet alignment to 2 bytes for all of +-batadv's packet types. +- +-As no unaligned accesses existed on the performance-critical paths anyways, +-this chance does have any (positive or negative) effect on performance, but +-it still makes sense to avoid these accesses to prevent log noise when +-examining other unaligned accesses in the kernel while batman-adv is +-active. +- +-Signed-off-by: Matthias Schiffer +-Signed-off-by: Sven Eckelmann +---- +- +-diff --git a/include/uapi/linux/batadv_packet.h b/include/uapi/linux/batadv_packet.h +-index daefd72..894d8d2 100644 +---- a/include/uapi/linux/batadv_packet.h +-+++ b/include/uapi/linux/batadv_packet.h +-@@ -196,8 +196,6 @@ struct batadv_bla_claim_dst { +- __be16 group; /* group id */ +- }; +- +--#pragma pack() +-- +- /** +- * struct batadv_ogm_packet - ogm (routing protocol) packet +- * @packet_type: batman-adv packet type, part of the general header +-@@ -222,9 +220,6 @@ struct batadv_ogm_packet { +- __u8 reserved; +- __u8 tq; +- __be16 tvlv_len; +-- /* __packed is not needed as the struct size is divisible by 4, +-- * and the largest data type in this struct has a size of 4. +-- */ +- }; +- +- #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) +-@@ -249,9 +244,6 @@ struct batadv_ogm2_packet { +- __u8 orig[ETH_ALEN]; +- __be16 tvlv_len; +- __be32 throughput; +-- /* __packed is not needed as the struct size is divisible by 4, +-- * and the largest data type in this struct has a size of 4. +-- */ +- }; +- +- #define BATADV_OGM2_HLEN sizeof(struct batadv_ogm2_packet) +-@@ -405,7 +397,6 @@ struct batadv_icmp_packet_rr { +- * misalignment of the payload after the ethernet header. It may also lead to +- * leakage of information when the padding it not initialized before sending. +- */ +--#pragma pack(2) +- +- /** +- * struct batadv_unicast_packet - unicast packet for network payload +-@@ -533,8 +524,6 @@ struct batadv_coded_packet { +- __be16 coded_len; +- }; +- +--#pragma pack() +-- +- /** +- * struct batadv_unicast_tvlv_packet - generic unicast packet with tvlv payload +- * @packet_type: batman-adv packet type, part of the general header +-@@ -641,4 +630,6 @@ struct batadv_tvlv_mcast_data { +- __u8 reserved[3]; +- }; +- +-+#pragma pack() +-+ +- #endif /* _UAPI_LINUX_BATADV_PACKET_H_ */ +diff --git a/batman-adv/patches/9000-unaligned-access.patch b/batman-adv/patches/9000-unaligned-access.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..eb067329bc5e9f112b56d03c20c612fb1fd1e32d +--- /dev/null ++++ b/batman-adv/patches/9000-unaligned-access.patch +@@ -0,0 +1,87 @@ ++From: Matthias Schiffer ++Date: Wed, 24 Jan 2018 11:21:37 +0000 (+0100) ++Subject: batman-adv: always assume 2-byte packet alignment ++X-Git-Url: https://git.open-mesh.org/batman-adv.git/commitdiff_plain/0509fc0c128ba2891770305c57c9b6a3a61ea7bd ++ ++batman-adv: always assume 2-byte packet alignment ++ ++NIC drivers generally try to ensure that the "network header" is aligned ++to a 4-byte boundary. This is not always possible: When Ethernet frames are ++encapsulated in other packets with 4-byte aligned headers, the inner ++Ethernet header will have 4-byte alignment, and in consequence, the inner ++network header is aligned to 2, but not to 4 bytes. ++ ++Most parts of batman-adv only care about 2-byte alignment; in particular, ++no unaligned accesses occur in performance-critical paths that handle ++actual payload data. This is not true for OGM handling: the seqno and crc ++fields are accessed as 32-bit values. To avoid these unaligned accesses, ++this patch reduces the expected packet alignment to 2 bytes for all of ++batadv's packet types. ++ ++As no unaligned accesses existed on the performance-critical paths anyways, ++this chance does have any (positive or negative) effect on performance, but ++it still makes sense to avoid these accesses to prevent log noise when ++examining other unaligned accesses in the kernel while batman-adv is ++active. ++ ++Signed-off-by: Matthias Schiffer ++Signed-off-by: Sven Eckelmann ++--- ++ ++diff --git a/include/uapi/linux/batadv_packet.h b/include/uapi/linux/batadv_packet.h ++index daefd72..894d8d2 100644 ++--- a/include/uapi/linux/batadv_packet.h +++++ b/include/uapi/linux/batadv_packet.h ++@@ -196,8 +196,6 @@ struct batadv_bla_claim_dst { ++ __be16 group; /* group id */ ++ }; ++ ++-#pragma pack() ++- ++ /** ++ * struct batadv_ogm_packet - ogm (routing protocol) packet ++ * @packet_type: batman-adv packet type, part of the general header ++@@ -222,9 +220,6 @@ struct batadv_ogm_packet { ++ __u8 reserved; ++ __u8 tq; ++ __be16 tvlv_len; ++- /* __packed is not needed as the struct size is divisible by 4, ++- * and the largest data type in this struct has a size of 4. ++- */ ++ }; ++ ++ #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) ++@@ -249,9 +244,6 @@ struct batadv_ogm2_packet { ++ __u8 orig[ETH_ALEN]; ++ __be16 tvlv_len; ++ __be32 throughput; ++- /* __packed is not needed as the struct size is divisible by 4, ++- * and the largest data type in this struct has a size of 4. ++- */ ++ }; ++ ++ #define BATADV_OGM2_HLEN sizeof(struct batadv_ogm2_packet) ++@@ -405,7 +397,6 @@ struct batadv_icmp_packet_rr { ++ * misalignment of the payload after the ethernet header. It may also lead to ++ * leakage of information when the padding it not initialized before sending. ++ */ ++-#pragma pack(2) ++ ++ /** ++ * struct batadv_unicast_packet - unicast packet for network payload ++@@ -533,8 +524,6 @@ struct batadv_coded_packet { ++ __be16 coded_len; ++ }; ++ ++-#pragma pack() ++- ++ /** ++ * struct batadv_unicast_tvlv_packet - generic unicast packet with tvlv payload ++ * @packet_type: batman-adv packet type, part of the general header ++@@ -641,4 +630,6 @@ struct batadv_tvlv_mcast_data { ++ __u8 reserved[3]; ++ }; ++ +++#pragma pack() +++ ++ #endif /* _UAPI_LINUX_BATADV_PACKET_H_ */