Date: Wed, 24 Sep 2003 13:05:10 -0700 (PDT) From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 38531 for review Message-ID: <200309242005.h8OK5ADC012627@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=38531 Change 38531 by sam@sam_ebb on 2003/09/24 13:05:04 o hookup ipv4 ctlinput paths to a noop routine; we should be handling path mtu changes at least o correct potential null pointer deref in ipsec4_common_input_cb Affected files ... .. //depot/projects/netperf/sys/netinet/in_proto.c#3 edit .. //depot/projects/netperf/sys/netipsec/ipsec_input.c#6 edit .. //depot/projects/netperf/sys/netipsec/ipsec_output.c#5 edit Differences ... ==== //depot/projects/netperf/sys/netinet/in_proto.c#3 (text+ko) ==== @@ -160,13 +160,13 @@ #endif /* IPSEC */ #ifdef FAST_IPSEC { SOCK_RAW, &inetdomain, IPPROTO_AH, PR_ATOMIC|PR_ADDR, - ah4_input, 0, 0, 0, + ah4_input, 0, ah4_ctlinput, 0, 0, 0, 0, 0, 0, &nousrreqs }, { SOCK_RAW, &inetdomain, IPPROTO_ESP, PR_ATOMIC|PR_ADDR, - esp4_input, 0, 0, 0, + esp4_input, 0, esp4_ctlinput, 0, 0, 0, 0, 0, 0, &nousrreqs ==== //depot/projects/netperf/sys/netipsec/ipsec_input.c#6 (text+ko) ==== @@ -94,6 +94,8 @@ #define IPSEC_ISTAT(p,x,y,z) ((p) == IPPROTO_ESP ? (x)++ : \ (p) == IPPROTO_AH ? (y)++ : (z)++) +static void ipsec4_common_ctlinput(int, struct sockaddr *, void *, 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 @@ -231,12 +233,26 @@ { ipsec4_common_input(m, off, IPPROTO_AH); } +void +ah4_ctlinput(int cmd, struct sockaddr *sa, void *v) +{ + if (sa->sa_family == AF_INET && + sa->sa_len == sizeof(struct sockaddr_in)) + ipsec4_common_ctlinput(cmd, sa, v, IPPROTO_AH); +} void esp4_input(struct mbuf *m, int off) { ipsec4_common_input(m, off, IPPROTO_ESP); } +void +esp4_ctlinput(int cmd, struct sockaddr *sa, void *v) +{ + if (sa->sa_family == AF_INET && + sa->sa_len == sizeof(struct sockaddr_in)) + ipsec4_common_ctlinput(cmd, sa, v, IPPROTO_ESP); +} void ipcomp4_input(struct mbuf *m, int off) @@ -444,6 +460,12 @@ m_freem(m); return error; } + +void +ipsec4_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto) +{ + /* XXX nothing just yet */ +} #endif /* INET */ #ifdef INET6 @@ -493,82 +515,6 @@ return IPPROTO_DONE; } -void -esp6_ctlinput(int cmd, struct sockaddr *sa, void *d) -{ - if (sa->sa_family != AF_INET6 || - sa->sa_len != sizeof(struct sockaddr_in6)) - return; - if ((unsigned)cmd >= PRC_NCMDS) - return; - - /* if the parameter is from icmp6, decode it. */ - if (d != NULL) { - struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; - struct mbuf *m = ip6cp->ip6c_m; - int off = ip6cp->ip6c_off; - - struct ip6ctlparam ip6cp1; - - /* - * Notify the error to all possible sockets via pfctlinput2. - * Since the upper layer information (such as protocol type, - * source and destination ports) is embedded in the encrypted - * data and might have been cut, we can't directly call - * an upper layer ctlinput function. However, the pcbnotify - * function will consider source and destination addresses - * as well as the flow info value, and may be able to find - * some PCB that should be notified. - * Although pfctlinput2 will call esp6_ctlinput(), there is - * no possibility of an infinite loop of function calls, - * because we don't pass the inner IPv6 header. - */ - bzero(&ip6cp1, sizeof(ip6cp1)); - ip6cp1.ip6c_src = ip6cp->ip6c_src; - pfctlinput2(cmd, sa, (void *)&ip6cp1); - - /* - * Then go to special cases that need ESP header information. - * XXX: We assume that when ip6 is non NULL, - * M and OFF are valid. - */ - - if (cmd == PRC_MSGSIZE) { - struct secasvar *sav; - u_int32_t spi; - int valid; - - /* check header length before using m_copydata */ - if (m->m_pkthdr.len < off + sizeof (struct esp)) - return; - m_copydata(m, off + offsetof(struct esp, esp_spi), - sizeof(u_int32_t), (caddr_t) &spi); - /* - * Check to see if we have a valid SA corresponding to - * the address in the ICMP message payload. - */ - sav = KEY_ALLOCSA((union sockaddr_union *)sa, - IPPROTO_ESP, spi); - valid = (sav != NULL); - if (sav) - KEY_FREESAV(&sav); - - /* XXX Further validation? */ - - /* - * Depending on whether the SA is "valid" and - * routing table size (mtudisc_{hi,lo}wat), we will: - * - recalcurate the new MTU and create the - * corresponding routing entry, or - * - ignore the MTU change notification. - */ - icmp6_mtudisc_update(ip6cp, valid); - } - } else { - /* we normally notify any pcb here */ - } -} - /* * IPsec input callback, called by the transform callback. Takes care of * filtering and other sanity checks on the processed packet. @@ -738,7 +684,8 @@ m_tag_prepend(m, mtag); } else { - mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE; + if (mt != NULL) + mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE; /* XXX do we need to mark m_flags??? */ } @@ -788,4 +735,80 @@ m_freem(m); return error; } + +void +esp6_ctlinput(int cmd, struct sockaddr *sa, void *d) +{ + if (sa->sa_family != AF_INET6 || + sa->sa_len != sizeof(struct sockaddr_in6)) + return; + if ((unsigned)cmd >= PRC_NCMDS) + return; + + /* if the parameter is from icmp6, decode it. */ + if (d != NULL) { + struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; + struct mbuf *m = ip6cp->ip6c_m; + int off = ip6cp->ip6c_off; + + struct ip6ctlparam ip6cp1; + + /* + * Notify the error to all possible sockets via pfctlinput2. + * Since the upper layer information (such as protocol type, + * source and destination ports) is embedded in the encrypted + * data and might have been cut, we can't directly call + * an upper layer ctlinput function. However, the pcbnotify + * function will consider source and destination addresses + * as well as the flow info value, and may be able to find + * some PCB that should be notified. + * Although pfctlinput2 will call esp6_ctlinput(), there is + * no possibility of an infinite loop of function calls, + * because we don't pass the inner IPv6 header. + */ + bzero(&ip6cp1, sizeof(ip6cp1)); + ip6cp1.ip6c_src = ip6cp->ip6c_src; + pfctlinput2(cmd, sa, (void *)&ip6cp1); + + /* + * Then go to special cases that need ESP header information. + * XXX: We assume that when ip6 is non NULL, + * M and OFF are valid. + */ + + if (cmd == PRC_MSGSIZE) { + struct secasvar *sav; + u_int32_t spi; + int valid; + + /* check header length before using m_copydata */ + if (m->m_pkthdr.len < off + sizeof (struct esp)) + return; + m_copydata(m, off + offsetof(struct esp, esp_spi), + sizeof(u_int32_t), (caddr_t) &spi); + /* + * Check to see if we have a valid SA corresponding to + * the address in the ICMP message payload. + */ + sav = KEY_ALLOCSA((union sockaddr_union *)sa, + IPPROTO_ESP, spi); + valid = (sav != NULL); + if (sav) + KEY_FREESAV(&sav); + + /* XXX Further validation? */ + + /* + * Depending on whether the SA is "valid" and + * routing table size (mtudisc_{hi,lo}wat), we will: + * - recalcurate the new MTU and create the + * corresponding routing entry, or + * - ignore the MTU change notification. + */ + icmp6_mtudisc_update(ip6cp, valid); + } + } else { + /* we normally notify any pcb here */ + } +} #endif /* INET6 */ ==== //depot/projects/netperf/sys/netipsec/ipsec_output.c#5 (text+ko) ==== @@ -347,7 +347,7 @@ IPSEC_ASSERT(m != NULL, ("null mbuf")); IPSEC_ASSERT(isr != NULL, ("null isr")); - mtx_lock(&isr->lock); /* insure SA contents don't change */ + IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */ isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error); if (isr == NULL) @@ -466,10 +466,10 @@ } else { error = ipsec_process_done(m, isr); } - mtx_unlock(&isr->lock); + IPSECREQUEST_UNLOCK(isr); return error; bad: - mtx_unlock(&isr->lock); + IPSECREQUEST_UNLOCK(isr); if (m) m_freem(m); return error;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309242005.h8OK5ADC012627>