Source-Changes-HG archive

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

[src/trunk]: src/sys/netipsec Fix bugs in SPD refcounts due to PCBpolicy cach...



details:   https://anonhg.NetBSD.org/src/rev/204c9eecd837
branches:  trunk
changeset: 566976:204c9eecd837
user:      jonathan <jonathan%NetBSD.org@localhost>
date:      Wed May 26 23:16:25 2004 +0000

description:
Fix bugs in SPD refcounts due to PCBpolicy cache, by backporting the
KAME sys/netkey/key.c rev 1.119 ke_sp_unlink()/key_sp_dead() logic.

I have been running a similar version for about 10 days now, and it
fixes the PCB-cache refcount problems for me.

Checked in as a candidate for pullup to the 2.0 branch.

diffstat:

 sys/netipsec/key.c |  71 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 56 insertions(+), 15 deletions(-)

diffs (155 lines):

diff -r 216750fa609e -r 204c9eecd837 sys/netipsec/key.c
--- a/sys/netipsec/key.c        Wed May 26 23:13:03 2004 +0000
+++ b/sys/netipsec/key.c        Wed May 26 23:16:25 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: key.c,v 1.17 2004/05/26 22:14:18 jonathan Exp $        */
+/*     $NetBSD: key.c,v 1.18 2004/05/26 23:16:25 jonathan Exp $        */
 /*     $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $        */
 /*     $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $   */
 
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.17 2004/05/26 22:14:18 jonathan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.18 2004/05/26 23:16:25 jonathan Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -489,6 +489,9 @@
 static const char *key_getuserfqdn __P((void));
 #endif
 static void key_sa_chgstate __P((struct secasvar *, u_int8_t));
+static  __inline void key_sp_dead __P((struct secpolicy *));
+static void key_sp_unlink __P((struct secpolicy *sp));
+
 static struct mbuf *key_alloc_mbuf __P((int));
 struct callout key_timehandler_ch;
 
@@ -514,6 +517,28 @@
        (p)->refcnt--;                                                  \
 } while (0)
 
+
+static __inline void
+key_sp_dead(struct secpolicy *sp)
+{
+
+       /* mark the SP dead */
+       sp->state = IPSEC_SPSTATE_DEAD;
+}
+
+static void
+key_sp_unlink(struct secpolicy *sp)
+{
+
+       /* remove from SP index */
+       if (__LIST_CHAINED(sp)) {
+               LIST_REMOVE(sp, chain);
+               /* Release refcount held just for being on chain */
+               KEY_FREESP(&sp);
+       }
+}
+
+
 /*
  * Return 0 when there are known to be no SP's for the specified
  * direction.  Otherwise return 1.  This is used by IPsec code
@@ -1188,16 +1213,13 @@
 
        IPSEC_ASSERT(sp != NULL, ("key_delsp: null sp"));
 
-       sp->state = IPSEC_SPSTATE_DEAD;
+       key_sp_dead(sp);
 
        IPSEC_ASSERT(sp->refcnt == 0,
                ("key_delsp: SP with references deleted (refcnt %u)",
                sp->refcnt));
 
        s = splsoftnet();       /*called from softclock()*/
-       /* remove from SP index */
-       if (__LIST_CHAINED(sp))
-               LIST_REMOVE(sp, chain);
 
     {
        struct ipsecrequest *isr = sp->req, *nextisr;
@@ -1803,8 +1825,10 @@
        newsp = key_getsp(&spidx);
        if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
                if (newsp) {
-                       newsp->state = IPSEC_SPSTATE_DEAD;
+                       key_sp_dead(newsp);
+                       key_sp_unlink(newsp);   /* XXX jrs ordering */
                        KEY_FREESP(&newsp);
+                       newsp = NULL;
                }
        } else {
                if (newsp != NULL) {
@@ -2042,8 +2066,9 @@
        /* save policy id to buffer to be returned. */
        xpl0->sadb_x_policy_id = sp->id;
 
-       sp->state = IPSEC_SPSTATE_DEAD;
-       KEY_FREESP(&sp);
+       key_sp_dead(sp);
+       key_sp_unlink(sp);      /* XXX jrs ordering */
+       KEY_FREESP(&sp);        /* ref gained by key_getspbyid */
 
 #if defined(__NetBSD__)
        /* Invalidate all cached SPD pointers in the PCBs. */
@@ -2111,8 +2136,10 @@
                key_senderror(so, m, EINVAL);
        }
 
-       sp->state = IPSEC_SPSTATE_DEAD;
-       KEY_FREESP(&sp);
+       key_sp_dead(sp);
+       key_sp_unlink(sp);      /* XXX jrs ordering */
+       KEY_FREESP(&sp);        /* ref gained by key_getsp */
+       sp = NULL;
 
 #if defined(__NetBSD__)
        /* Invalidate all cached SPD pointers in the PCBs. */
@@ -2325,8 +2352,18 @@
                return key_senderror(so, m, EINVAL);
 
        for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
-               LIST_FOREACH(sp, &sptree[dir], chain) {
-                       sp->state = IPSEC_SPSTATE_DEAD;
+               struct secpolicy * nextsp;
+               for (sp = LIST_FIRST(&sptree[dir]);
+                    sp != NULL;
+                    sp = nextsp) {
+
+                       nextsp = LIST_NEXT(sp, chain);
+                       if (sp->state == IPSEC_SPSTATE_DEAD)
+                               continue;
+                       key_sp_dead(sp);
+                       key_sp_unlink(sp);
+                       /* 'sp' dead; continue transfers to 'sp = nextsp' */
+                       continue;
                }
        }
 
@@ -4119,7 +4156,11 @@
                        nextsp = LIST_NEXT(sp, chain);
 
                        if (sp->state == IPSEC_SPSTATE_DEAD) {
-                               KEY_FREESP(&sp);
+                               key_sp_unlink(sp);      /*XXX*/
+
+                               /* 'sp' dead; continue transfers to
+                                * 'sp = nextsp'
+                                */
                                continue;
                        }
 
@@ -4129,7 +4170,7 @@
                        /* the deletion will occur next time */
                        if ((sp->lifetime && now - sp->created > sp->lifetime)
                         || (sp->validtime && now - sp->lastused > sp->validtime)) {
-                               sp->state = IPSEC_SPSTATE_DEAD;
+                               key_sp_dead(sp);
                                key_spdexpire(sp);
                                continue;
                        }



Home | Main Index | Thread Index | Old Index