Thu Aug 27 02:53:47 2020 UTC ()
wg: Use m_pullup to make message header contiguous before processing.


(riastradh)
diff -r1.25 -r1.26 src/sys/net/if_wg.c

cvs diff -r1.25 -r1.26 src/sys/net/if_wg.c (expand / switch to unified diff)

--- src/sys/net/if_wg.c 2020/08/27 02:52:33 1.25
+++ src/sys/net/if_wg.c 2020/08/27 02:53:47 1.26
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_wg.c,v 1.25 2020/08/27 02:52:33 riastradh Exp $ */ 1/* $NetBSD: if_wg.c,v 1.26 2020/08/27 02:53:47 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.25 2020/08/27 02:52:33 riastradh Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.26 2020/08/27 02:53:47 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>
@@ -2333,31 +2333,27 @@ wg_handle_msg_data(struct wg_softc *wg,  @@ -2333,31 +2333,27 @@ wg_handle_msg_data(struct wg_softc *wg,
2333 const struct sockaddr *src) 2333 const struct sockaddr *src)
2334{ 2334{
2335 struct wg_msg_data *wgmd; 2335 struct wg_msg_data *wgmd;
2336 char *encrypted_buf = NULL, *decrypted_buf; 2336 char *encrypted_buf = NULL, *decrypted_buf;
2337 size_t encrypted_len, decrypted_len; 2337 size_t encrypted_len, decrypted_len;
2338 struct wg_session *wgs; 2338 struct wg_session *wgs;
2339 struct wg_peer *wgp; 2339 struct wg_peer *wgp;
2340 size_t mlen; 2340 size_t mlen;
2341 struct psref psref; 2341 struct psref psref;
2342 int error, af; 2342 int error, af;
2343 bool success, free_encrypted_buf = false, ok; 2343 bool success, free_encrypted_buf = false, ok;
2344 struct mbuf *n; 2344 struct mbuf *n;
2345 2345
2346 if (m->m_len < sizeof(struct wg_msg_data)) { 2346 KASSERT(m->m_len >= sizeof(struct wg_msg_data));
2347 m = m_pullup(m, sizeof(struct wg_msg_data)); 
2348 if (m == NULL) 
2349 return; 
2350 } 
2351 wgmd = mtod(m, struct wg_msg_data *); 2347 wgmd = mtod(m, struct wg_msg_data *);
2352 2348
2353 KASSERT(wgmd->wgmd_type == WG_MSG_TYPE_DATA); 2349 KASSERT(wgmd->wgmd_type == WG_MSG_TYPE_DATA);
2354 WG_TRACE("data"); 2350 WG_TRACE("data");
2355 2351
2356 wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref); 2352 wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref);
2357 if (wgs == NULL) { 2353 if (wgs == NULL) {
2358 WG_TRACE("No session found"); 2354 WG_TRACE("No session found");
2359 m_freem(m); 2355 m_freem(m);
2360 return; 2356 return;
2361 } 2357 }
2362 wgp = wgs->wgs_peer; 2358 wgp = wgs->wgs_peer;
2363 2359
@@ -2563,93 +2559,112 @@ wg_handle_msg_cookie(struct wg_softc *wg @@ -2563,93 +2559,112 @@ wg_handle_msg_cookie(struct wg_softc *wg
2563 } 2559 }
2564 /* 2560 /*
2565 * [W] 6.6: Interaction with Cookie Reply System 2561 * [W] 6.6: Interaction with Cookie Reply System
2566 * "it should simply store the decrypted cookie value from the cookie 2562 * "it should simply store the decrypted cookie value from the cookie
2567 * reply message, and wait for the expiration of the REKEY-TIMEOUT 2563 * reply message, and wait for the expiration of the REKEY-TIMEOUT
2568 * timer for retrying a handshake initiation message." 2564 * timer for retrying a handshake initiation message."
2569 */ 2565 */
2570 wgp->wgp_latest_cookie_time = time_uptime; 2566 wgp->wgp_latest_cookie_time = time_uptime;
2571 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie)); 2567 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie));
2572out: 2568out:
2573 wg_put_session(wgs, &psref); 2569 wg_put_session(wgs, &psref);
2574} 2570}
2575 2571
2576static bool 2572static struct mbuf *
2577wg_validate_msg_length(struct wg_softc *wg, const struct mbuf *m) 2573wg_validate_msg_header(struct wg_softc *wg, struct mbuf *m)
2578{ 2574{
2579 struct wg_msg *wgm; 2575 struct wg_msg wgm;
2580 size_t mlen; 2576 size_t mbuflen;
 2577 size_t msglen;
2581 2578
2582 mlen = m_length(m); 2579 /*
2583 if (__predict_false(mlen < sizeof(struct wg_msg))) 2580 * Get the mbuf chain length. It is already guaranteed, by
2584 return false; 2581 * wg_overudp_cb, to be large enough for a struct wg_msg.
 2582 */
 2583 mbuflen = m_length(m);
 2584 KASSERT(mbuflen >= sizeof(struct wg_msg));
2585 2585
2586 wgm = mtod(m, struct wg_msg *); 2586 /*
2587 switch (wgm->wgm_type) { 2587 * Copy the message header (32-bit message type) out -- we'll
 2588 * worry about contiguity and alignment later.
 2589 */
 2590 m_copydata(m, 0, sizeof(wgm), &wgm);
 2591 switch (wgm.wgm_type) {
2588 case WG_MSG_TYPE_INIT: 2592 case WG_MSG_TYPE_INIT:
2589 if (__predict_true(mlen >= sizeof(struct wg_msg_init))) 2593 msglen = sizeof(struct wg_msg_init);
2590 return true; 
2591 break; 2594 break;
2592 case WG_MSG_TYPE_RESP: 2595 case WG_MSG_TYPE_RESP:
2593 if (__predict_true(mlen >= sizeof(struct wg_msg_resp))) 2596 msglen = sizeof(struct wg_msg_resp);
2594 return true; 
2595 break; 2597 break;
2596 case WG_MSG_TYPE_COOKIE: 2598 case WG_MSG_TYPE_COOKIE:
2597 if (__predict_true(mlen >= sizeof(struct wg_msg_cookie))) 2599 msglen = sizeof(struct wg_msg_cookie);
2598 return true; 
2599 break; 2600 break;
2600 case WG_MSG_TYPE_DATA: 2601 case WG_MSG_TYPE_DATA:
2601 if (__predict_true(mlen >= sizeof(struct wg_msg_data))) 2602 msglen = sizeof(struct wg_msg_data);
2602 return true; 
2603 break; 2603 break;
2604 default: 2604 default:
2605 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG, 2605 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG,
2606 "Unexpected msg type: %u\n", wgm->wgm_type); 2606 "Unexpected msg type: %u\n", wgm.wgm_type);
2607 return false; 2607 goto error;
2608 } 2608 }
2609 WG_DLOG("Invalid msg size: mlen=%lu type=%u\n", mlen, wgm->wgm_type); 
2610 2609
2611 return false; 2610 /* Verify the mbuf chain is long enough for this type of message. */
 2611 if (__predict_false(mbuflen < msglen)) {
 2612 WG_DLOG("Invalid msg size: mbuflen=%lu type=%u\n", mbuflen,
 2613 wgm.wgm_type);
 2614 goto error;
 2615 }
 2616
 2617 /* Make the message header contiguous if necessary. */
 2618 if (__predict_false(m->m_len < msglen)) {
 2619 m = m_pullup(m, msglen);
 2620 if (m == NULL)
 2621 return NULL;
 2622 }
 2623
 2624 return m;
 2625
 2626error:
 2627 m_freem(m);
 2628 return NULL;
