Module Name: src
Committed By: riastradh
Date: Tue Oct 8 02:28:43 UTC 2024
Modified Files:
src/tests/net/if_wg: t_basic.sh
Log Message:
wg(4): Test truncated UDP input from the network.
This triggers double-free in the IPv6 udp6_input path -- but,
confusingly, not the IPv4 udp_input path, even though the overudp_cb
interface ought to be the same:
/* udp_input -- no further use of m if return is -1 */
if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) {
UDP_STATINC(UDP_STAT_HDROPS);
return;
}
/* udp6_input -- m_freem if return is not 0 */
if (udp6_realinput(AF_INET6, &src, &dst, &m, off) == 0) {
...
}
bad:
m_freem(m);
return IPPROTO_DONE;
The subroutines udp4_realinput and udp6_realinput pass through the
return value of overudp_cb in essentially the same way:
/* udp4_realinput */
if (inp->inp_overudp_cb != NULL) {
int ret;
ret = inp->inp_overudp_cb(mp, off, inp->inp_socket,
sintosa(src), inp->inp_overudp_arg);
switch (ret) {
case -1: /* Error, m was freed */
rcvcnt = -1;
goto bad;
...
bad:
return rcvcnt;
/* udp6_realinput */
if (inp->inp_overudp_cb != NULL) {
int ret;
ret = inp->inp_overudp_cb(mp, off, inp->inp_socket,
sin6tosa(src), inp->inp_overudp_arg);
switch (ret) {
case -1: /* Error, m was freed */
rcvcnt = -1;
goto bad;
...
bad:
return rcvcnt;
PR kern/58688: userland panic of kernel via wg(4)
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/tests/net/if_wg/t_basic.sh
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/tests/net/if_wg/t_basic.sh
diff -u src/tests/net/if_wg/t_basic.sh:1.4 src/tests/net/if_wg/t_basic.sh:1.5
--- src/tests/net/if_wg/t_basic.sh:1.4 Tue Mar 2 07:16:24 2021
+++ src/tests/net/if_wg/t_basic.sh Tue Oct 8 02:28:43 2024
@@ -1,4 +1,4 @@
-# $NetBSD: t_basic.sh,v 1.4 2021/03/02 07:16:24 simonb Exp $
+# $NetBSD: t_basic.sh,v 1.5 2024/10/08 02:28:43 riastradh Exp $
#
# Copyright (c) 2018 Ryota Ozaki <[email protected]>
# All rights reserved.
@@ -48,6 +48,23 @@ check_ping_payload()
done
}
+check_badudp()
+{
+ local proto=$1
+ local ip=$2
+ local port=51820 # XXX parametrize more clearly
+
+ if [ $proto = inet ]; then
+ atf_check -o ignore -e ignore \
+ $HIJACKING nc -4uv -w1 $ip $port </dev/null
+ else
+ atf_check -o ignore -e ignore \
+ $HIJACKING nc -6uv -w1 $ip $port </dev/null
+ atf_expect_fail "PR kern/58688:" \
+ " userland panic of kernel via wg(4)"
+ fi
+}
+
test_common()
{
local type=$1
@@ -107,6 +124,9 @@ test_common()
elif [ $type = payload ]; then
export RUMP_SERVER=$SOCK_LOCAL
check_ping_payload $inner_proto $ip_wg_peer
+ elif [ $type = badudp ]; then
+ export RUMP_SERVER=$SOCK_LOCAL
+ check_badudp $outer_proto $ip_peer
fi
destroy_wg_interfaces
@@ -282,6 +302,36 @@ add_payload_sizes_test()
atf_add_test_case ${name}
}
+add_badudp_test()
+{
+ local inner=$1
+ local outer=$2
+ local ipv4=inet
+ local ipv6=inet6
+
+ name="wg_badudp_${inner}_over_${outer}"
+ fulldesc="Test wg(4) with ${inner} over ${outer} with bad UDP packets"
+
+ eval inner=\$$inner
+ eval outer=\$$outer
+
+ atf_test_case ${name} cleanup
+ eval "
+ ${name}_head() {
+ atf_set descr \"${fulldesc}\"
+ atf_set require.progs rump_server wgconfig wg-keygen nc
+ }
+ ${name}_body() {
+ test_common badudp $outer $inner
+ rump_server_destroy_ifaces
+ }
+ ${name}_cleanup() {
+ \$DEBUG && dump
+ cleanup
+ }"
+ atf_add_test_case ${name}
+}
+
atf_test_case wg_multiple_interfaces cleanup
wg_multiple_interfaces_head()
{
@@ -459,6 +509,11 @@ wg_multiple_peers_cleanup()
atf_init_test_cases()
{
+ add_badudp_test ipv4 ipv4
+ add_badudp_test ipv4 ipv6
+ add_badudp_test ipv6 ipv4
+ add_badudp_test ipv6 ipv6
+
add_basic_test ipv4 ipv4
add_basic_test ipv4 ipv6
add_basic_test ipv6 ipv4