The following commit has been merged in the merge/master branch:
commit a198a2362ac6bf8a5a7053f8b87db3f43e5cced9
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Fri Mar 11 16:44:06 2016 +0100
batman-adv: Fix reference counting of hardif_neigh_node object for neigh_node
The batadv_neigh_node was specific to a batadv_hardif_neigh_node and held
an implicit reference to it. But this reference was never stored in form of
a pointer in the batadv_neigh_node itself. Instead
batadv_neigh_node_release depends on a consistent state of
hard_iface->neigh_list and that batadv_hardif_neigh_get always returns the
batadv_hardif_neigh_node object which it has a reference for. But
batadv_hardif_neigh_get cannot guarantee that because it is working only
with rcu_read_lock on this list. It can therefore happen that a neigh_addr
is in this list twice or that batadv_hardif_neigh_get cannot find the
batadv_hardif_neigh_node for an neigh_addr due to some other list
operations taking place at the same time.
Instead add a batadv_hardif_neigh_node pointer directly in
batadv_neigh_node which will be used for the reference counter decremented
on release of batadv_neigh_node.
Fixes: fed2826b490c ("batman-adv: add list of unique single hop neighbors per hard-interface")
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index d52f67a..c355a82 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -250,7 +250,6 @@ static void batadv_neigh_node_release(struct kref *ref)
{
struct hlist_node *node_tmp;
struct batadv_neigh_node *neigh_node;
- struct batadv_hardif_neigh_node *hardif_neigh;
struct batadv_neigh_ifinfo *neigh_ifinfo;
struct batadv_algo_ops *bao;
@@ -262,13 +261,7 @@ static void batadv_neigh_node_release(struct kref *ref)
batadv_neigh_ifinfo_put(neigh_ifinfo);
}
- hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming,
- neigh_node->addr);
- if (hardif_neigh) {
- /* batadv_hardif_neigh_get() increases refcount too */
- batadv_hardif_neigh_put(hardif_neigh);
- batadv_hardif_neigh_put(hardif_neigh);
- }
+ batadv_hardif_neigh_put(neigh_node->hardif_neigh);
if (bao->bat_neigh_free)
bao->bat_neigh_free(neigh_node);
@@ -665,6 +658,10 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
neigh_node->orig_node = orig_node;
neigh_node->last_seen = jiffies;
+ /* increment unique neighbor refcount */
+ kref_get(&hardif_neigh->refcount);
+ neigh_node->hardif_neigh = hardif_neigh;
+
/* extra reference for return */
kref_init(&neigh_node->refcount);
kref_get(&neigh_node->refcount);
@@ -673,9 +670,6 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
spin_unlock_bh(&orig_node->neigh_list_lock);
- /* increment unique neighbor refcount */
- kref_get(&hardif_neigh->refcount);
-
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
neigh_addr, orig_node->orig, hard_iface->net_dev->name);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 65afd09..1e47fbe 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -433,6 +433,7 @@ struct batadv_hardif_neigh_node {
* @ifinfo_lock: lock protecting private ifinfo members and list
* @if_incoming: pointer to incoming hard-interface
* @last_seen: when last packet via this neighbor was received
+ * @hardif_neigh: hardif_neigh of this neighbor
* @refcount: number of contexts the object is used
* @rcu: struct used for freeing in an RCU-safe manner
*/
@@ -444,6 +445,7 @@ struct batadv_neigh_node {
spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */
struct batadv_hard_iface *if_incoming;
unsigned long last_seen;
+ struct batadv_hardif_neigh_node *hardif_neigh;
struct kref refcount;
struct rcu_head rcu;
};
--
linux integration
The following commit has been merged in the merge/master branch:
commit 9e5e03716c0e6a12e4bb466a042bc519b55734bb
Author: Marek Lindner <mareklindner(a)neomailbox.ch>
Date: Fri Mar 11 16:01:09 2016 +0100
batman-adv: init neigh node last seen field
Fixes: 58232977fbaf ("basic routing code complete (hases and ring buffer added) -> needs testing !")
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
[sven(a)narfation.org: fix conflicts with current version]
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index e4cbb07..d52f67a 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -663,6 +663,7 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
ether_addr_copy(neigh_node->addr, neigh_addr);
neigh_node->if_incoming = hard_iface;
neigh_node->orig_node = orig_node;
+ neigh_node->last_seen = jiffies;
/* extra reference for return */
kref_init(&neigh_node->refcount);
--
linux integration
The following commit has been merged in the merge/master branch:
commit 08ba64d0b558be47b48c1ef275b671b518581d04
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Sun Mar 20 12:27:53 2016 +0100
batman-adv: Reduce refcnt of removed router when updating route
_batadv_update_route rcu_derefences orig_ifinfo->router outside of a
spinlock protected region to print some information messages to the debug
log. But this pointer is not checked again when the new pointer is assigned
in the spinlock protected region. Thus is can happen that the value of
orig_ifinfo->router changed in the meantime and thus the reference counter
of the wrong router gets reduced after the spinlock protected region.
Just rcu_dereferencing the value of orig_ifinfo->router inside the spinlock
protected region (which also set the new pointer) is enough to get the
correct old router object.
Fixes: d90ddb94423f ("batman-adv: Make orig_node->router an rcu protected pointer")
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 1fb1be3..7b260e1 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -104,6 +104,15 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
neigh_node = NULL;
spin_lock_bh(&orig_node->neigh_list_lock);
+ /* curr_router used earlier may not be the current orig_ifinfo->router
+ * anymore because it was dereferenced outside of the neigh_list_lock
+ * protected region. After the new best neighbor has replace the current
+ * best neighbor the reference counter needs to decrease. Consequently,
+ * the code needs to ensure the curr_router variable contains a pointer
+ * to the replaced best neighbor.
+ */
+ curr_router = rcu_dereference_protected(orig_ifinfo->router, true);
+
rcu_assign_pointer(orig_ifinfo->router, neigh_node);
spin_unlock_bh(&orig_node->neigh_list_lock);
batadv_orig_ifinfo_free_ref(orig_ifinfo);
--
linux integration
The following commit has been merged in the merge/master branch:
commit fbb98aa65dbba86c94808204060434393c2ad19e
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Sat Mar 19 13:55:21 2016 +0100
batman-adv: Deactive TO_BE_ACTIVATED hardif on shutdown
The shutdown of an batman-adv interface can happen with one of its slave
interfaces still being in the BATADV_IF_TO_BE_ACTIVATED state. A possible
reason for it is that the routing algorithm BATMAN_V was selected and
batadv_schedule_bat_ogm was not yet called for this interface. This slave
interface still has to be set to BATADV_IF_INACTIVE or the batman-adv
interface will never reduce its usage counter and thus never gets shutdown.
This problem can be simulated via:
$ modprobe dummy
$ modprobe batman-adv routing_algo=BATMAN_V
$ ip link add bat0 type batadv
$ ip link set dummy0 master bat0
$ ip link set dummy0 up
$ ip link del bat0
unregister_netdevice: waiting for bat0 to become free. Usage count = 3
Fixes: 88861ea9acb7 ("[batman-adv] replacing if up/down timer with kernel notifications")
Reported-by: Matthias Schiffer <mschiffer(a)universe-factory.net>
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index b22b277..c61d5b0 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -572,8 +572,7 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batadv_hard_iface *primary_if = NULL;
- if (hard_iface->if_status == BATADV_IF_ACTIVE)
- batadv_hardif_deactivate_interface(hard_iface);
+ batadv_hardif_deactivate_interface(hard_iface);
if (hard_iface->if_status != BATADV_IF_INACTIVE)
goto out;
--
linux integration
The following commit has been merged in the merge/master branch:
commit d1059685e5abf1d63e7938292dd332d376f086e1
Merge: fbb98aa65dbba86c94808204060434393c2ad19e 08ba64d0b558be47b48c1ef275b671b518581d04
Author: Marek Lindner <mareklindner(a)neomailbox.ch>
Date: Sun Mar 27 15:51:40 2016 +0800
Merge branch 'maint' into next
diff --combined net/batman-adv/routing.c
index 4dd646a,7b260e1..b781bf7
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@@ -1,4 -1,4 +1,4 @@@
-/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@@@ -25,7 -25,6 +25,7 @@@
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/jiffies.h>
+#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
#include <linux/rculist.h>
@@@ -73,7 -72,7 +73,7 @@@ static void _batadv_update_route(struc
rcu_read_lock();
curr_router = rcu_dereference(orig_ifinfo->router);
- if (curr_router && !atomic_inc_not_zero(&curr_router->refcount))
+ if (curr_router && !kref_get_unless_zero(&curr_router->refcount))
curr_router = NULL;
rcu_read_unlock();
@@@ -98,20 -97,29 +98,29 @@@
}
if (curr_router)
- batadv_neigh_node_free_ref(curr_router);
+ batadv_neigh_node_put(curr_router);
/* increase refcount of new best neighbor */
- if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
+ if (neigh_node && !kref_get_unless_zero(&neigh_node->refcount))
neigh_node = NULL;
spin_lock_bh(&orig_node->neigh_list_lock);
+ /* curr_router used earlier may not be the current orig_ifinfo->router
+ * anymore because it was dereferenced outside of the neigh_list_lock
+ * protected region. After the new best neighbor has replace the current
+ * best neighbor the reference counter needs to decrease. Consequently,
+ * the code needs to ensure the curr_router variable contains a pointer
+ * to the replaced best neighbor.
+ */
+ curr_router = rcu_dereference_protected(orig_ifinfo->router, true);
+
rcu_assign_pointer(orig_ifinfo->router, neigh_node);
spin_unlock_bh(&orig_node->neigh_list_lock);
- batadv_orig_ifinfo_free_ref(orig_ifinfo);
+ batadv_orig_ifinfo_put(orig_ifinfo);
/* decrease refcount of previous best neighbor */
if (curr_router)
- batadv_neigh_node_free_ref(curr_router);
+ batadv_neigh_node_put(curr_router);
}
/**
@@@ -138,7 -146,7 +147,7 @@@ void batadv_update_route(struct batadv_
out:
if (router)
- batadv_neigh_node_free_ref(router);
+ batadv_neigh_node_put(router);
}
/**
@@@ -147,29 -155,23 +156,29 @@@
* @bat_priv: the bat priv with all the soft interface information
* @seq_num_diff: difference between the current/received sequence number and
* the last sequence number
+ * @seq_old_max_diff: maximum age of sequence number not considered as restart
* @last_reset: jiffies timestamp of the last reset, will be updated when reset
* is detected
+ * @protection_started: is set to true if the protection window was started,
+ * doesn't change otherwise.
*
* Return:
* 0 if the packet is to be accepted.
* 1 if the packet is to be ignored.
*/
int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
- unsigned long *last_reset)
+ s32 seq_old_max_diff, unsigned long *last_reset,
+ bool *protection_started)
{
- if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
+ if (seq_num_diff <= -seq_old_max_diff ||
seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
if (!batadv_has_timed_out(*last_reset,
BATADV_RESET_PROTECTION_MS))
return 1;
*last_reset = jiffies;
+ if (protection_started)
+ *protection_started = true;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"old packet received, start protection\n");
}
@@@ -269,9 -271,9 +278,9 @@@ static int batadv_recv_my_icmp_packet(s
}
out:
if (primary_if)
- batadv_hardif_free_ref(primary_if);
+ batadv_hardif_put(primary_if);
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return ret;
}
@@@ -317,9 -319,9 +326,9 @@@ static int batadv_recv_icmp_ttl_exceede
out:
if (primary_if)
- batadv_hardif_free_ref(primary_if);
+ batadv_hardif_put(primary_if);
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return ret;
}
@@@ -403,7 -405,7 +412,7 @@@ int batadv_recv_icmp_packet(struct sk_b
out:
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return ret;
}
@@@ -498,14 -500,14 +507,14 @@@ batadv_find_router(struct batadv_priv *
hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) {
/* acquire some structures and references ... */
- if (!atomic_inc_not_zero(&cand->refcount))
+ if (!kref_get_unless_zero(&cand->refcount))
continue;
cand_router = rcu_dereference(cand->router);
if (!cand_router)
goto next;
- if (!atomic_inc_not_zero(&cand_router->refcount)) {
+ if (!kref_get_unless_zero(&cand_router->refcount)) {
cand_router = NULL;
goto next;
}
@@@ -524,8 -526,8 +533,8 @@@
/* mark the first possible candidate */
if (!first_candidate) {
- atomic_inc(&cand_router->refcount);
- atomic_inc(&cand->refcount);
+ kref_get(&cand_router->refcount);
+ kref_get(&cand->refcount);
first_candidate = cand;
first_candidate_router = cand_router;
}
@@@ -545,16 -547,16 +554,16 @@@
next:
/* free references */
if (cand_router) {
- batadv_neigh_node_free_ref(cand_router);
+ batadv_neigh_node_put(cand_router);
cand_router = NULL;
}
- batadv_orig_ifinfo_free_ref(cand);
+ batadv_orig_ifinfo_put(cand);
}
rcu_read_unlock();
/* last_bonding_candidate is reset below, remove the old reference. */
if (orig_node->last_bonding_candidate)
- batadv_orig_ifinfo_free_ref(orig_node->last_bonding_candidate);
+ batadv_orig_ifinfo_put(orig_node->last_bonding_candidate);
/* After finding candidates, handle the three cases:
* 1) there is a next candidate, use that
@@@ -562,17 -564,17 +571,17 @@@
* 3) there is no candidate at all, return the default router
*/
if (next_candidate) {
- batadv_neigh_node_free_ref(router);
+ batadv_neigh_node_put(router);
/* remove references to first candidate, we don't need it. */
if (first_candidate) {
- batadv_neigh_node_free_ref(first_candidate_router);
- batadv_orig_ifinfo_free_ref(first_candidate);
+ batadv_neigh_node_put(first_candidate_router);
+ batadv_orig_ifinfo_put(first_candidate);
}
router = next_candidate_router;
orig_node->last_bonding_candidate = next_candidate;
} else if (first_candidate) {
- batadv_neigh_node_free_ref(router);
+ batadv_neigh_node_put(router);
/* refcounting has already been done in the loop above. */
router = first_candidate_router;
@@@ -649,7 -651,7 +658,7 @@@ static int batadv_route_unicast_packet(
out:
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return ret;
}
@@@ -702,9 -704,9 +711,9 @@@ batadv_reroute_unicast_packet(struct ba
ret = true;
out:
if (primary_if)
- batadv_hardif_free_ref(primary_if);
+ batadv_hardif_put(primary_if);
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return ret;
}
@@@ -768,7 -770,7 +777,7 @@@ static int batadv_check_unicast_ttvn(st
return 0;
curr_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
}
/* check if the TTVN contained in the packet is fresher than what the
@@@ -808,7 -810,7 +817,7 @@@
ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr);
- batadv_hardif_free_ref(primary_if);
+ batadv_hardif_put(primary_if);
unicast_packet->ttvn = curr_ttvn;
@@@ -908,7 -910,7 +917,7 @@@ int batadv_recv_unicast_packet(struct s
rx_success:
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return NET_RX_SUCCESS;
}
@@@ -1019,7 -1021,7 +1028,7 @@@ int batadv_recv_frag_packet(struct sk_b
out:
if (orig_node_src)
- batadv_orig_node_free_ref(orig_node_src);
+ batadv_orig_node_put(orig_node_src);
return ret;
}
@@@ -1080,8 -1082,7 +1089,8 @@@ int batadv_recv_bcast_packet(struct sk_
/* check whether the packet is old and the host just restarted. */
if (batadv_window_protected(bat_priv, seq_diff,
- &orig_node->bcast_seqno_reset))
+ BATADV_BCAST_MAX_AGE,
+ &orig_node->bcast_seqno_reset, NULL))
goto spin_unlock;
/* mark broadcast in flood history, update window position
@@@ -1124,6 -1125,6 +1133,6 @@@ spin_unlock
spin_unlock_bh(&orig_node->bcast_seqno_lock);
out:
if (orig_node)
- batadv_orig_node_free_ref(orig_node);
+ batadv_orig_node_put(orig_node);
return ret;
}
--
linux integration
The following commit has been merged in the merge/master branch:
commit 4735b462b1d09caa0d12d8460186a4e552c43a85
Author: Arnd Bergmann <arnd(a)arndb.de>
Date: Wed Mar 2 21:45:56 2016 +0100
batman-adv: clarify CFG80211 dependency
The driver calls cfg80211_get_station, which may be part of a
module, so we must not enable BATMAN_ADV_BATMAN_V if
BATMAN_ADV=y and CFG80211=m:
net/built-in.o: In function `batadv_v_elp_get_throughput':
(text+0x5c62c): undefined reference to `cfg80211_get_station'
This clarifies the dependency to cover all combinations.
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
Fixes: 2e0a2972e354 ("batman-adv: Depend on CFG80211 for BATMAN_V")
Acked-by: Antonio Quartulli <a(a)unstable.cc>
Signed-off-by: David S. Miller <davem(a)davemloft.net>
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index e651dc9..f66930e 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -17,7 +17,7 @@ config BATMAN_ADV
config BATMAN_ADV_BATMAN_V
bool "B.A.T.M.A.N. V protocol (experimental)"
- depends on BATMAN_ADV && CFG80211
+ depends on BATMAN_ADV && CFG80211=y || (CFG80211=m && BATMAN_ADV=m)
default n
help
This option enables the B.A.T.M.A.N. V protocol, the successor
--
linux integration
The following commit has been merged in the merge/master branch:
commit 289e386bcec0d469fc629019b349f47d17789911
Author: Linus Lüssing <linus.luessing(a)c0d3.blue>
Date: Fri Mar 11 14:04:49 2016 +0100
batman-adv: Fix broadcast/ogm queue limit on a removed interface
When removing a single interface while a broadcast or ogm packet is
still pending then we will free the forward packet without releasing the
queue slots again.
This patch is supposed to fix this issue.
Fixes: d5bbce8465af ("batman-adv: Add missing hardif_free_ref in forw_packet_free")
Signed-off-by: Linus Lüssing <linus.luessing(a)c0d3.blue>
[sven(a)narfation.org: fix conflicts with current version]
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 3ce06e0..7641785 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -675,6 +675,9 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
if (pending) {
hlist_del(&forw_packet->list);
+ if (!forw_packet->own)
+ atomic_inc(&bat_priv->bcast_queue_left);
+
batadv_forw_packet_free(forw_packet);
}
}
@@ -702,6 +705,9 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
if (pending) {
hlist_del(&forw_packet->list);
+ if (!forw_packet->own)
+ atomic_inc(&bat_priv->batman_queue_left);
+
batadv_forw_packet_free(forw_packet);
}
}
--
linux integration
The following commit has been merged in the merge/master branch:
commit 7d2f8a773bae5e07cadc9a9f74ac21abe32cde13
Author: Sven Eckelmann <sven(a)narfation.org>
Date: Fri Feb 26 17:56:13 2016 +0100
batman-adv: Check skb size before using encapsulated ETH+VLAN header
The encapsulated ethernet and VLAN header may be outside the received
ethernet frame. Thus the skb buffer size has to be checked before it can be
parsed to find out if it encapsulates another batman-adv packet.
Fixes: 48628bb9419f ("batman-adv: softif bridge loop avoidance")
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 6c65de9..64d721c 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -407,11 +407,17 @@ void batadv_interface_rx(struct net_device *soft_iface,
*/
nf_reset(skb);
+ if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
+ goto dropped;
+
vid = batadv_get_vid(skb, 0);
ethhdr = eth_hdr(skb);
switch (ntohs(ethhdr->h_proto)) {
case ETH_P_8021Q:
+ if (!pskb_may_pull(skb, VLAN_ETH_HLEN))
+ goto dropped;
+
vhdr = (struct vlan_ethhdr *)skb->data;
if (vhdr->h_vlan_encapsulated_proto != ethertype)
@@ -423,8 +429,6 @@ void batadv_interface_rx(struct net_device *soft_iface,
}
/* skb->dev & skb->pkt_type are set here */
- if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
- goto dropped;
skb->protocol = eth_type_trans(skb, soft_iface);
/* should not be necessary anymore as we use skb_pull_rcsum()
--
linux integration