The following commit has been merged in the master branch:
commit aecf54d3a00d5b2155f59468dbcb42dc950e74c5
Author: Sven Eckelmann <sven.eckelmann(a)gmx.de>
Date: Sat Sep 18 15:35:41 2010 +0000
batman-adv: Use refcnt to track usage count of gw_node
gw_election may leak data from the rcu protected list of all gateway
nodes outside the read-side critical area. This is not valid as we may
free the data using a call_rcu created callback after we unlock using
rcu_read_unlock. A workaround is to provide a reference count to be sure
that the memory isn't freed to early.
It is currently only to implement the already existing functionality and
doesn't provide the full tracking of all usage cases.
Additionally, we must gw_node_hold inside the
rcu_read_lock()..rcu_read_unlock() before we attach to the structure
which "leaks" it. When another function now removed it from its usage
context (curr_gw, usage on stack, ...) then we must gw_node_put it. If
it is decremented to zero then we can issue the call_rcu to the freeing
function. So "put" is not allowed inside an rcu_read_lock.
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)gmx.de>
diff --git a/gateway_client.c b/gateway_client.c
index 8bc1cb0..16f0757 100644
--- a/gateway_client.c
+++ b/gateway_client.c
@@ -28,6 +28,17 @@
#include <linux/udp.h>
#include <linux/if_vlan.h>
+static void gw_node_hold(struct gw_node *gw_node)
+{
+ atomic_inc(&gw_node->refcnt);
+}
+
+static void gw_node_put(struct gw_node *gw_node)
+{
+ if (atomic_dec_and_test(&gw_node->refcnt))
+ kfree(gw_node);
+}
+
void *gw_get_selected(struct bat_priv *bat_priv)
{
struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
@@ -205,6 +216,8 @@ static void gw_node_add(struct bat_priv *bat_priv,
memset(gw_node, 0, sizeof(struct gw_node));
INIT_HLIST_NODE(&gw_node->list);
gw_node->orig_node = orig_node;
+ atomic_set(&gw_node->refcnt, 0);
+ gw_node_hold(gw_node);
spin_lock_irqsave(&bat_priv->gw_list_lock, flags);
hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
@@ -281,7 +294,7 @@ void gw_node_purge_deleted(struct bat_priv *bat_priv)
hlist_del_rcu(&gw_node->list);
synchronize_rcu();
- kfree(gw_node);
+ gw_node_put(gw_node);
}
}
@@ -300,7 +313,7 @@ void gw_node_list_free(struct bat_priv *bat_priv)
&bat_priv->gw_list, list) {
hlist_del_rcu(&gw_node->list);
synchronize_rcu();
- kfree(gw_node);
+ gw_node_put(gw_node);
}
gw_deselect(bat_priv);
diff --git a/types.h b/types.h
index 1940404..ecc4365 100644
--- a/types.h
+++ b/types.h
@@ -95,6 +95,7 @@ struct gw_node {
struct hlist_node list;
struct orig_node *orig_node;
unsigned long deleted;
+ atomic_t refcnt;
};
/**
--
batman-adv
The following commit has been merged in the master branch:
commit 2b6a7a5586c180458400beecb13e3c7ec573bb00
Author: Sven Eckelmann <sven.eckelmann(a)gmx.de>
Date: Sat Sep 18 15:35:35 2010 +0000
batman-adv: Always protect list_for_each_entry_rcu with RCU
receive_bat_packet is not called with rcu_read_lock so we must ensure by
ourself that we protect list_for_each_entry_rcu using the correct RCU
locks.
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)gmx.de>
diff --git a/routing.c b/routing.c
index 603a932..1781b7e 100644
--- a/routing.c
+++ b/routing.c
@@ -575,6 +575,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
batman_packet->tq, batman_packet->ttl, batman_packet->version,
has_directlink_flag);
+ rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (batman_if->if_status != IF_ACTIVE)
continue;
@@ -597,6 +598,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
if (compare_orig(ethhdr->h_source, broadcast_addr))
is_broadcast = 1;
}
+ rcu_read_unlock();
if (batman_packet->version != COMPAT_VERSION) {
bat_dbg(DBG_BATMAN, bat_priv,
--
batman-adv
The following commit has been merged in the master branch:
commit be4f3dbf84c25597ac6073149b3277ac6a46b58c
Author: Sven Eckelmann <sven.eckelmann(a)gmx.de>
Date: Sat Sep 18 15:35:35 2010 +0000
batman-adv: Remove unneeded rcu_read_lock
Regions which do not use rcu functions don't need to protected by
rcu_read_lock. If we want to protect data from being freed than it must
be covered by the same read-side critical section or otherwise the grace
period may already ended and freed the memory before we called
rcu_read_lock again.
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)gmx.de>
diff --git a/gateway_client.c b/gateway_client.c
index dd96d99..bfac0ff 100644
--- a/gateway_client.c
+++ b/gateway_client.c
@@ -342,9 +342,7 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_node *node;
int gw_count = 0;
- rcu_read_lock();
if (!bat_priv->primary_if) {
- rcu_read_unlock();
return seq_printf(seq, "BATMAN mesh %s disabled - please "
"specify interfaces to enable it\n",
@@ -352,7 +350,6 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
}
if (bat_priv->primary_if->if_status != IF_ACTIVE) {
- rcu_read_unlock();
return seq_printf(seq, "BATMAN mesh %s disabled - "
"primary interface not active\n",
@@ -365,7 +362,6 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
"outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
bat_priv->primary_if->net_dev->name,
bat_priv->primary_if->addr_str, net_dev->name);
- rcu_read_unlock();
rcu_read_lock();
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
diff --git a/originator.c b/originator.c
index 2250266..3424ac2 100644
--- a/originator.c
+++ b/originator.c
@@ -335,7 +335,6 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
net_dev->name);
}
- rcu_read_lock();
seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
SOURCE_VERSION, REVISION_VERSION_STR,
bat_priv->primary_if->net_dev->name,
@@ -343,7 +342,6 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
"outgoingIF", "Potential nexthops");
- rcu_read_unlock();
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
--
batman-adv
The following commit has been merged in the master branch:
commit 267436330e2b6fc4c2f94d6296cbf9298dd1b39a
Author: Sven Eckelmann <sven.eckelmann(a)gmx.de>
Date: Sat Sep 18 15:35:31 2010 +0000
batman-adv: Introduce if_list_lock to protect if_list
The update critical sections of if_list must be protected by a locking
primitive other than RCU. The iterator must also be protected by the
chosen locking mechanism.
The rtnl_lock in hardif_remove_interfaces must also be moved outside the
iterator primitive to ensure that we don't deadlock the kernel due to
differently nested locks in hardif_remove_interfaces and hard_if_event.
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)gmx.de>
diff --git a/hard-interface.c b/hard-interface.c
index edbfddf..3cd7cb1 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -35,6 +35,9 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
+/* protect update critical side of if_list - but not the content */
+static DEFINE_SPINLOCK(if_list_lock);
+
struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
{
struct batman_if *batman_if;
@@ -402,7 +405,11 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
INIT_LIST_HEAD(&batman_if->list);
check_known_mac_addr(batman_if->net_dev->dev_addr);
+
+ spin_lock(&if_list_lock);
list_add_tail_rcu(&batman_if->list, &if_list);
+ spin_unlock(&if_list_lock);
+
return batman_if;
free_if:
@@ -430,6 +437,8 @@ static void hardif_remove_interface(struct batman_if *batman_if)
return;
batman_if->if_status = IF_TO_BE_REMOVED;
+
+ /* caller must take if_list_lock */
list_del_rcu(&batman_if->list);
sysfs_del_hardif(&batman_if->hardif_obj);
dev_put(batman_if->net_dev);
@@ -440,11 +449,13 @@ void hardif_remove_interfaces(void)
{
struct batman_if *batman_if, *batman_if_tmp;
+ rtnl_lock();
+ spin_lock(&if_list_lock);
list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) {
- rtnl_lock();
hardif_remove_interface(batman_if);
- rtnl_unlock();
}
+ spin_unlock(&if_list_lock);
+ rtnl_unlock();
}
static int hard_if_event(struct notifier_block *this,
@@ -469,7 +480,9 @@ static int hard_if_event(struct notifier_block *this,
hardif_deactivate_interface(batman_if);
break;
case NETDEV_UNREGISTER:
+ spin_lock(&if_list_lock);
hardif_remove_interface(batman_if);
+ spin_unlock(&if_list_lock);
break;
case NETDEV_CHANGEMTU:
if (batman_if->soft_iface)
--
batman-adv
The following commit has been merged in the next branch:
commit 68875a5f3a8d9cf236c450ddd91c8baa56d8e657
Author: Marek Lindner <lindner_marek(a)yahoo.de>
Date: Sat Sep 18 11:22:50 2010 +0200
batctl: change email
Signed-off-by: Andreas Langer <an.langer at gmx.de>
diff --git a/bat-hosts.c b/bat-hosts.c
index 5802e80..888b997 100644
--- a/bat-hosts.c
+++ b/bat-hosts.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/functions.c b/functions.c
index 497e166..cff8b52 100644
--- a/functions.c
+++ b/functions.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/functions.h b/functions.h
index 6aa9487..1b1c350 100644
--- a/functions.h
+++ b/functions.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/main.h b/main.h
index 2a37836..f45fec0 100644
--- a/main.h
+++ b/main.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/man/batctl.8 b/man/batctl.8
index 4e6950a..fd002f8 100644
--- a/man/batctl.8
+++ b/man/batctl.8
@@ -156,7 +156,7 @@ remember than MAC addresses.
.BR dmesg (1),
.BR dot (1)
.SH AUTHOR
-batctl was written by Andreas Langer <a.langer(a)q-dsl.de> and Marek
+batctl was written by Andreas Langer <an.langer(a)gmx.de> and Marek
Lindner <lindner_marek(a)yahoo.de>.
.PP
This manual page was written by Simon Wunderlich
diff --git a/ping.c b/ping.c
index affd6ad..288bd01 100644
--- a/ping.c
+++ b/ping.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/tcpdump.c b/tcpdump.c
index 118a862..92a5262 100644
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>
+ * Andreas Langer <an.langer(a)gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/tcpdump.h b/tcpdump.h
index 19b0585..f98d63f 100644
--- a/tcpdump.h
+++ b/tcpdump.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/traceroute.c b/traceroute.c
index 63de7e6..dc97a01 100644
--- a/traceroute.c
+++ b/traceroute.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner <lindner_marek(a)yahoo.de>
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner <lindner_marek(a)yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
--
batctl
The following commit has been merged in the next branch:
commit 7e95742719e5cec4dc99c392032c038fb0cffb54
Author: Sven Eckelmann <sven.eckelmann(a)gmx.de>
Date: Sat Sep 18 11:11:40 2010 +0000
batman-adv: wait for call_rcu before unloading module
synchronize_rcu respective synchronize_net only waits for the rcu grace
period to elapse and we may fail to finish the calls which were made to
call_rcu in that time. In result the module could be unloaded during the
execution of the RCU callbacks.
rcu_barrier[1] will now wait for all outstanding RCU callbacks to finish
before continuing.
[1] Documentation/RCU/rcubarrier.txt
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)gmx.de>
diff --git a/main.c b/main.c
index c9d3be5..0a9f6f3 100644
--- a/main.c
+++ b/main.c
@@ -73,7 +73,7 @@ static void __exit batman_exit(void)
destroy_workqueue(bat_event_workqueue);
bat_event_workqueue = NULL;
- synchronize_net();
+ rcu_barrier();
}
int mesh_init(struct net_device *soft_iface)
--
batman-adv
The following commit has been merged in the master branch:
commit f28eb1d620e38437823a478500c0bcde09003419
Author: Marek Lindner <lindner_marek(a)yahoo.de>
Date: Sat Sep 18 11:22:53 2010 +0200
vis: change email
Signed-off-by: Andreas Langer <an.langer at gmx.de>
diff --git a/vis.c b/vis.c
index 6efa66d..4087ecb 100644
--- a/vis.c
+++ b/vis.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
diff --git a/vis.h b/vis.h
index 273d86d..9f26ee6 100644
--- a/vis.h
+++ b/vis.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
*
- * Andreas Langer <a.langer(a)q-dsl.de>, Marek Lindner
+ * Andreas Langer <an.langer(a)gmx.de>, Marek Lindner
*
*
* This program is free software; you can redistribute it and/or
--
vis; test conversation
The following commit has been merged in the master branch:
commit d1167df04ecd1bfa1539b18b30a055ffb57fb2dc
Author: Marek Lindner <lindner_marek(a)yahoo.de>
Date: Sat Sep 18 11:22:49 2010 +0200
batman: change email
Signed-off-by: Andreas Langer <an.langer at gmx.de>
diff --git a/THANKS b/THANKS
index c3ad35f..9c10878 100644
--- a/THANKS
+++ b/THANKS
@@ -10,6 +10,6 @@ Thomas Lopatic (thomas-at-lopatic.de)
Felix Fietkau (nbd-at-nbd.name)
Ludger Schmudde (lui-at-schmudde.com)
Simon Wunderlich (siwu-at-hrz.tu-chemnitz.de)
-Andreas Langer (a.langer-at-q-dsl.de)
+Andreas Langer (an.langer-at-gmx.de)
Sven Eckelmann (sven.eckelmann-at-gmx.de)
Antoine van Gelder (antoine-at-7degrees.co.za)
--
batman; test conversation