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();
}
-
To unsubscribe from this list: 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
This archive was generated by hypermail 2b29 : Thu Jul 31 2003 - 22:00:01 EST