git: 439da7f06dce - main - if_stf: KASAN fix

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 30 Nov 2021 17:36:13 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=439da7f06dcea5af17e7d5b3b4784e54207194ac

commit 439da7f06dcea5af17e7d5b3b4784e54207194ac
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2021-11-30 15:30:22 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2021-11-30 16:35:15 +0000

    if_stf: KASAN fix
    
    In in_stf_input() we grabbed a pointer to the IPv4 header and later did
    an m_pullup() before we look at the IPv6 header. However, m_pullup()
    could rearrange the mbuf chain and potentially invalidate the pointer to
    the IPv4 header.
    
    Avoid this issue by copying the IP header rather than getting a pointer
    to it.
    
    Reported by:    markj, Jenkins (KASAN job)
    Reviewed by:    markj
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D33192
---
 sys/net/if_stf.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index 7807c6ebe7e9..51ea0a61ae0d 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -727,7 +727,7 @@ static int
 in_stf_input(struct mbuf *m, int off, int proto, void *arg)
 {
 	struct stf_softc *sc = arg;
-	struct ip *ip;
+	struct ip ip;
 	struct ip6_hdr *ip6;
 	u_int8_t otos, itos;
 	struct ifnet *ifp;
@@ -743,7 +743,7 @@ in_stf_input(struct mbuf *m, int off, int proto, void *arg)
 		return (IPPROTO_DONE);
 	}
 
-	ip = mtod(m, struct ip *);
+	m_copydata(m, 0, sizeof(struct ip), (caddr_t)&ip);
 	if (sc == NULL || (STF2IFP(sc)->if_flags & IFF_UP) == 0) {
 		m_freem(m);
 		SDT_PROBE2(if_stf, , stf_input, out, IPPROTO_DONE, __LINE__);
@@ -760,14 +760,14 @@ in_stf_input(struct mbuf *m, int off, int proto, void *arg)
 	 * perform sanity check against outer src/dst.
 	 * for source, perform ingress filter as well.
 	 */
-	if (stf_checkaddr4(sc, &ip->ip_dst, NULL) < 0 ||
-	    stf_checkaddr4(sc, &ip->ip_src, m->m_pkthdr.rcvif) < 0) {
+	if (stf_checkaddr4(sc, &ip.ip_dst, NULL) < 0 ||
+	    stf_checkaddr4(sc, &ip.ip_src, m->m_pkthdr.rcvif) < 0) {
 		m_freem(m);
 		SDT_PROBE2(if_stf, , stf_input, out, IPPROTO_DONE, __LINE__);
 		return (IPPROTO_DONE);
 	}
 
-	otos = ip->ip_tos;
+	otos = ip.ip_tos;
 	m_adj(m, off);
 
 	if (m->m_len < sizeof(*ip6)) {
@@ -795,8 +795,8 @@ in_stf_input(struct mbuf *m, int off, int proto, void *arg)
 	 * reject packets with private address range.
 	 * (requirement from RFC3056 section 2 1st paragraph)
 	 */
-	if ((IN6_IS_ADDR_6TO4(&ip6->ip6_src) && isrfc1918addr(&ip->ip_src)) ||
-	    (IN6_IS_ADDR_6TO4(&ip6->ip6_dst) && isrfc1918addr(&ip->ip_dst))) {
+	if ((IN6_IS_ADDR_6TO4(&ip6->ip6_src) && isrfc1918addr(&ip.ip_src)) ||
+	    (IN6_IS_ADDR_6TO4(&ip6->ip6_dst) && isrfc1918addr(&ip.ip_dst))) {
 		m_freem(m);
 		SDT_PROBE2(if_stf, , stf_input, out, IPPROTO_DONE, __LINE__);
 		return (IPPROTO_DONE);