From mgrooms@shrew.net  Wed Feb 27 07:49:01 2008
Return-Path: <mgrooms@shrew.net>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 6C00C1065672
	for <freebsd-gnats-submit@freebsd.org>; Wed, 27 Feb 2008 07:49:01 +0000 (UTC)
	(envelope-from mgrooms@shrew.net)
Received: from shrew.net (206-223-169-85.beanfield.net [206.223.169.85])
	by mx1.freebsd.org (Postfix) with ESMTP id 3ED8F13C45B
	for <freebsd-gnats-submit@freebsd.org>; Wed, 27 Feb 2008 07:49:01 +0000 (UTC)
	(envelope-from mgrooms@shrew.net)
Received: from localhost (wm-ca.hub.org [206.223.169.82])
	by shrew.net (Postfix) with ESMTP id 93B2579E8C3;
	Wed, 27 Feb 2008 01:16:45 -0600 (CST)
Received: from shrew.net ([206.223.169.85])
 by localhost (mx1.hub.org [206.223.169.82]) (amavisd-new, port 10024)
 with ESMTP id 82191-04; Wed, 27 Feb 2008 07:16:44 +0000 (UTC)
Received: from hole.shrew.net (cpe-66-25-136-5.austin.res.rr.com [66.25.136.5])
	by shrew.net (Postfix) with ESMTP id CE49B79E8BE;
	Wed, 27 Feb 2008 01:16:43 -0600 (CST)
Received: from hole.shrew.net (localhost.shrew.net [127.0.0.1])
	by hole.shrew.net (8.13.8/8.13.8) with ESMTP id m1R7GOi9065276;
	Wed, 27 Feb 2008 01:16:25 -0600 (CST)
	(envelope-from mgrooms@hole.shrew.net)
Received: (from mgrooms@localhost)
	by hole.shrew.net (8.13.8/8.13.8/Submit) id m1R7GN8L065275;
	Wed, 27 Feb 2008 01:16:23 -0600 (CST)
	(envelope-from mgrooms)
Message-Id: <200802270716.m1R7GN8L065275@hole.shrew.net>
Date: Wed, 27 Feb 2008 01:16:23 -0600 (CST)
From: Matthew Grooms <mgrooms@shrew.net>
Reply-To: Matthew Grooms <mgrooms@shrew.net>
To: FreeBSD-gnats-submit@freebsd.org
Cc: bzeeb-lists@lists.zabbadoz.net
Subject: FAST IPsec spd_delete2 bug ...
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         121140
>Category:       kern
>Synopsis:       [netipsec] [patch] FAST IPsec spd_delete2 bug ...
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bz
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 27 07:50:02 UTC 2008
>Closed-Date:    Sat Mar 08 18:51:33 UTC 2008
>Last-Modified:  Sat Mar 08 18:51:33 UTC 2008
>Originator:     Matthew Grooms
>Release:        FreeBSD 6.2-RELEASE i386
>Organization:
Shrew Soft Inc
>Environment:
System: FreeBSD hole.shrew.net 6.2-RELEASE FreeBSD 6.2-RELEASE #0: Tue May 15 17:47:14 UTC 2007 root@hole.shrew.net:/usr/obj/usr/src/sys/CUSTOM i386

I believe this effects all FreeBSD releases with FAST IPsec.

>Description:

There is a bug in /usr/src/sys/netipsec/key.c in FreeBSD FAST IPsec
sources. If an spd_delete2 message is submitted for an invalid policy
id, the kernel crashes.

>How-To-Repeat:

send an SADB_X_SPDDELETE2 message to PF_KEY with an invalid policy id.

>Fix:

Please apply this patch.

--- spddelete.diff begins here ---
--- key.c	Fri Feb 15 02:18:16 2008
+++ key.c.fixed	Fri Feb 15 02:18:35 2008
@@ -2125,7 +2125,7 @@
 	/* Is there SP in SPD ? */
 	if ((sp = key_getspbyid(id)) == NULL) {
 		ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id));
-		key_senderror(so, m, EINVAL);
+		return key_senderror(so, m, EINVAL);
 	}
 
 	sp->state = IPSEC_SPSTATE_DEAD;
--- spddelete.diff ends here ---
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->gnn 
Responsible-Changed-By: remko 
Responsible-Changed-When: Wed Feb 27 07:59:44 UTC 2008 
Responsible-Changed-Why:  
Over to maintainer. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121140 
Responsible-Changed-From-To: gnn->bz 
Responsible-Changed-By: bz 
Responsible-Changed-When: Wed Feb 27 08:30:39 UTC 2008 
Responsible-Changed-Why:  
That one was for me. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121140 

