From patchwork Tue Dec 15 23:31:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 4789 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=79.140.41.39; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver=b.a.t.m.a.n@lists.open-mesh.org Authentication-Results: open-mesh.org; dkim=pass reason="1024-bit key; unprotected key" header.d=narfation.org header.i=@narfation.org header.b=ENMlGY0I; dkim-adsp=pass; dkim-atps=neutral Received: from v3-1039.vlinux.de (narfation.org [79.140.41.39]) by open-mesh.org (Postfix) with ESMTPS id CEB1581944 for ; Wed, 16 Dec 2015 00:32:19 +0100 (CET) Received: from sven-desktop.home.narfation.org (unknown [IPv6:2a02:3100:260c:3afd:2066:82e6:79c1:88d8]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 1B5F8110102; Wed, 16 Dec 2015 00:32:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=narfation.org; s=20121; t=1450222339; bh=ShWWbLEtNea4f5qpyk9FBV2ulLc4cBurfRNHKbwpg9s=; h=From:To:Cc:Subject:Date:From; b=ENMlGY0ILH3vWR1rpCLHUu2zc/3scWjJystUR+yRqCnq+o8g8hY0HYT9xGRcJ1yD6 /LyZtR9B9Wj6pF0BtM6wNhV0Kz1kP1dekxqwR83ZMVYFV7wUvjV0TCgSgbjQxT/LBl /QF8wt00GHPzS1ryezg9PsgX+TcwkuYXSDZfYTig= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 16 Dec 2015 00:31:34 +0100 Message-Id: <1450222316-1764-1-git-send-email-sven@narfation.org> X-Mailer: git-send-email 2.6.4 Subject: [B.A.T.M.A.N.] [PATCH 01/23] batman-adv: Fix list removal of batadv_hardif_neigh_node X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Dec 2015 23:32:20 -0000 The neigh_list with batadv_hardif_neigh_node objects is accessed with only rcu_read_lock in batadv_neigh_node_get and batadv_iv_neigh_print. Thus is is not allowed to kfree the object before the rcu grace period ends which may still tries to access this object. Therefore the object has first to be removed from the neigh_list and then it has either wait with synchronize_rcu or call_rcu till the grace period ends before it can be freed. Signed-off-by: Sven Eckelmann --- I have no idea why batadv_hardif_neigh_free_now is considered to be safe to call. The only caller is batadv_neigh_node_free_rcu but this function never makes sure that the previously mentioned two functions are actually not accessing it right now when hlist_del_rcu_init + kfree is called. --- net/batman-adv/originator.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 00b0437..2681c7d 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -217,10 +217,6 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu); - spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); - hlist_del_init_rcu(&hardif_neigh->list); - spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); - batadv_hardif_free_ref_now(hardif_neigh->if_incoming); kfree(hardif_neigh); } @@ -233,8 +229,13 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) static void batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) { - if (atomic_dec_and_test(&hardif_neigh->refcount)) + if (atomic_dec_and_test(&hardif_neigh->refcount)) { + spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + hlist_del_init_rcu(&hardif_neigh->list); + spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu); + } } /** @@ -244,8 +245,13 @@ batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) */ void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) { - if (atomic_dec_and_test(&hardif_neigh->refcount)) + if (atomic_dec_and_test(&hardif_neigh->refcount)) { + spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + hlist_del_init_rcu(&hardif_neigh->list); + spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu); + } } /**