wg: Check mbuf chain length before m_copydata.diff -r1.24 -r1.25 src/sys/net/if_wg.c
(riastradh)
--- src/sys/net/if_wg.c 2020/08/26 16:03:41 1.24
+++ src/sys/net/if_wg.c 2020/08/27 02:52:33 1.25
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if_wg.c,v 1.24 2020/08/26 16:03:41 riastradh Exp $ */ | 1 | /* $NetBSD: if_wg.c,v 1.25 2020/08/27 02:52:33 riastradh Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> | 4 | * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -31,27 +31,27 @@ | @@ -31,27 +31,27 @@ | |||
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * This network interface aims to implement the WireGuard protocol. | 33 | * This network interface aims to implement the WireGuard protocol. | |
34 | * The implementation is based on the paper of WireGuard as of | 34 | * The implementation is based on the paper of WireGuard as of | |
35 | * 2018-06-30 [1]. The paper is referred in the source code with label | 35 | * 2018-06-30 [1]. The paper is referred in the source code with label | |
36 | * [W]. Also the specification of the Noise protocol framework as of | 36 | * [W]. Also the specification of the Noise protocol framework as of | |
37 | * 2018-07-11 [2] is referred with label [N]. | 37 | * 2018-07-11 [2] is referred with label [N]. | |
38 | * | 38 | * | |
39 | * [1] https://www.wireguard.com/papers/wireguard.pdf | 39 | * [1] https://www.wireguard.com/papers/wireguard.pdf | |
40 | * [2] http://noiseprotocol.org/noise.pdf | 40 | * [2] http://noiseprotocol.org/noise.pdf | |
41 | */ | 41 | */ | |
42 | 42 | |||
43 | #include <sys/cdefs.h> | 43 | #include <sys/cdefs.h> | |
44 | __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.24 2020/08/26 16:03:41 riastradh Exp $"); | 44 | __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.25 2020/08/27 02:52:33 riastradh Exp $"); | |
45 | 45 | |||
46 | #ifdef _KERNEL_OPT | 46 | #ifdef _KERNEL_OPT | |
47 | #include "opt_inet.h" | 47 | #include "opt_inet.h" | |
48 | #endif | 48 | #endif | |
49 | 49 | |||
50 | #include <sys/param.h> | 50 | #include <sys/param.h> | |
51 | #include <sys/systm.h> | 51 | #include <sys/systm.h> | |
52 | #include <sys/kernel.h> | 52 | #include <sys/kernel.h> | |
53 | #include <sys/mbuf.h> | 53 | #include <sys/mbuf.h> | |
54 | #include <sys/socket.h> | 54 | #include <sys/socket.h> | |
55 | #include <sys/sockio.h> | 55 | #include <sys/sockio.h> | |
56 | #include <sys/errno.h> | 56 | #include <sys/errno.h> | |
57 | #include <sys/ioctl.h> | 57 | #include <sys/ioctl.h> | |
@@ -2905,29 +2905,45 @@ wg_so_upcall(struct socket *so, void *ar | @@ -2905,29 +2905,45 @@ wg_so_upcall(struct socket *so, void *ar | |||
2905 | wg_wakeup_worker(wgw, reason); | 2905 | wg_wakeup_worker(wgw, reason); | |
2906 | } | 2906 | } | |
2907 | 2907 | |||
2908 | static int | 2908 | static int | |
2909 | wg_overudp_cb(struct mbuf **mp, int offset, struct socket *so, | 2909 | wg_overudp_cb(struct mbuf **mp, int offset, struct socket *so, | |
2910 | struct sockaddr *src, void *arg) | 2910 | struct sockaddr *src, void *arg) | |
2911 | { | 2911 | { | |
2912 | struct wg_softc *wg = arg; | 2912 | struct wg_softc *wg = arg; | |
2913 | struct wg_msg wgm; | 2913 | struct wg_msg wgm; | |
2914 | struct mbuf *m = *mp; | 2914 | struct mbuf *m = *mp; | |
2915 | 2915 | |||
2916 | WG_TRACE("enter"); | 2916 | WG_TRACE("enter"); | |
2917 | 2917 | |||
2918 | /* Verify the mbuf chain is long enough to have a wg msg header. */ | |||
2919 | KASSERT(offset <= m_length(m)); | |||
2920 | if (__predict_false(m_length(m) - offset < sizeof(struct wg_msg))) { | |||
2921 | m_freem(m); | |||
2922 | return -1; | |||
2923 | } | |||
2924 | ||||
2925 | /* | |||
2926 | * Copy the message header (32-bit message type) out -- we'll | |||
2927 | * worry about contiguity and alignment later. | |||
2928 | */ | |||
2918 | m_copydata(m, offset, sizeof(struct wg_msg), &wgm); | 2929 | m_copydata(m, offset, sizeof(struct wg_msg), &wgm); | |
2919 | WG_DLOG("type=%d\n", wgm.wgm_type); | 2930 | WG_DLOG("type=%d\n", wgm.wgm_type); | |
2920 | 2931 | |||
2932 | /* | |||
2933 | * Handle DATA packets promptly as they arrive. Other packets | |||
2934 | * may require expensive public-key crypto and are not as | |||
2935 | * sensitive to latency, so defer them to the worker thread. | |||
2936 | */ | |||
2921 | switch (wgm.wgm_type) { | 2937 | switch (wgm.wgm_type) { | |
2922 | case WG_MSG_TYPE_DATA: | 2938 | case WG_MSG_TYPE_DATA: | |
2923 | m_adj(m, offset); | 2939 | m_adj(m, offset); | |
2924 | wg_handle_msg_data(wg, m, src); | 2940 | wg_handle_msg_data(wg, m, src); | |
2925 | *mp = NULL; | 2941 | *mp = NULL; | |
2926 | return 1; | 2942 | return 1; | |
2927 | default: | 2943 | default: | |
2928 | break; | 2944 | break; | |
2929 | } | 2945 | } | |
2930 | 2946 | |||
2931 | return 0; | 2947 | return 0; | |
2932 | } | 2948 | } | |
2933 | 2949 |
--- src/tests/net/if_wg/t_misc.sh 2020/08/27 02:51:49 1.2
+++ src/tests/net/if_wg/t_misc.sh 2020/08/27 02:52:33 1.3
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | # $NetBSD: t_misc.sh,v 1.2 2020/08/27 02:51:49 riastradh Exp $ | 1 | # $NetBSD: t_misc.sh,v 1.3 2020/08/27 02:52:33 riastradh Exp $ | |
2 | # | 2 | # | |
3 | # Copyright (c) 2018 Ryota Ozaki <ozaki.ryota@gmail.com> | 3 | # Copyright (c) 2018 Ryota Ozaki <ozaki.ryota@gmail.com> | |
4 | # All rights reserved. | 4 | # All rights reserved. | |
5 | # | 5 | # | |
6 | # Redistribution and use in source and binary forms, with or without | 6 | # Redistribution and use in source and binary forms, with or without | |
7 | # modification, are permitted provided that the following conditions | 7 | # modification, are permitted provided that the following conditions | |
8 | # are met: | 8 | # are met: | |
9 | # 1. Redistributions of source code must retain the above copyright | 9 | # 1. Redistributions of source code must retain the above copyright | |
10 | # notice, this list of conditions and the following disclaimer. | 10 | # notice, this list of conditions and the following disclaimer. | |
11 | # 2. Redistributions in binary form must reproduce the above copyright | 11 | # 2. Redistributions in binary form must reproduce the above copyright | |
12 | # notice, this list of conditions and the following disclaimer in the | 12 | # notice, this list of conditions and the following disclaimer in the | |
13 | # documentation and/or other materials provided with the distribution. | 13 | # documentation and/or other materials provided with the distribution. | |
14 | # | 14 | # | |
@@ -578,23 +578,96 @@ wg_psk_body() | @@ -578,23 +578,96 @@ wg_psk_body() | |||
578 | 578 | |||
579 | rm -f $pskfile | 579 | rm -f $pskfile | |
580 | 580 | |||
581 | destroy_wg_interfaces | 581 | destroy_wg_interfaces | |
582 | } | 582 | } | |
583 | 583 | |||
584 | wg_psk_cleanup() | 584 | wg_psk_cleanup() | |
585 | { | 585 | { | |
586 | 586 | |||
587 | $DEBUG && dump | 587 | $DEBUG && dump | |
588 | cleanup | 588 | cleanup | |
589 | } | 589 | } | |
590 | 590 | |||
591 | atf_test_case wg_malformed cleanup | |||
592 | wg_malformed_head() | |||
593 | { | |||
594 | ||||
595 | atf_set "descr" "tests malformed packet headers" | |||
596 | atf_set "require.progs" "nc" "rump_server" "wgconfig" "wg-keygen" | |||
597 | atf_set "timeout" "10" | |||
598 | } | |||
599 | ||||
600 | wg_malformed_body() | |||
601 | { | |||
602 | local ifconfig="atf_check -s exit:0 rump.ifconfig" | |||
603 | local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1" | |||
604 | local ip_local=192.168.1.1 | |||
605 | local ip_peer=192.168.1.2 | |||
606 | local ip_wg_local=10.0.0.1 | |||
607 | local ip_wg_peer=10.0.0.2 | |||
608 | local port=51820 | |||
609 | setup_servers | |||
610 | ||||
611 | # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer | |||
612 | generate_keys | |||
613 | ||||
614 | export RUMP_SERVER=$SOCK_LOCAL | |||
615 | setup_common shmif0 inet $ip_local 24 | |||
616 | setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" | |||
617 | ||||
618 | export RUMP_SERVER=$SOCK_PEER | |||
619 | setup_common shmif0 inet $ip_peer 24 | |||
620 | setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" | |||
621 | ||||
622 | export RUMP_SERVER=$SOCK_LOCAL | |||
623 | add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 | |||
624 | ||||
625 | export RUMP_SERVER=$SOCK_PEER | |||
626 | add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 | |||
627 | ||||
628 | export RUMP_SERVER=$SOCK_LOCAL | |||
629 | ||||
630 | $ping $ip_wg_peer | |||
631 | ||||
632 | printf 'send malformed packets\n' | |||
633 | ||||
634 | $HIJACKING ping -c 1 -n $ip_peer | |||
635 | ||||
636 | printf 'x' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
637 | printf 'xy' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
638 | printf 'xyz' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
639 | printf 'xyzw' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
640 | printf '\x00\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
641 | printf '\x00\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
642 | printf '\x01\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
643 | printf '\x01\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
644 | printf '\x02\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
645 | printf '\x02\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
646 | printf '\x03\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
647 | printf '\x03\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
648 | printf '\x04\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
649 | printf '\x04\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port | |||
650 | ||||
651 | printf 'done sending malformed packets\n' | |||
652 | ||||
653 | $ping $ip_wg_peer | |||
654 | } | |||
655 | ||||
656 | wg_malformed_cleanup() | |||
657 | { | |||
658 | ||||
659 | $DEBUG && dump | |||
660 | cleanup | |||
661 | } | |||
662 | ||||
591 | atf_init_test_cases() | 663 | atf_init_test_cases() | |
592 | { | 664 | { | |
593 | 665 | |||
594 | atf_add_test_case wg_rekey | 666 | atf_add_test_case wg_rekey | |
595 | atf_add_test_case wg_handshake_timeout | 667 | atf_add_test_case wg_handshake_timeout | |
596 | atf_add_test_case wg_cookie | 668 | atf_add_test_case wg_cookie | |
597 | atf_add_test_case wg_mobility | 669 | atf_add_test_case wg_mobility | |
598 | atf_add_test_case wg_keepalive | 670 | atf_add_test_case wg_keepalive | |
599 | atf_add_test_case wg_psk | 671 | atf_add_test_case wg_psk | |
672 | atf_add_test_case wg_malformed | |||
600 | } | 673 | } |