From 6ba6c05cb2d4dd6510637fecb31e2b66e7495467 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Tue, 5 Jul 2022 19:27:00 +0200 Subject: [PATCH] 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 }