batman-adv: 2013.3.0 updated stability fixes
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
This commit is contained in:
parent
040106786d
commit
60296fff41
2 changed files with 204 additions and 1 deletions
|
@ -12,7 +12,7 @@ PKG_NAME:=batman-adv
|
|||
|
||||
PKG_VERSION:=2013.3.0
|
||||
BATCTL_VERSION:=2013.3.0
|
||||
PKG_RELEASE:=4
|
||||
PKG_RELEASE:=5
|
||||
PKG_MD5SUM:=d070c0879cd8fe8125315a4566fabd2d
|
||||
BATCTL_MD5SUM:=747535b0296f0013a6f99373a51d41fc
|
||||
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
From c98c3e521913b8dd5fee4d3b90dc9ed7a47e5bee Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
|
||||
Date: Tue, 6 Aug 2013 20:21:15 +0200
|
||||
Subject: [PATCH] batman-adv: fix potential kernel paging errors for unicast
|
||||
transmissions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
There are several functions which might reallocate skb data. Currently
|
||||
some places keep reusing their old ethhdr pointer regardless of whether
|
||||
they became invalid after such a reallocation or not. This potentially
|
||||
leads to kernel paging errors.
|
||||
|
||||
This patch fixes these by refetching the ethdr pointer after the
|
||||
potential reallocations.
|
||||
|
||||
Signed-off-by: Linus Lüssing <linus.luessing@web.de>
|
||||
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
|
||||
---
|
||||
bridge_loop_avoidance.c | 2 ++
|
||||
gateway_client.c | 13 ++++++++++++-
|
||||
gateway_client.h | 3 +--
|
||||
soft-interface.c | 9 ++++++++-
|
||||
unicast.c | 13 ++++++++++---
|
||||
5 files changed, 33 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c
|
||||
index e14531f..264de88 100644
|
||||
--- a/bridge_loop_avoidance.c
|
||||
+++ b/bridge_loop_avoidance.c
|
||||
@@ -1529,6 +1529,8 @@ out:
|
||||
* in these cases, the skb is further handled by this function and
|
||||
* returns 1, otherwise it returns 0 and the caller shall further
|
||||
* process the skb.
|
||||
+ *
|
||||
+ * This call might reallocate skb data.
|
||||
*/
|
||||
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
||||
unsigned short vid)
|
||||
diff --git a/gateway_client.c b/gateway_client.c
|
||||
index f105219..7614af3 100644
|
||||
--- a/gateway_client.c
|
||||
+++ b/gateway_client.c
|
||||
@@ -508,6 +508,7 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* this call might reallocate skb data */
|
||||
static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
|
||||
{
|
||||
int ret = false;
|
||||
@@ -568,6 +569,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* this call might reallocate skb data */
|
||||
bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
|
||||
{
|
||||
struct ethhdr *ethhdr;
|
||||
@@ -619,6 +621,12 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
|
||||
|
||||
if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
|
||||
return false;
|
||||
+
|
||||
+ /* skb->data might have been reallocated by pskb_may_pull() */
|
||||
+ ethhdr = (struct ethhdr *)skb->data;
|
||||
+ if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
|
||||
+ ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
|
||||
+
|
||||
udphdr = (struct udphdr *)(skb->data + *header_len);
|
||||
*header_len += sizeof(*udphdr);
|
||||
|
||||
@@ -634,12 +642,14 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
|
||||
return true;
|
||||
}
|
||||
|
||||
+/* this call might reallocate skb data */
|
||||
bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
|
||||
- struct sk_buff *skb, struct ethhdr *ethhdr)
|
||||
+ struct sk_buff *skb)
|
||||
{
|
||||
struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
|
||||
struct batadv_orig_node *orig_dst_node = NULL;
|
||||
struct batadv_gw_node *curr_gw = NULL;
|
||||
+ struct ethhdr *ethhdr;
|
||||
bool ret, out_of_range = false;
|
||||
unsigned int header_len = 0;
|
||||
uint8_t curr_tq_avg;
|
||||
@@ -648,6 +658,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
+ ethhdr = (struct ethhdr *)skb->data;
|
||||
orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
|
||||
ethhdr->h_dest);
|
||||
if (!orig_dst_node)
|
||||
diff --git a/gateway_client.h b/gateway_client.h
|
||||
index 039902d..1037d75 100644
|
||||
--- a/gateway_client.h
|
||||
+++ b/gateway_client.h
|
||||
@@ -34,7 +34,6 @@ void batadv_gw_node_delete(struct batadv_priv *bat_priv,
|
||||
void batadv_gw_node_purge(struct batadv_priv *bat_priv);
|
||||
int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset);
|
||||
bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
|
||||
-bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
|
||||
- struct sk_buff *skb, struct ethhdr *ethhdr);
|
||||
+bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
|
||||
diff --git a/soft-interface.c b/soft-interface.c
|
||||
index 700d0b4..0f04e1c 100644
|
||||
--- a/soft-interface.c
|
||||
+++ b/soft-interface.c
|
||||
@@ -180,6 +180,9 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
if (batadv_bla_tx(bat_priv, skb, vid))
|
||||
goto dropped;
|
||||
|
||||
+ /* skb->data might have been reallocated by batadv_bla_tx() */
|
||||
+ ethhdr = (struct ethhdr *)skb->data;
|
||||
+
|
||||
/* Register the client MAC in the transtable */
|
||||
if (!is_multicast_ether_addr(ethhdr->h_source))
|
||||
batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
|
||||
@@ -220,6 +223,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ /* reminder: ethhdr might have become unusable from here on
|
||||
+ * (batadv_gw_is_dhcp_target() might have reallocated skb data)
|
||||
+ */
|
||||
}
|
||||
|
||||
/* ethernet packet should be broadcasted */
|
||||
@@ -266,7 +273,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
/* unicast packet */
|
||||
} else {
|
||||
if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) {
|
||||
- ret = batadv_gw_out_of_range(bat_priv, skb, ethhdr);
|
||||
+ ret = batadv_gw_out_of_range(bat_priv, skb);
|
||||
if (ret)
|
||||
goto dropped;
|
||||
}
|
||||
diff --git a/unicast.c b/unicast.c
|
||||
index dc8b5d4..688a041 100644
|
||||
--- a/unicast.c
|
||||
+++ b/unicast.c
|
||||
@@ -326,7 +326,9 @@ static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
|
||||
* @skb: the skb containing the payload to encapsulate
|
||||
* @orig_node: the destination node
|
||||
*
|
||||
- * Returns false if the payload could not be encapsulated or true otherwise
|
||||
+ * Returns false if the payload could not be encapsulated or true otherwise.
|
||||
+ *
|
||||
+ * This call might reallocate skb data.
|
||||
*/
|
||||
static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
|
||||
struct batadv_orig_node *orig_node)
|
||||
@@ -343,7 +345,9 @@ static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
|
||||
* @orig_node: the destination node
|
||||
* @packet_subtype: the batman 4addr packet subtype to use
|
||||
*
|
||||
- * Returns false if the payload could not be encapsulated or true otherwise
|
||||
+ * Returns false if the payload could not be encapsulated or true otherwise.
|
||||
+ *
|
||||
+ * This call might reallocate skb data.
|
||||
*/
|
||||
bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
|
||||
struct sk_buff *skb,
|
||||
@@ -401,7 +405,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
|
||||
struct batadv_neigh_node *neigh_node;
|
||||
int data_len = skb->len;
|
||||
int ret = NET_RX_DROP;
|
||||
- unsigned int dev_mtu;
|
||||
+ unsigned int dev_mtu, header_len;
|
||||
|
||||
/* get routing information */
|
||||
if (is_multicast_ether_addr(ethhdr->h_dest)) {
|
||||
@@ -429,10 +433,12 @@ find_router:
|
||||
switch (packet_type) {
|
||||
case BATADV_UNICAST:
|
||||
batadv_unicast_prepare_skb(skb, orig_node);
|
||||
+ header_len = sizeof(struct batadv_unicast_packet);
|
||||
break;
|
||||
case BATADV_UNICAST_4ADDR:
|
||||
batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
|
||||
packet_subtype);
|
||||
+ header_len = sizeof(struct batadv_unicast_4addr_packet);
|
||||
break;
|
||||
default:
|
||||
/* this function supports UNICAST and UNICAST_4ADDR only. It
|
||||
@@ -441,6 +447,7 @@ find_router:
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ ethhdr = (struct ethhdr *)(skb->data + header_len);
|
||||
unicast_packet = (struct batadv_unicast_packet *)skb->data;
|
||||
|
||||
/* inform the destination node that we are still missing a correct route
|
||||
--
|
||||
1.7.10.4
|
||||
|
Loading…
Reference in a new issue