2612} 2629}
2613 2630
2614static void 2631static void
2615wg_handle_packet(struct wg_softc *wg, struct mbuf *m, 2632wg_handle_packet(struct wg_softc *wg, struct mbuf *m,
2616 const struct sockaddr *src) 2633 const struct sockaddr *src)
2617{ 2634{
2618 struct wg_msg *wgm; 2635 struct wg_msg *wgm;
2619 bool valid; 
2620 2636
2621 valid = wg_validate_msg_length(wg, m); 2637 m = wg_validate_msg_header(wg, m);
2622 if (!valid) { 2638 if (__predict_false(m == NULL))
2623 m_freem(m); 
2624 return; 2639 return;
2625 } 
2626 2640
 2641 KASSERT(m->m_len >= sizeof(struct wg_msg));
2627 wgm = mtod(m, struct wg_msg *); 2642 wgm = mtod(m, struct wg_msg *);
2628 switch (wgm->wgm_type) { 2643 switch (wgm->wgm_type) {
2629 case WG_MSG_TYPE_INIT: 2644 case WG_MSG_TYPE_INIT:
2630 wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src); 2645 wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src);
2631 break; 2646 break;
2632 case WG_MSG_TYPE_RESP: 2647 case WG_MSG_TYPE_RESP:
2633 wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src); 2648 wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src);
2634 break; 2649 break;
2635 case WG_MSG_TYPE_COOKIE: 2650 case WG_MSG_TYPE_COOKIE:
2636 wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm); 2651 wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm);
2637 break; 2652 break;
2638 case WG_MSG_TYPE_DATA: 2653 case WG_MSG_TYPE_DATA:
2639 wg_handle_msg_data(wg, m, src); 2654 wg_handle_msg_data(wg, m, src);
2640 break; 2655 break;
2641 default: 2656 default:
2642 /* wg_validate_msg_length should already reject this case */ 2657 /* wg_validate_msg_header should already reject this case */
2643 break; 2658 break;
2644 } 2659 }
2645} 2660}
2646 2661
2647static void 2662static void
2648wg_receive_packets(struct wg_softc *wg, const int af) 2663wg_receive_packets(struct wg_softc *wg, const int af)
2649{ 2664{
2650 2665
2651 for (;;) { 2666 for (;;) {
2652 int error, flags; 2667 int error, flags;
2653 struct socket *so; 2668 struct socket *so;
2654 struct mbuf *m = NULL; 2669 struct mbuf *m = NULL;
2655 struct uio dummy_uio; 2670 struct uio dummy_uio;