Re: Possible memory leak in xfrm_policy_insert

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, May 31, 2003 at 11:41:27PM -0700, David S. Miller wrote:
> 
> I've applied your fix.  Thanks a lot.

And here is a patch to fix the leak in the flow cache.  They used to
be pol_put's before the move.

And I've made sure it's a -p1 patch :)

Thanks,
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: include/net/flow.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/flow.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 flow.h
--- include/net/flow.h	27 May 2003 08:38:39 -0000	1.1.1.3
+++ a/include/net/flow.h	1 Jun 2003 04:53:42 -0000
@@ -82,8 +82,10 @@
 #define FLOW_DIR_OUT	1
 #define FLOW_DIR_FWD	2
 
+typedef void (*flow_obj_destroy_t)(void *);
 typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
-			       void **objp, atomic_t **obj_refp);
+			       void **objp, atomic_t **obj_refp,
+			       flow_obj_destroy_t *destroyer);
 
 extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
 			       flow_resolve_t resolver);
Index: include/net/xfrm.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/xfrm.h,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 xfrm.h
--- include/net/xfrm.h	27 May 2003 08:38:39 -0000	1.1.1.8
+++ a/include/net/xfrm.h	1 Jun 2003 04:46:35 -0000
@@ -348,7 +348,7 @@
 		atomic_inc(&policy->refcnt);
 }
 
-extern void __xfrm_policy_destroy(struct xfrm_policy *policy);
+extern void __xfrm_policy_destroy(void *policy);
 
 static inline void xfrm_pol_put(struct xfrm_policy *policy)
 {
Index: net/xfrm/xfrm_policy.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_policy.c,v
retrieving revision 1.3
diff -u -r1.3 xfrm_policy.c
--- net/xfrm/xfrm_policy.c	1 Jun 2003 00:10:13 -0000	1.3
+++ a/net/xfrm/xfrm_policy.c	1 Jun 2003 04:56:48 -0000
@@ -179,8 +188,10 @@
 
 /* Destroy xfrm_policy: descendant resources must be released to this moment. */
 
-void __xfrm_policy_destroy(struct xfrm_policy *policy)
+void __xfrm_policy_destroy(void *data)
 {
+	struct xfrm_policy *policy = data;
+
 	if (!policy->dead)
 		BUG();
 
@@ -381,8 +391,9 @@
 
 /* Find policy to apply to this flow. */
 
-void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
-			void **objp, atomic_t **obj_refp)
+static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+			       void **objp, atomic_t **obj_refp,
+			       flow_obj_destroy_t *obj_destroyp)
 {
 	struct xfrm_policy *pol;
 
@@ -401,8 +412,10 @@
 		}
 	}
 	read_unlock_bh(&xfrm_policy_lock);
-	if ((*objp = (void *) pol) != NULL)
+	if ((*objp = (void *) pol) != NULL) {
 		*obj_refp = &pol->refcnt;
+		*obj_destroyp = __xfrm_policy_destroy;
+	}
 }
 
 struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
Index: net/core/flow.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/core/flow.c,v
retrieving revision 1.2
diff -u -r1.2 flow.c
--- net/core/flow.c	1 Jun 2003 00:08:36 -0000	1.2
+++ a/net/core/flow.c	1 Jun 2003 04:54:19 -0000
@@ -22,6 +22,7 @@
 	u32			genid;
 	void			*object;
 	atomic_t		*object_ref;
+	flow_obj_destroy_t	object_destroy;
 };
 
 atomic_t flow_cache_genid = ATOMIC_INIT(0);
@@ -48,6 +49,12 @@
 
 #define FLOW_HASH_RND_PERIOD	(10 * 60 * HZ)
 
+static inline void flow_obj_put(struct flow_cache_entry *fle)
+{
+	if (fle->object && atomic_dec_and_test(fle->object_ref))
+		fle->object_destroy(fle->object);
+}
+
 static void flow_cache_new_hashrnd(unsigned long arg)
 {
 	int i;
@@ -74,8 +81,7 @@
 		}
 		while ((fle = *flp) != NULL) {
 			*flp = fle->next;
-			if (fle->object)
-				atomic_dec(fle->object_ref);
+			flow_obj_put(fle);
 			kmem_cache_free(flow_cachep, fle);
 			flow_count(cpu)--;
 		}
@@ -172,17 +178,18 @@
 	{
 		void *obj;
 		atomic_t *obj_ref;
+		flow_obj_destroy_t obj_destroy;
 
-		resolver(key, family, dir, &obj, &obj_ref);
+		resolver(key, family, dir, &obj, &obj_ref, &obj_destroy);
 
 		if (fle) {
 			fle->genid = atomic_read(&flow_cache_genid);
 
-			if (fle->object)
-				atomic_dec(fle->object_ref);
+			flow_obj_put(fle);
 
 			fle->object = obj;
 			fle->object_ref = obj_ref;
+			fle->object_destroy = obj_destroy;
 			if (obj)
 				atomic_inc(fle->object_ref);
 		} else {
@@ -199,6 +206,7 @@
 				fle->genid = atomic_read(&flow_cache_genid);
 				fle->object = obj;
 				fle->object_ref = obj_ref;
+				fle->object_destroy = obj_destroy;
 				if (obj)
 					atomic_inc(fle->object_ref);
 

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux