From nobody@FreeBSD.org  Wed Mar  5 10:59:37 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 81B4F106567B
	for <freebsd-gnats-submit@FreeBSD.org>; Wed,  5 Mar 2008 10:59:37 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 6C2618FC2C
	for <freebsd-gnats-submit@FreeBSD.org>; Wed,  5 Mar 2008 10:59:37 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m25AuaXs054967
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 5 Mar 2008 10:56:36 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id m25Auaek054966;
	Wed, 5 Mar 2008 10:56:36 GMT
	(envelope-from nobody)
Message-Id: <200803051056.m25Auaek054966@www.freebsd.org>
Date: Wed, 5 Mar 2008 10:56:36 GMT
From: Cyrus Rahman <crahman@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: New IPSEC fails to obey policy levels
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         121384
>Category:       kern
>Synopsis:       [ipsec] New IPSEC fails to obey policy levels
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bz
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Mar 05 11:00:03 UTC 2008
>Closed-Date:    Fri Mar 21 23:22:35 UTC 2008
>Last-Modified:  Fri Mar 21 23:30:01 UTC 2008
>Originator:     Cyrus Rahman
>Release:        7.0-RELEASE
>Organization:
>Environment:
FreeBSD snowfall.signetica.com 7.0-RELEASE FreeBSD 7.0-RELEASE #7: Wed Mar  5 00:48:02 MST 2008     cr@snowfall.signetica.com:/usr/src/sys/i386/compile/SIGNETICA  i386

>Description:
IPSEC policies include a level: default, use, require, or unique.  A level of 'use' should mean that the kernel will use an SA if available, otherwise it should pass the packet as it would normally.  However, with the new IPSEC this level is ignored and packets are discarded if the SA is not available.
>How-To-Repeat:
Between two hosts with no security associations and which are not running anything to set up such associations, check for connectivity with ping:

From hostA:
root# ping hostB
...echo replies

Install a policy like this on hostA:
spdadd -4 hostA hostB any -P out ipsec
        esp/transport//use;
spdadd -4 hostB hostA any -P in ipsec
        esp/transport//use;

Things should continue to work, however:

root# ping hostB
ping: sendto: Invalid argument
ping: sendto: Invalid argument

>Fix:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: bz 
Responsible-Changed-When: Wed Mar 5 11:16:13 UTC 2008 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121384 
State-Changed-From-To: open->feedback 
State-Changed-By: bz 
State-Changed-When: Sat Mar 8 22:38:07 UTC 2008 
State-Changed-Why:  
A patch was presented for testing. 


Responsible-Changed-From-To: freebsd-net->bz 
Responsible-Changed-By: bz 
Responsible-Changed-When: Sat Mar 8 22:38:07 UTC 2008 
Responsible-Changed-Why:  
Take this one, as I have a patch. 

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

