git: 6ba6c05cb2d4 - main - if_ovpn: deal with short packets

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 05 Jul 2022 17:55:48 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=6ba6c05cb2d4dd6510637fecb31e2b66e7495467

commit 6ba6c05cb2d4dd6510637fecb31e2b66e7495467
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-07-05 17:27:00 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-07-05 17:27:00 +0000

    if_ovpn: deal with short packets
    
    If we receive a UDP packet (directed towards an active OpenVPN socket)
    which is too short to contain an OpenVPN header ('struct
    ovpn_wire_header') we wound up making m_copydata() read outside the
    mbuf, and panicking the machine.
    
    Explicitly check that the packet is long enough to copy the data we're
    interested in. If it's not we will pass the packet to userspace, just
    like we'd do for an unknown peer.
    
    Extend a test case to provoke this situation.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/net/if_ovpn.c                | 7 +++++--
 tests/sys/net/if_ovpn/if_ovpn.sh | 1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 9430d1cebe56..779d51075e3d 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -2080,11 +2080,14 @@ ovpn_peer_from_mbuf(struct ovpn_softc *sc, struct mbuf *m, int off)
 {
 	struct ovpn_wire_header ohdr;
 	uint32_t peerid;
+	const size_t hdrlen = sizeof(ohdr) - sizeof(ohdr.auth_tag);
 
 	OVPN_RASSERT(sc);
 
-	m_copydata(m, off + sizeof(struct udphdr),
-	    sizeof(ohdr) - sizeof(ohdr.auth_tag), (caddr_t)&ohdr);
+	if (m_length(m, NULL) < (off + sizeof(struct udphdr) + hdrlen))
+		return (NULL);
+
+	m_copydata(m, off + sizeof(struct udphdr), hdrlen, (caddr_t)&ohdr);
 
 	peerid = ntohl(ohdr.opcode) & 0x00ffffff;
 
diff --git a/tests/sys/net/if_ovpn/if_ovpn.sh b/tests/sys/net/if_ovpn/if_ovpn.sh
index fb32e3ed1895..faf21d5669b1 100644
--- a/tests/sys/net/if_ovpn/if_ovpn.sh
+++ b/tests/sys/net/if_ovpn/if_ovpn.sh
@@ -91,6 +91,7 @@ atf_test_case "4in4" "cleanup"
 	# Give the tunnel time to come up
 	sleep 10
 
+	echo 'foo' | jexec b nc -u -w 2 192.0.2.1 1194
 	atf_check -s exit:0 -o ignore jexec b ping -c 3 198.51.100.1
 }