lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20080128.210222.07062540.yoshfuji@linux-ipv6.org>
Date:	Mon, 28 Jan 2008 21:02:22 +0900 (JST)
From:	YOSHIFUJI Hideaki / 吉藤英明 
	<yoshfuji@...ux-ipv6.org>
To:	davem@...emloft.net
Cc:	yoshfuji@...ux-ipv6.org, mitch@...ux.vnet.ibm.com,
	netdev@...r.kernel.org
Subject: [PATCH net-2.6.25] [IPV6] ADDRLABEL: Fix double free on label
 deletion.

If an entry is being deleted because it has only one reference, 
we immediately delete it and blindly register the rcu handler for it,
This results in oops by double freeing that object.

This patch fixes it by consolidating the code paths for the deletion;
let its rcu handler delete the object if it has no more reference.

Bug was found by Mitsuru Chinen <mitch@...ux.vnet.ibm.com>

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@...ux-ipv6.org>
---

diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index 6f1ca60..7a706c4 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -106,6 +106,11 @@ static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p)
 	kfree(p);
 }
 
+static void ip6addrlbl_free_rcu(struct rcu_head *h)
+{
+	ip6addrlbl_free(container_of(h, struct ip6addrlbl_entry, rcu));
+}
+
 static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p)
 {
 	return atomic_inc_not_zero(&p->refcnt);
@@ -114,12 +119,7 @@ static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p)
 static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p)
 {
 	if (atomic_dec_and_test(&p->refcnt))
-		ip6addrlbl_free(p);
-}
-
-static void ip6addrlbl_free_rcu(struct rcu_head *h)
-{
-	ip6addrlbl_free(container_of(h, struct ip6addrlbl_entry, rcu));
+		call_rcu(&p->rcu, ip6addrlbl_free_rcu);
 }
 
 /* Find label */
@@ -240,7 +240,6 @@ int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
 				}
 				hlist_replace_rcu(&p->list, &newp->list);
 				ip6addrlbl_put(p);
-				call_rcu(&p->rcu, ip6addrlbl_free_rcu);
 				goto out;
 			} else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
 				   (p->prefixlen < newp->prefixlen)) {
@@ -300,7 +299,6 @@ int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
 		    ipv6_addr_equal(&p->prefix, prefix)) {
 			hlist_del_rcu(&p->list);
 			ip6addrlbl_put(p);
-			call_rcu(&p->rcu, ip6addrlbl_free_rcu);
 			ret = 0;
 			break;
 		}

-- 
YOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@...ux-ipv6.org>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