Date: Mon, 12 Feb 2018 12:41:54 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r329157 - stable/11/sys/netinet6 Message-ID: <201802121241.w1CCfsb4021900@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Mon Feb 12 12:41:53 2018 New Revision: 329157 URL: https://svnweb.freebsd.org/changeset/base/329157 Log: MFC r328876: Modify ip6_get_prevhdr() to be able use it safely. Instead of returning pointer to the previous header, return its offset. In frag6_input() use m_copyback() and determined offset to store next header instead of accessing to it by pointer and assuming that the memory is contiguous. In rip6_input() use offset returned by ip6_get_prevhdr() instead of calculating it from pointers arithmetic, because IP header can belong to another mbuf in the chain. Reported by: Maxime Villard <max at m00nbsd dot net> Modified: stable/11/sys/netinet6/frag6.c stable/11/sys/netinet6/ip6_input.c stable/11/sys/netinet6/ip6_var.h stable/11/sys/netinet6/raw_ip6.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/netinet6/frag6.c ============================================================================== --- stable/11/sys/netinet6/frag6.c Mon Feb 12 10:34:15 2018 (r329156) +++ stable/11/sys/netinet6/frag6.c Mon Feb 12 12:41:53 2018 (r329157) @@ -575,10 +575,8 @@ insert: /* * Store NXT to the original. */ - { - char *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */ - *prvnxtp = nxt; - } + m_copyback(m, ip6_get_prevhdr(m, offset), sizeof(uint8_t), + (caddr_t)&nxt); frag6_remque(q6); V_frag6_nfrags -= q6->ip6q_nfrag; Modified: stable/11/sys/netinet6/ip6_input.c ============================================================================== --- stable/11/sys/netinet6/ip6_input.c Mon Feb 12 10:34:15 2018 (r329156) +++ stable/11/sys/netinet6/ip6_input.c Mon Feb 12 12:41:53 2018 (r329157) @@ -1625,49 +1625,39 @@ ip6_pullexthdr(struct mbuf *m, size_t off, int nxt) /* * Get pointer to the previous header followed by the header * currently processed. - * XXX: This function supposes that - * M includes all headers, - * the next header field and the header length field of each header - * are valid, and - * the sum of each header length equals to OFF. - * Because of these assumptions, this function must be called very - * carefully. Moreover, it will not be used in the near future when - * we develop `neater' mechanism to process extension headers. */ -char * +int ip6_get_prevhdr(const struct mbuf *m, int off) { - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); + struct ip6_ext ip6e; + struct ip6_hdr *ip6; + int len, nlen, nxt; if (off == sizeof(struct ip6_hdr)) - return (&ip6->ip6_nxt); - else { - int len, nxt; - struct ip6_ext *ip6e = NULL; + return (offsetof(struct ip6_hdr, ip6_nxt)); + if (off < sizeof(struct ip6_hdr)) + panic("%s: off < sizeof(struct ip6_hdr)", __func__); - nxt = ip6->ip6_nxt; - len = sizeof(struct ip6_hdr); - while (len < off) { - ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len); - - switch (nxt) { - case IPPROTO_FRAGMENT: - len += sizeof(struct ip6_frag); - break; - case IPPROTO_AH: - len += (ip6e->ip6e_len + 2) << 2; - break; - default: - len += (ip6e->ip6e_len + 1) << 3; - break; - } - nxt = ip6e->ip6e_nxt; + ip6 = mtod(m, struct ip6_hdr *); + nxt = ip6->ip6_nxt; + len = sizeof(struct ip6_hdr); + nlen = 0; + while (len < off) { + m_copydata(m, len, sizeof(ip6e), (caddr_t)&ip6e); + switch (nxt) { + case IPPROTO_FRAGMENT: + nlen = sizeof(struct ip6_frag); + break; + case IPPROTO_AH: + nlen = (ip6e.ip6e_len + 2) << 2; + break; + default: + nlen = (ip6e.ip6e_len + 1) << 3; } - if (ip6e) - return (&ip6e->ip6e_nxt); - else - return NULL; + len += nlen; + nxt = ip6e.ip6e_nxt; } + return (len - nlen); } /* Modified: stable/11/sys/netinet6/ip6_var.h ============================================================================== --- stable/11/sys/netinet6/ip6_var.h Mon Feb 12 10:34:15 2018 (r329156) +++ stable/11/sys/netinet6/ip6_var.h Mon Feb 12 12:41:53 2018 (r329157) @@ -362,7 +362,7 @@ void ip6_direct_input(struct mbuf *); void ip6_freepcbopts(struct ip6_pktopts *); int ip6_unknown_opt(u_int8_t *, struct mbuf *, int); -char * ip6_get_prevhdr(const struct mbuf *, int); +int ip6_get_prevhdr(const struct mbuf *, int); int ip6_nexthdr(const struct mbuf *, int, int, int *); int ip6_lasthdr(const struct mbuf *, int, int, int *); Modified: stable/11/sys/netinet6/raw_ip6.c ============================================================================== --- stable/11/sys/netinet6/raw_ip6.c Mon Feb 12 10:34:15 2018 (r329156) +++ stable/11/sys/netinet6/raw_ip6.c Mon Feb 12 12:41:53 2018 (r329157) @@ -323,12 +323,10 @@ rip6_input(struct mbuf **mp, int *offp, int proto) RIP6STAT_INC(rip6s_nosockmcast); if (proto == IPPROTO_NONE) m_freem(m); - else { - char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */ + else icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER, - prvnxtp - mtod(m, char *)); - } + ip6_get_prevhdr(m, *offp)); IP6STAT_DEC(ip6s_delivered); } return (IPPROTO_DONE);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802121241.w1CCfsb4021900>