From: "Bjoern A. Zeeb" <bz@FreeBSD.org>
To: bug-followup@FreeBSD.org, crahman@gmail.com
Cc:  
Subject: Re: kern/121384: New IPSEC fails to obey policy levels
Date: Sat, 8 Mar 2008 22:37:53 +0000 (UTC)

 Hi,
 
 can you try this patch and report back? (if possible also check
 require, etc. still work as expected).
 
 You can also fetch the patch from
 http://sources.zabbadoz.net/freebsd/patchset/20080308-01-netipsec-level-use-pr121384.diff
 
 
 Index: sys/netinet/ip_ipsec.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netinet/ip_ipsec.c,v
 retrieving revision 1.8
 diff -u -p -r1.8 ip_ipsec.c
 --- sys/netinet/ip_ipsec.c	7 Oct 2007 20:44:23 -0000	1.8
 +++ sys/netinet/ip_ipsec.c	8 Mar 2008 22:31:54 -0000
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD: src/sys/netinet/ip_i
 
   #include <sys/param.h>
   #include <sys/systm.h>
 +#include <sys/errno.h>
   #include <sys/kernel.h>
   #include <sys/malloc.h>
   #include <sys/mbuf.h>
 @@ -330,6 +331,17 @@ ip_ipsec_output(struct mbuf **m, struct
   		/* NB: callee frees mbuf */
   		*error = ipsec4_process_packet(*m, sp->req, *flags, 0);
   		/*
 +		 * In case error is -1 we had a SP with level of 'use'
 +		 * and no SA. We will return no error and just continue
 +		 * to process the packet w/o IPsec.
 +		 */
 +		if (*error == EJUSTRETURN) {
 +			*error = 0;
 +			ip->ip_len = ntohs(ip->ip_len);
 +			ip->ip_off = ntohs(ip->ip_off);
 +			goto done;
 +		}
 +		/*
   		 * Preserve KAME behaviour: ENOENT can be returned
   		 * when an SA acquire is in progress.  Don't propagate
   		 * this to user-level; it confuses applications.
 Index: sys/netinet6/ip6_output.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netinet6/ip6_output.c,v
 retrieving revision 1.114
 diff -u -p -r1.114 ip6_output.c
 --- sys/netinet6/ip6_output.c	2 Feb 2008 14:11:31 -0000	1.114
 +++ sys/netinet6/ip6_output.c	8 Mar 2008 22:31:54 -0000
 @@ -384,7 +384,9 @@ ip6_output(struct mbuf *m0, struct ip6_p
   	error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
   				    &needipsectun);
   	m = state.m;
 -	if (error) {
 +	if (error == EJUSTRETURN) {
 +		goto skip_ipsec2;
 +	} else if (error) {
   		/* mbuf is already reclaimed in ipsec6_output_trans. */
   		m = NULL;
   		switch (error) {
 @@ -395,7 +397,8 @@ ip6_output(struct mbuf *m0, struct ip6_p
   		case ENOMEM:
   			break;
   		default:
 -			printf("ip6_output (ipsec): error code %d\n", error);
 +			printf("[%s:%d] (ipsec): error code %d\n",
 +			    __func__, __LINE__, error);
   			/* FALLTHROUGH */
   		case ENOENT:
   			/* don't show these error codes to the user */
 @@ -550,7 +553,10 @@ again:
   		m = state.m;
   		ro = (struct route_in6 *)state.ro;
   		dst = (struct sockaddr_in6 *)state.dst;
 -		if (error) {
 +		if (error == EJUSTRETURN) {
 +			exthdrs.ip6e_ip6 = m;
 +
 +		} else if (error) {
   			/* mbuf is already reclaimed in ipsec6_output_tunnel. */
   			m0 = m = NULL;
   			m = NULL;
 @@ -562,7 +568,8 @@ again:
   			case ENOMEM:
   				break;
   			default:
 -				printf("ip6_output (ipsec): error code %d\n", error);
 +				printf("[%s:%d] (ipsec): error code %d\n",
 +				    __func__, __LINE__, error);
   				/* FALLTHROUGH */
   			case ENOENT:
   				/* don't show these error codes to the user */
 @@ -580,8 +587,6 @@ again:
   			m = NULL;
   			goto done;
   		}
 -
 -		exthdrs.ip6e_ip6 = m;
   	}
   #endif /* IPSEC */
 
 Index: sys/netipsec/ipsec_output.c
 ===================================================================
 RCS file: /shared/mirror/FreeBSD/r/ncvs/src/sys/netipsec/ipsec_output.c,v
 retrieving revision 1.17
 diff -u -p -r1.17 ipsec_output.c
 --- sys/netipsec/ipsec_output.c	28 Nov 2007 22:33:52 -0000	1.17
 +++ sys/netipsec/ipsec_output.c	8 Mar 2008 22:31:54 -0000
 @@ -203,7 +203,6 @@ ipsec_nextisr(
   {
   #define IPSEC_OSTAT(x,y,z) (isr->saidx.proto == IPPROTO_ESP ? (x)++ : \
   			    isr->saidx.proto == IPPROTO_AH ? (y)++ : (z)++)
 -	struct secasvar *sav;
 
   	IPSEC_SPLASSERT_SOFTNET(__func__);
   	IPSECREQUEST_LOCK_ASSERT(isr);
 @@ -285,18 +284,18 @@ again:
   		ipsec4stat.ips_out_nosa++;
   		goto bad;
   	}
 -	sav = isr->sav;
 -	if (sav == NULL) {		/* XXX valid return */
 +	if (isr->sav == NULL) {
   		IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
 -			("no SA found, but required; level %u",
 +		    ("no SA found, but required; level %u",
   			ipsec_get_reqlevel(isr)));
   		IPSECREQUEST_UNLOCK(isr);
   		isr = isr->next;
 -		if (isr == NULL) {
 -			/*XXXstatistic??*/
 -			*error = EINVAL;		/*XXX*/
 +		/*
 +		 * Found a 'use' policy w/o SA and nothing more.
 +		 * Return w/o error and w/o isr.
 +		 */
 +		if (isr == NULL)
   			return isr;
 -		}
   		IPSECREQUEST_LOCK(isr);
   		goto again;
   	}
 @@ -319,7 +318,7 @@ again:
   	 * Sanity check the SA contents for the caller
   	 * before they invoke the xform output method.
   	 */
 -	if (sav->tdb_xform == NULL) {
 +	if (isr->sav->tdb_xform == NULL) {
   		DPRINTF(("%s: no transform for SA\n", __func__));
   		IPSEC_OSTAT(espstat.esps_noxform, ahstat.ahs_noxform,
   		    ipcompstat.ipcomps_noxform);
 @@ -356,8 +355,11 @@ ipsec4_process_packet(
   	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
 
   	isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
 -	if (isr == NULL)
 -		goto bad;
 +	if (isr == NULL) {
 +		if (error != 0)
 +			goto bad;
 +		return EJUSTRETURN;
 +	}
 
   	sav = isr->sav;
 
 @@ -581,21 +583,24 @@ ipsec6_output_trans(
   	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
   	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
   	if (isr == NULL) {
 +		if (error != 0) {
   #ifdef notdef
 -		/* XXX should notification be done for all errors ? */
 -		/*
 -		 * Notify the fact that the packet is discarded
 -		 * to ourselves. I believe this is better than
 -		 * just silently discarding. (jinmei@kame.net)
 -		 * XXX: should we restrict the error to TCP packets?
 -		 * XXX: should we directly notify sockets via
 -		 *      pfctlinputs?
 -		 */
 -		icmp6_error(m, ICMP6_DST_UNREACH,
 -			    ICMP6_DST_UNREACH_ADMIN, 0);
 -		m = NULL;	/* NB: icmp6_error frees mbuf */
 +			/* XXX should notification be done for all errors ? */
 +			/*
 +			 * Notify the fact that the packet is discarded
 +			 * to ourselves. I believe this is better than
 +			 * just silently discarding. (jinmei@kame.net)
 +			 * XXX: should we restrict the error to TCP packets?
 +			 * XXX: should we directly notify sockets via
 +			 *      pfctlinputs?
 +			 */
 +			icmp6_error(m, ICMP6_DST_UNREACH,
 +				    ICMP6_DST_UNREACH_ADMIN, 0);
 +			m = NULL;	/* NB: icmp6_error frees mbuf */
   #endif
 -		goto bad;
 +			goto bad;
 +		}
 +		return EJUSTRETURN;
   	}
 
   	error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
 @@ -712,8 +717,11 @@ ipsec6_output_tunnel(struct ipsec_output
 
   	IPSECREQUEST_LOCK(isr);		/* insure SA contents don't change */
   	isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
 -	if (isr == NULL)
 -		goto bad;
 +	if (isr == NULL) {
 +		if (error != 0)
 +			goto bad;
 +		return EJUSTRETURN; 
 +	}
 
   #ifdef DEV_ENC
   	/* pass the mbuf to enc0 for bpf processing */
 
 
 -- 
 Bjoern A. Zeeb                                 bzeeb at Zabbadoz dot NeT
 Software is harder than hardware  so better get it right the first time.

From: "Cyrus Rahman" <crahman@gmail.com>
To: "Bjoern A. Zeeb" <bz@freebsd.org>, bug-followup@freebsd.org
Cc:  
Subject: Re: kern/121384: New IPSEC fails to obey policy levels
Date: Wed, 12 Mar 2008 19:07:13 -0600

 Hi,
 
 > can you try this patch and report back? (if possible also check
 > require, etc. still work as expected).
 
 I've tested this patch in a variety of situations and it seems correct.
 
 Thanks!
State-Changed-From-To: feedback->patched 
State-Changed-By: bz 
State-Changed-When: Fri Mar 14 16:39:53 UTC 2008 
State-Changed-Why:  
A slightly different patch (less whitespace changes, one fix) 
was committed and will me MFCed. 

And updated patch can (temporary) be found here: 
http://sources.zabbadoz.net/freebsd/patchset/20080314-02-netipsec-level-use-pr121384.diff 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/121384: commit references a PR
Date: Fri, 14 Mar 2008 16:38:22 +0000 (UTC)

 bz          2008-03-14 16:38:11 UTC
 
   FreeBSD src repository
 
   Modified files:
     sys/netinet          ip_ipsec.c 
     sys/netinet6         ip6_output.c 
     sys/netipsec         ipsec_output.c 
   Log:
   Correct IPsec behaviour with a 'use' level in SP but no SA available.
   In that case return an continue processing the packet without IPsec.
   
   PR:             121384
   MFC after:      5 days
   Reported by:    Cyrus Rahman (crahman gmail.com)
   Tested by:      Cyrus Rahman (crahman gmail.com) [slightly older version]
   
   Revision  Changes    Path
   1.9       +12 -0     src/sys/netinet/ip_ipsec.c
   1.117     +16 -2     src/sys/netinet6/ip6_output.c
   1.18      +33 -22    src/sys/netipsec/ipsec_output.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: bz 
State-Changed-When: Fri Mar 21 23:22:12 UTC 2008 
State-Changed-Why:  
Patch MFCed. Thanks for reporting and testing. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/121384: commit references a PR
Date: Fri, 21 Mar 2008 23:22:13 +0000 (UTC)

 bz          2008-03-21 23:22:07 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_7)
     sys/netinet          ip_ipsec.c 
     sys/netinet6         ip6_output.c 
     sys/netipsec         ipsec_output.c 
   Log:
   MFC: rev. 1.9 ip_ipsec.c, 1.117 ip6_output.c, 1.18 ipsec_output.c
   
     Correct IPsec behaviour with a 'use' level in SP but no SA available.
     In that case return an continue processing the packet without IPsec.
   
     PR:             121384
     Reported by:    Cyrus Rahman (crahman gmail.com)
     Tested by:      Cyrus Rahman (crahman gmail.com) [slightly older version]
   
   Revision   Changes    Path
   1.8.2.1    +12 -0     src/sys/netinet/ip_ipsec.c
   1.109.2.6  +16 -2     src/sys/netinet6/ip6_output.c
   1.16.2.1   +33 -22    src/sys/netipsec/ipsec_output.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
>Unformatted:
