Ranjeet Shetye <ranjeet.shetye2@zultys.com> wrote: > > kernel is 2.6.0-test1 from bk (current as of Fri, July 25), talking to > a 2.4.21 kernel with IPSec backport. IPSec is tunnel mode, ESP and AH > with AES and MD5 for phase 1 and phase 2. PFS is off. default > lifetimes. no modules loaded on 2.6 kernel. > > Starting tetheral (intf going into promiscuous mode ?) triggers this > bug consistently. When an secpath is COWed, we lose reference to the states. Does this patch help? -- 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: kernel-source-2.5/include/net/xfrm.h =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/xfrm.h,v retrieving revision 1.14 diff -u -r1.14 xfrm.h --- kernel-source-2.5/include/net/xfrm.h 26 Jul 2003 03:56:01 -0000 1.14 +++ kernel-source-2.5/include/net/xfrm.h 26 Jul 2003 04:06:29 -0000 @@ -9,7 +9,6 @@ #include <linux/crypto.h> #include <linux/pfkeyv2.h> #include <linux/in6.h> -#include <linux/slab.h> #include <net/sock.h> #include <net/dst.h> @@ -539,7 +538,6 @@ struct sec_path { - kmem_cache_t *pool; atomic_t refcnt; int len; struct sec_decap_state x[XFRM_MAX_DEPTH]; @@ -562,6 +560,8 @@ __secpath_destroy(sp); } +extern struct sec_path *secpath_dup(struct sec_path *src); + static inline int __xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) { @@ -818,8 +818,7 @@ extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard); -extern void xfrm4_input_init(void); -extern void xfrm6_input_init(void); +extern void xfrm_input_init(void); extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); extern void xfrm_probe_algs(void); Index: kernel-source-2.5/net/ipv4/xfrm4_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/xfrm4_input.c,v retrieving revision 1.3 diff -u -r1.3 xfrm4_input.c --- kernel-source-2.5/net/ipv4/xfrm4_input.c 26 Jul 2003 03:56:01 -0000 1.3 +++ kernel-source-2.5/net/ipv4/xfrm4_input.c 26 Jul 2003 03:48:44 -0000 @@ -9,13 +9,10 @@ * */ -#include <linux/slab.h> #include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> -static kmem_cache_t *secpath_cachep; - int xfrm4_rcv(struct sk_buff *skb) { return xfrm4_rcv_encap(skb, 0); @@ -100,19 +97,12 @@ /* Allocate new secpath or COW existing one. */ if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { - kmem_cache_t *pool = skb->sp ? skb->sp->pool : secpath_cachep; struct sec_path *sp; - sp = kmem_cache_alloc(pool, SLAB_ATOMIC); + sp = secpath_dup(skb->sp); if (!sp) goto drop; - if (skb->sp) { - memcpy(sp, skb->sp, sizeof(struct sec_path)); + if (skb->sp) secpath_put(skb->sp); - } else { - sp->pool = pool; - sp->len = 0; - } - atomic_set(&sp->refcnt, 1); skb->sp = sp; } if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) @@ -142,16 +132,3 @@ kfree_skb(skb); return 0; } - - -void __init xfrm4_input_init(void) -{ - secpath_cachep = kmem_cache_create("secpath4_cache", - sizeof(struct sec_path), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - - if (!secpath_cachep) - panic("IP: failed to allocate secpath4_cache\n"); -} - Index: kernel-source-2.5/net/ipv4/xfrm4_policy.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/xfrm4_policy.c,v retrieving revision 1.2 diff -u -r1.2 xfrm4_policy.c --- kernel-source-2.5/net/ipv4/xfrm4_policy.c 13 Jun 2003 11:23:45 -0000 1.2 +++ kernel-source-2.5/net/ipv4/xfrm4_policy.c 26 Jul 2003 04:06:46 -0000 @@ -271,7 +271,6 @@ { xfrm4_state_init(); xfrm4_policy_init(); - xfrm4_input_init(); } void __exit xfrm4_fini(void) Index: kernel-source-2.5/net/ipv6/xfrm6_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/xfrm6_input.c,v retrieving revision 1.2 diff -u -r1.2 xfrm6_input.c --- kernel-source-2.5/net/ipv6/xfrm6_input.c 26 Jul 2003 03:56:02 -0000 1.2 +++ kernel-source-2.5/net/ipv6/xfrm6_input.c 26 Jul 2003 03:52:04 -0000 @@ -14,8 +14,6 @@ #include <net/ipv6.h> #include <net/xfrm.h> -static kmem_cache_t *secpath_cachep; - static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph, struct sk_buff *skb) { @@ -93,19 +91,12 @@ /* Allocate new secpath or COW existing one. */ if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { - kmem_cache_t *pool = skb->sp ? skb->sp->pool : secpath_cachep; struct sec_path *sp; - sp = kmem_cache_alloc(pool, SLAB_ATOMIC); + sp = secpath_dup(skb->sp); if (!sp) goto drop; - if (skb->sp) { - memcpy(sp, skb->sp, sizeof(struct sec_path)); + if (skb->sp) secpath_put(skb->sp); - } else { - sp->pool = pool; - sp->len = 0; - } - atomic_set(&sp->refcnt, 1); skb->sp = sp; } @@ -136,15 +127,3 @@ kfree_skb(skb); return -1; } - -void __init xfrm6_input_init(void) -{ - secpath_cachep = kmem_cache_create("secpath6_cache", - sizeof(struct sec_path), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - - if (!secpath_cachep) - panic("IPv6: failed to allocate secpath6_cache\n"); -} - Index: kernel-source-2.5/net/ipv6/xfrm6_policy.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/xfrm6_policy.c,v retrieving revision 1.4 diff -u -r1.4 xfrm6_policy.c --- kernel-source-2.5/net/ipv6/xfrm6_policy.c 9 Jul 2003 09:18:42 -0000 1.4 +++ kernel-source-2.5/net/ipv6/xfrm6_policy.c 26 Jul 2003 04:06:55 -0000 @@ -274,7 +274,6 @@ { xfrm6_policy_init(); xfrm6_state_init(); - xfrm6_input_init(); } void __exit xfrm6_fini(void) Index: kernel-source-2.5/net/xfrm/xfrm_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_input.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 xfrm_input.c --- kernel-source-2.5/net/xfrm/xfrm_input.c 2 Jul 2003 20:40:16 -0000 1.1.1.3 +++ kernel-source-2.5/net/xfrm/xfrm_input.c 26 Jul 2003 03:45:57 -0000 @@ -7,15 +7,38 @@ * */ +#include <linux/slab.h> #include <net/ip.h> #include <net/xfrm.h> +static kmem_cache_t *secpath_cachep; + void __secpath_destroy(struct sec_path *sp) { int i; for (i = 0; i < sp->len; i++) xfrm_state_put(sp->x[i].xvec); - kmem_cache_free(sp->pool, sp); + kmem_cache_free(secpath_cachep, sp); +} + +struct sec_path *secpath_dup(struct sec_path *src) +{ + struct sec_path *sp; + + sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC); + if (!sp) + return NULL; + + sp->len = 0; + if (src) { + int i; + + memcpy(sp, src, sizeof(*sp)); + for (i = 0; i < sp->len; i++) + xfrm_state_hold(sp->x[i].xvec); + } + atomic_set(&sp->refcnt, 1); + return sp; } /* Fetch spi and seq from ipsec header */ @@ -49,4 +72,14 @@ *spi = *(u32*)(skb->h.raw + offset); *seq = *(u32*)(skb->h.raw + offset_seq); return 0; +} + +void __init xfrm_input_init(void) +{ + secpath_cachep = kmem_cache_create("secpath_cache", + sizeof(struct sec_path), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!secpath_cachep) + panic("XFRM: failed to allocate secpath_cache\n"); } Index: kernel-source-2.5/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.22 diff -u -r1.22 xfrm_policy.c --- kernel-source-2.5/net/xfrm/xfrm_policy.c 14 Jul 2003 10:07:57 -0000 1.22 +++ kernel-source-2.5/net/xfrm/xfrm_policy.c 26 Jul 2003 04:07:02 -0000 @@ -1223,5 +1223,6 @@ { xfrm_state_init(); xfrm_policy_init(); + xfrm_input_init(); } - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html