netdev
[Top] [All Lists]

[IPSEC] fix ref counting in __xfrm4_bundle_create()

To: netdev@xxxxxxxxxxx
Subject: [IPSEC] fix ref counting in __xfrm4_bundle_create()
From: Eugene Surovegin <ebs@xxxxxxxxxxx>
Date: Fri, 28 May 2004 17:14:50 -0700
Mail-followup-to: netdev@xxxxxxxxxxx
Sender: netdev-bounce@xxxxxxxxxxx
User-agent: Mutt/1.5.5.1i
Hi all!

I think there is a ref counting bug in error path of __xfrm4_bundle_create().

xfrm_lookup() assumes that xfrm_bundle_create() will take ownership of 
xfrm_state array passed to it. If xfrm_bundle_create() fails, xfrm_lookup() 
will 
call xfrm_state_put() to release this array. 

Unfortunately, error path in __xfrm4_bundle_create() also calls 
xfrm_state_put() 
(indirectly through dst_free() -> ... -> xfrm_dst_destroy()) and we end up 
calling xfrm_state_put() _twice_.

This causes "infamous" :) "x->km.state == XFRM_STATE_DEAD" assertion in some 
our 
tests when interface is removed when IPSec traffic is going through it.

IPv6 version (__xfrm6_bundle_create()) seems to have the same problem. I'll 
send 
IPv6 version if my analysis and fix are correct :).

Here is IPv4 version (patch is against current linux-2.5 BK).

Signed-off-by: Eugene Surovegin <ebs@xxxxxxxxxxx>

===== net/ipv4/xfrm4_policy.c 1.8 vs edited =====
--- 1.8/net/ipv4/xfrm4_policy.c Fri Mar 19 19:35:32 2004
+++ edited/net/ipv4/xfrm4_policy.c      Fri May 28 16:22:35 2004
@@ -87,6 +87,7 @@
 
                if (unlikely(dst1 == NULL)) {
                        err = -ENOBUFS;
+                       nx = i;
                        goto error;
                }
 
@@ -157,8 +158,14 @@
        return 0;
 
 error:
-       if (dst)
+       if (dst){
+               /* bump refcount because dst_free will decrement it
+                  and our caller (xfrm_lookup) will do the same on error.
+               */
+               for (i = 0; i < nx; i++)
+                       xfrm_state_hold(xfrm[i]);
                dst_free(dst);
+       }       
        return err;
 }
 






<Prev in Thread] Current Thread [Next in Thread>