From: Matthew Grooms <mgrooms@shrew.net>
To: bug-followup@FreeBSD.org, mgrooms@shrew.net
Cc:  
Subject: Re: kern/121140: FAST IPsec spd_delete2 bug ...
Date: Wed, 27 Feb 2008 02:09:34 -0600

 Bjoern A. Zeeb requested that this PR be assigned to him.
 
 Reference:
 
 http://docs.freebsd.org/cgi/getmsg.cgi?fetch=8085+0+archive/2008/freebsd-net/20080224.freebsd-net
 
 Thanks,
 
 -Matthew
State-Changed-From-To: open->patched 
State-Changed-By: bz 
State-Changed-When: Fri Feb 29 22:03:22 UTC 2008 
State-Changed-Why:  
It seems this is fixed in various branches but I missed an MFC 
to older once. I'll do that the next days. I am checking if more 
seriously needed MFCs were missed a year ago. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121140 

From: "Bjoern A. Zeeb" <bz@FreeBSD.org>
To: bug-followup@FreeBSD.org, mgrooms@shrew.net
Cc:  
Subject: Re: kern/121140: FAST IPsec spd_delete2 bug ...
Date: Tue, 4 Mar 2008 21:45:14 +0000 (UTC)

 Hi,
 
 7 and HEAD should be fine.
 
 I have a more complete MFC patch to RELENG_6. Could you try that
 and report back if everything is fine for you with that one?
 
 You can also fetch it from
 http://sources.zabbadoz.net/freebsd/patchset/20080304-01-MFC-netipsec.diff
 
 
 Index: sys/netipsec/ipsec.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netipsec/ipsec.c,v
 retrieving revision 1.12
 diff -u -p -r1.12 ipsec.c
 --- sys/netipsec/ipsec.c	2 Jun 2005 23:56:10 -0000	1.12
 +++ sys/netipsec/ipsec.c	4 Mar 2008 20:22:21 -0000
 @@ -732,6 +732,7 @@ ipsec6_get_ulp(m, spidx, needport)
   	int off, nxt;
   	struct tcphdr th;
   	struct udphdr uh;
 +	struct icmp6_hdr ih;
 
   	/* sanity check */
   	if (m == NULL)
 @@ -772,6 +773,15 @@ ipsec6_get_ulp(m, spidx, needport)
   		((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport;
   		break;
   	case IPPROTO_ICMPV6:
 +		spidx->ul_proto = nxt;
 +		if (off + sizeof(struct icmp6_hdr) > m->m_pkthdr.len)
 +			break;
 +		m_copydata(m, off, sizeof(ih), (caddr_t)&ih);
 +		((struct sockaddr_in6 *)&spidx->src)->sin6_port =
 +		    htons((uint16_t)ih.icmp6_type);
 +		((struct sockaddr_in6 *)&spidx->dst)->sin6_port =
 +		    htons((uint16_t)ih.icmp6_code);
 +		break;
   	default:
   		/* XXX intermediate headers??? */
   		spidx->ul_proto = nxt;
 @@ -1825,12 +1835,12 @@ char *
   ipsec_address(union sockaddr_union* sa)
   {
   	switch (sa->sa.sa_family) {
 -#if INET
 +#ifdef INET
   	case AF_INET:
   		return inet_ntoa4(sa->sin.sin_addr);
   #endif /* INET */
 
 -#if INET6
 +#ifdef INET6
   	case AF_INET6:
   		return ip6_sprintf(&sa->sin6.sin6_addr);
   #endif /* INET6 */
 Index: sys/netipsec/ipsec_input.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netipsec/ipsec_input.c,v
 retrieving revision 1.9.2.2
 diff -u -p -r1.9.2.2 ipsec_input.c
 --- sys/netipsec/ipsec_input.c	24 Jul 2006 23:20:59 -0000	1.9.2.2
 +++ sys/netipsec/ipsec_input.c	4 Mar 2008 20:22:21 -0000
 @@ -100,7 +100,7 @@ static void ipsec4_common_ctlinput(int,
   /*
    * ipsec_common_input gets called when an IPsec-protected packet
    * is received by IPv4 or IPv6.  It's job is to find the right SA
 - # and call the appropriate transform.  The transform callback
 + * and call the appropriate transform.  The transform callback
    * takes care of further processing (like ingress filtering).
    */
   static int
 @@ -116,6 +116,10 @@ ipsec_common_input(struct mbuf *m, int s
 
   	IPSEC_ASSERT(m != NULL, ("null packet"));
 
 +	IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
 +		sproto == IPPROTO_IPCOMP,
 +		("unexpected security protocol %u", sproto));
 +
   	if ((sproto == IPPROTO_ESP && !esp_enable) ||
   	    (sproto == IPPROTO_AH && !ah_enable) ||
   	    (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
 @@ -436,7 +440,7 @@ ipsec4_common_input_cb(struct mbuf *m, s
   		tdbi->spi = sav->spi;
 
   		m_tag_prepend(m, mtag);
 -	} else {
 +	} else if (mt != NULL) {
   		mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
   		/* XXX do we need to mark m_flags??? */
   	}
 Index: sys/netipsec/ipsec_output.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netipsec/ipsec_output.c,v
 retrieving revision 1.10.8.1
 diff -u -p -r1.10.8.1 ipsec_output.c
 --- sys/netipsec/ipsec_output.c	24 Jul 2006 23:20:59 -0000	1.10.8.1
 +++ sys/netipsec/ipsec_output.c	4 Mar 2008 20:22:21 -0000
 @@ -559,7 +559,7 @@ ipsec6_output_trans(
   	IPSEC_ASSERT(tun != NULL, ("null tun"));
 
   	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 -		printf("%s: applyed SP\n", __func__);
 +		printf("%s: applied SP\n", __func__);
   		kdebug_secpolicy(sp));
 
   	isr = sp->req;
 @@ -685,7 +685,7 @@ ipsec6_output_tunnel(struct ipsec_output
   	IPSEC_ASSERT(sp != NULL, ("null sp"));
 
   	KEYDEBUG(KEYDEBUG_IPSEC_DATA,
 -		printf("%s: applyed SP\n", __func__);
 +		printf("%s: applied SP\n", __func__);
   		kdebug_secpolicy(sp));
 
   	m = state->m;
 Index: sys/netipsec/key.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netipsec/key.c,v
 retrieving revision 1.20.2.1
 diff -u -p -r1.20.2.1 key.c
 --- sys/netipsec/key.c	4 Sep 2006 15:17:50 -0000	1.20.2.1
 +++ sys/netipsec/key.c	4 Mar 2008 20:22:21 -0000
 @@ -2116,8 +2116,7 @@ key_spddelete2(so, m, mhp)
   	if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
   	    mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
   		ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", __func__));
 -		key_senderror(so, m, EINVAL);
 -		return 0;
 +		return key_senderror(so, m, EINVAL);
   	}
 
   	id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
 @@ -2125,7 +2124,7 @@ key_spddelete2(so, m, mhp)
   	/* Is there SP in SPD ? */
   	if ((sp = key_getspbyid(id)) == NULL) {
   		ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id));
 -		key_senderror(so, m, EINVAL);
 +		return key_senderror(so, m, EINVAL);
   	}
 
   	sp->state = IPSEC_SPSTATE_DEAD;
 @@ -2253,7 +2252,6 @@ key_spdacquire(sp)
   {
   	struct mbuf *result = NULL, *m;
   	struct secspacq *newspacq;
 -	int error;
 
   	IPSEC_ASSERT(sp != NULL, ("null secpolicy"));
   	IPSEC_ASSERT(sp->req == NULL, ("policy exists"));
 @@ -2281,10 +2279,9 @@ key_spdacquire(sp)
 
   	/* create new sadb_msg to reply. */
   	m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0);
 -	if (!m) {
 -		error = ENOBUFS;
 -		goto fail;
 -	}
 +	if (!m)
 +		return ENOBUFS;
 +
   	result = m;
 
   	result->m_pkthdr.len = 0;
 @@ -2295,11 +2292,6 @@ key_spdacquire(sp)
   	    PFKEY_UNIT64(result->m_pkthdr.len);
 
   	return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED);
 -
 -fail:
 -	if (result)
 -		m_freem(result);
 -	return error;
   }
 
   /*
 @@ -3205,7 +3197,12 @@ key_mature(struct secasvar *sav)
   	switch (sav->sah->saidx.proto) {
   	case IPPROTO_ESP:
   	case IPPROTO_AH:
 -		if (ntohl(sav->spi) >= 0 && ntohl(sav->spi) <= 255) {
 +		/*
 +		 * RFC 4302, 2.4. Security Parameters Index (SPI), SPI values
 +		 * 1-255 reserved by IANA for future use,
 +		 * 0 for implementation specific, local use.
 +		 */
 +		if (ntohl(sav->spi) <= 255) {
   			ipseclog((LOG_DEBUG, "%s: illegal range of SPI %u.\n",
   			    __func__, (u_int32_t)ntohl(sav->spi)));
   			return EINVAL;
 @@ -3961,6 +3958,7 @@ key_sockaddrcmp(
   		    satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) {
   			return 1;
   		}
 +		break;
   	default:
   		if (bcmp(sa1, sa2, sa1->sa_len) != 0)
   			return 1;
 
State-Changed-From-To: patched->closed 
State-Changed-By: bz 
State-Changed-When: Sat Mar 8 18:50:33 UTC 2008 
State-Changed-Why:  
I have MFCed all the changes from my patch. 
Thanks a lot for reporting. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121140 
>Unformatted:
