From owner-svn-src-projects@freebsd.org Sat Nov 19 19:23:12 2016 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EB49CC4BF1E for ; Sat, 19 Nov 2016 19:23:12 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C57F5C09; Sat, 19 Nov 2016 19:23:12 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uAJJNBEk037888; Sat, 19 Nov 2016 19:23:11 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uAJJNB2i037885; Sat, 19 Nov 2016 19:23:11 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201611191923.uAJJNB2i037885@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Sat, 19 Nov 2016 19:23:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r308862 - projects/ipsec/sys/netinet6 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Nov 2016 19:23:13 -0000 Author: ae Date: Sat Nov 19 19:23:11 2016 New Revision: 308862 URL: https://svnweb.freebsd.org/changeset/base/308862 Log: Change ip6_ipsec_output() to return only two values 0 and 1. It returns 1 when IPSec consumes mbuf or some fatal error occured. In case of error it frees mbuf. When no IPSec processing is required, it returns zero. Also change its prototype to take mbuf pointer, since we don't expect that mbuf can be changed, but not consumed. Add IPSEC_OUTPUT() wrapper macro to hide call to ip6_ipsec_output(). Add ipsec6_checkpolicy() function similar to ipsec4_checkpolicy(). Also change ipsec6_process_packet() to take security policy returned by ipsec6_checkpolicy() instead of accessing to ipsecrequest. Add inpcb pointer to arguments list, it will be needed to update hdrsz field of struct inpcbpolicy. Move IPSEC block to the top of ip6_output() to fix possible mbufs leak when IPv6 extension headers are present (MAKE_EXTHDR allocates mbufs). Modified: projects/ipsec/sys/netinet6/ip6_ipsec.c projects/ipsec/sys/netinet6/ip6_ipsec.h projects/ipsec/sys/netinet6/ip6_output.c Modified: projects/ipsec/sys/netinet6/ip6_ipsec.c ============================================================================== --- projects/ipsec/sys/netinet6/ip6_ipsec.c Sat Nov 19 19:06:29 2016 (r308861) +++ projects/ipsec/sys/netinet6/ip6_ipsec.c Sat Nov 19 19:23:11 2016 (r308862) @@ -141,15 +141,13 @@ ip6_ipsec_input(struct mbuf *m, int nxt) /* * Called from ip6_output(). - * 1 = drop packet, 0 = continue processing packet, - * -1 = packet was reinjected and stop processing packet + * 0 = continue processing packet + * 1 = packet was consumed, stop processing */ - int -ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error) +ip6_ipsec_output(struct mbuf *m, struct inpcb *inp, int *error) { struct secpolicy *sp; - /* * Check the security policy (SP) for the packet and, if * required, do IPsec-related processing. There are two @@ -159,11 +157,10 @@ ip6_ipsec_output(struct mbuf **m, struct * AH, ESP, etc. processing), there will be a tag to bypass * the lookup and related policy checking. */ - if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) { - *error = 0; + *error = 0; + if (m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) return (0); - } - sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp); + sp = ipsec6_checkpolicy(m, inp, error); /* * There are four return cases: * sp != NULL apply IPsec policy @@ -177,46 +174,35 @@ ip6_ipsec_output(struct mbuf **m, struct * this is done in the normal processing path. */ #ifdef INET - if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(*m); - (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } #endif - if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { - in6_delayed_cksum(*m, (*m)->m_pkthdr.len - sizeof(struct ip6_hdr), - sizeof(struct ip6_hdr)); - (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { + in6_delayed_cksum(m, m->m_pkthdr.len - + sizeof(struct ip6_hdr), sizeof(struct ip6_hdr)); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; } #ifdef SCTP - if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) { - sctp_delayed_cksum(*m, sizeof(struct ip6_hdr)); - (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; + if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) { + sctp_delayed_cksum(m, sizeof(struct ip6_hdr)); + m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; } #endif - /* NB: callee frees mbuf */ - *error = ipsec6_process_packet(*m, sp->req); - KEY_FREESP(&sp); + /* NB: callee frees mbuf and releases reference to SP */ + *error = ipsec6_process_packet(m, sp, inp); if (*error == EJUSTRETURN) { /* * We had a SP with a level of 'use' and no SA. We * will just continue to process the packet without - * IPsec processing. + * IPsec processing and return without error. */ *error = 0; - goto done; + return (0); } - - /* - * Preserve KAME behaviour: ENOENT can be returned - * when an SA acquire is in progress. Don't propagate - * this to user-level; it confuses applications. - * - * XXX this will go away when the SADB is redone. - */ - if (*error == ENOENT) - *error = 0; - goto reinjected; + return (1); /* mbuf consumed by IPsec */ } else { /* sp == NULL */ if (*error != 0) { /* @@ -227,18 +213,12 @@ ip6_ipsec_output(struct mbuf **m, struct */ if (*error == -EINVAL) *error = 0; - goto bad; + m_freem(m); + return (1); } /* No IPsec processing for this packet. */ } -done: return (0); -reinjected: - return (-1); -bad: - if (sp != NULL) - KEY_FREESP(&sp); - return (1); } #if 0 Modified: projects/ipsec/sys/netinet6/ip6_ipsec.h ============================================================================== --- projects/ipsec/sys/netinet6/ip6_ipsec.h Sat Nov 19 19:06:29 2016 (r308861) +++ projects/ipsec/sys/netinet6/ip6_ipsec.h Sat Nov 19 19:23:11 2016 (r308862) @@ -32,10 +32,12 @@ #ifndef _NETINET_IP6_IPSEC_H_ #define _NETINET_IP6_IPSEC_H_ +#define IPSEC_OUTPUT(sc, m, inp, perr) ip6_ipsec_output((m), (inp), (perr)) + int ip6_ipsec_filtertunnel(struct mbuf *); int ip6_ipsec_fwd(struct mbuf *); int ip6_ipsec_input(struct mbuf *, int); -int ip6_ipsec_output(struct mbuf **, struct inpcb *, int *); +int ip6_ipsec_output(struct mbuf *, struct inpcb *, int *); #if 0 int ip6_ipsec_mtu(struct mbuf *); #endif Modified: projects/ipsec/sys/netinet6/ip6_output.c ============================================================================== --- projects/ipsec/sys/netinet6/ip6_output.c Sat Nov 19 19:06:29 2016 (r308861) +++ projects/ipsec/sys/netinet6/ip6_output.c Sat Nov 19 19:23:11 2016 (r308862) @@ -335,6 +335,16 @@ ip6_output(struct mbuf *m0, struct ip6_p } } +#ifdef IPSEC + /* + * IPSec checking which handles several cases. + * FAST IPSEC: We re-injected the packet. + * XXX: need scope argument. + */ + if (IPSEC_OUTPUT(ipv6, m, inp, &error) != 0) + goto done; +#endif /* IPSEC */ + bzero(&exthdrs, sizeof(exthdrs)); if (opt) { /* Hop-by-Hop options header */ @@ -359,24 +369,6 @@ ip6_output(struct mbuf *m0, struct ip6_p MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2); } -#ifdef IPSEC - /* - * IPSec checking which handles several cases. - * FAST IPSEC: We re-injected the packet. - * XXX: need scope argument. - */ - switch(ip6_ipsec_output(&m, inp, &error)) - { - case 1: /* Bad packet */ - goto freehdrs; - case -1: /* IPSec done */ - goto done; - case 0: /* No IPSec */ - default: - break; - } -#endif /* IPSEC */ - /* * Calculate the total length of the extension header chain. * Keep the length of the unfragmentable part for fragmentation.