From patchwork Sat Feb 23 14:09:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 17835 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 7520F80C70; Sat, 23 Feb 2019 15:09:22 +0100 (CET) Authentication-Results: open-mesh.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=narfation.org header.i=@narfation.org header.b="PrhGYkbW"; dkim-atps=neutral Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=79.140.41.39; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver= Received: from v3-1039.vlinux.de (narfation.org [79.140.41.39]) by open-mesh.org (Postfix) with ESMTPS id C641D805DE for ; Sat, 23 Feb 2019 15:09:20 +0100 (CET) Received: from sven-desktop.home.narfation.org (p200300C5973408FD0000000000004065.dip0.t-ipconnect.de [IPv6:2003:c5:9734:8fd::4065]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 601881100FB; Sat, 23 Feb 2019 15:09:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=narfation.org; s=20121; t=1550930960; bh=67GiRo/yugyEB/BxijuKU6hQL/fnQseMQ/jFQh21qdw=; h=From:To:Cc:Subject:Date:From; b=PrhGYkbW5Uz3HbmlOS8EHMJBN0r4w8tdBo5YDUbLx+cMW4u8NTSSUo3d+Ne0wZjTe VirHbtxqAfGKLYnbWaZuwNXYNG0dXTSVDXTqj8HDSjgOL8a03ryi0zPppzkz6aL9oC mj+1x2RQQYGFvKP/DfIzb/qzN2FjYXF2ItVbefmM= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Sat, 23 Feb 2019 15:09:04 +0100 Message-Id: <20190223140906.28979-1-sven@narfation.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Subject: [B.A.T.M.A.N.] batman-adv: Reduce claim hash refcnt only for removed entry X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 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: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" The batadv_hash_remove is a function which searches the hashtable for an entry using a needle, a hashtable bucket selection function and a compare function. It will lock the bucket list and delete an entry when the compare function matches it with the needle. It returns the pointer to the hlist_node which matches or NULL when no entry matches the needle. The batadv_bla_del_claim is not itself protected in anyway to avoid that any other function is modifying the hashtable between the search for the entry and the call to batadv_hash_remove. It can therefore happen that the entry either doesn't exist anymore or an entry was deleted which is not the same object as the needle. In such an situation, the reference counter (for the reference stored in the hashtable) must not be reduced for the needle. Instead the reference counter of the actually removed entry has to be reduced. Otherwise the reference counter will underflow and the object might be freed before all its references were dropped. The kref helpers reported this problem as: refcount_t: underflow; use-after-free. Fixes: a9ce0dc43e2c ("batman-adv: add basic bridge loop avoidance code") Signed-off-by: Sven Eckelmann --- Cc: Simon Wunderlich diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index ef39aabdb69435f384ae2ebef26d4d31367f427c..4fb01108e5f534b8a055edface0717f950ccdacc 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -803,6 +803,8 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, const u8 *mac, const unsigned short vid) { struct batadv_bla_claim search_claim, *claim; + struct batadv_bla_claim *claim_removed_entry; + struct hlist_node *claim_removed_node; ether_addr_copy(search_claim.addr, mac); search_claim.vid = vid; @@ -813,10 +815,18 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): %pM, vid %d\n", __func__, mac, batadv_print_vid(vid)); - batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim, - batadv_choose_claim, claim); - batadv_claim_put(claim); /* reference from the hash is gone */ + claim_removed_node = batadv_hash_remove(bat_priv->bla.claim_hash, + batadv_compare_claim, + batadv_choose_claim, claim); + if (!claim_removed_node) + goto free_claim; + /* reference from the hash is gone */ + claim_removed_entry = hlist_entry(claim_removed_node, + struct batadv_bla_claim, hash_entry); + batadv_claim_put(claim_removed_entry); + +free_claim: /* don't need the reference from hash_find() anymore */ batadv_claim_put(claim); } -- 2.20.1