diff options
-rw-r--r-- | TODO.md | 2 | ||||
-rw-r--r-- | src/if_wg.c | 43 | ||||
-rw-r--r-- | src/selftest/allowedips.c | 46 | ||||
-rw-r--r-- | src/wg_noise.c | 3 |
4 files changed, 59 insertions, 35 deletions
@@ -14,8 +14,6 @@ - Handle failures of `rn_inithead` and remember to call `rn_detachhead` somewhere during cleanup. - Stop using `M_WAITOK` and use `M_NOWAIT` instead. -- Check return value of `rn_inithead`. -- Perhaps call `rn_detachhead` to free memory when destroying aip. - Hash in jail/fib pointer to ratelimiter. ### Crypto TODO diff --git a/src/if_wg.c b/src/if_wg.c index e898caf..b678f68 100644 --- a/src/if_wg.c +++ b/src/if_wg.c @@ -2601,28 +2601,28 @@ wg_clone_create(struct if_clone *ifc, int unit, caddr_t params) struct wg_softc *sc; struct ifnet *ifp; - sc = malloc(sizeof(*sc), M_WG, M_WAITOK | M_ZERO); + sc = malloc(sizeof(*sc), M_WG, M_NOWAIT | M_ZERO); + if (!sc) + goto err_mem; + sc->sc_local = noise_local_alloc(sc); + if (!sc->sc_local) + goto free_sc; + if (!rn_inithead((void **)&sc->sc_aip4, offsetof(struct aip_addr, in) * NBBY)) + goto free_noise_local; + if (!rn_inithead((void **)&sc->sc_aip6, offsetof(struct aip_addr, in6) * NBBY)) + goto free_aip4; + sc->sc_ucred = crhold(curthread->td_ucred); sc->sc_socket.so_fibnum = curthread->td_proc->p_fibnum; ifp = sc->sc_ifp = if_alloc(IFT_WIREGUARD); ifp->if_softc = sc; if_initname(ifp, wgname, unit); - TAILQ_INIT(&sc->sc_peers); sc->sc_peers_num = 0; - - if ((sc->sc_local = noise_local_alloc(sc)) == NULL) { - free(sc, M_WG); - return (ENOMEM); - } - cookie_checker_init(&sc->sc_cookie); - sc->sc_socket.so_port = 0; - atomic_add_int(&clone_count, 1); ifp->if_capabilities = ifp->if_capenable = WG_CAPS; - wg_queue_init(&sc->sc_handshake_queue, "hsq"); sx_init(&sc->sc_lock, "wg softc lock"); GROUPTASK_INIT(&sc->sc_handshake, 0, (gtask_fn_t *)wg_softc_handshake_receive, sc); @@ -2630,13 +2630,8 @@ wg_clone_create(struct if_clone *ifc, int unit, caddr_t params) crypto_taskq_setup(sc); wg_queue_init(&sc->sc_encrypt_parallel, "encp"); wg_queue_init(&sc->sc_decrypt_parallel, "decp"); - - /* TODO check rn_inithead return value */ - rn_inithead((void **)&sc->sc_aip4, offsetof(struct aip_addr, in) * NBBY); - rn_inithead((void **)&sc->sc_aip6, offsetof(struct aip_addr, in6) * NBBY); RADIX_NODE_HEAD_LOCK_INIT(sc->sc_aip4); RADIX_NODE_HEAD_LOCK_INIT(sc->sc_aip6); - if_setmtu(ifp, DEFAULT_MTU); ifp->if_flags = IFF_NOARP | IFF_MULTICAST; ifp->if_init = wg_init; @@ -2645,19 +2640,25 @@ wg_clone_create(struct if_clone *ifc, int unit, caddr_t params) ifp->if_transmit = wg_transmit; ifp->if_output = wg_output; ifp->if_ioctl = wg_ioctl; - if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(uint32_t)); #ifdef INET6 ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD; #endif - sx_xlock(&wg_sx); LIST_INSERT_HEAD(&wg_list, sc, sc_entry); sx_xunlock(&wg_sx); - return (0); + +free_aip4: + rn_detachhead((void **)&sc->sc_aip4); +free_noise_local: + noise_local_free(sc->sc_local, NULL); +free_sc: + free(sc, M_WG); +err_mem: + return (ENOMEM); } static void @@ -2714,8 +2715,8 @@ wg_clone_destroy(struct ifnet *ifp) RADIX_NODE_HEAD_DESTROY(sc->sc_aip4); RADIX_NODE_HEAD_DESTROY(sc->sc_aip6); - free(sc->sc_aip4, M_RTABLE); - free(sc->sc_aip6, M_RTABLE); + rn_detachhead((void **)&sc->sc_aip4); + rn_detachhead((void **)&sc->sc_aip6); if (cred != NULL) crfree(cred); diff --git a/src/selftest/allowedips.c b/src/selftest/allowedips.c index 97011b0..294bb19 100644 --- a/src/selftest/allowedips.c +++ b/src/selftest/allowedips.c @@ -3,6 +3,29 @@ * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */ +static bool test_aip_init(struct wg_softc *sc) +{ + if (!rn_inithead((void **)&sc->sc_aip4, offsetof(struct aip_addr, in) * NBBY)) + return false; + if (!rn_inithead((void **)&sc->sc_aip6, offsetof(struct aip_addr, in6) * NBBY)) + return false; + RADIX_NODE_HEAD_LOCK_INIT(sc->sc_aip4); + RADIX_NODE_HEAD_LOCK_INIT(sc->sc_aip6); + return true; +} + +static void test_aip_deinit(struct wg_softc *sc) +{ + if (sc->sc_aip4) { + RADIX_NODE_HEAD_DESTROY(sc->sc_aip4); + rn_detachhead((void **)&sc->sc_aip4); + } + if (sc->sc_aip6) { + RADIX_NODE_HEAD_DESTROY(sc->sc_aip6); + rn_detachhead((void **)&sc->sc_aip6); + } +} + #ifdef WG_ALLOWEDIPS_RANDOMIZED_TEST enum { NUM_PEERS = 2000, @@ -197,13 +220,6 @@ static bool randomized_test(void) struct horrible_allowedips h; struct wg_softc sc = { 0 }; bool ret = false; - - rn_inithead((void **)&sc.sc_aip4, offsetof(struct aip_addr, in) * NBBY); - rn_inithead((void **)&sc.sc_aip6, offsetof(struct aip_addr, in6) * NBBY); - RADIX_NODE_HEAD_LOCK_INIT(sc.sc_aip4); - RADIX_NODE_HEAD_LOCK_INIT(sc.sc_aip6); - horrible_allowedips_init(&h); - peers = mallocarray(NUM_PEERS, sizeof(*peers), M_WG, M_NOWAIT | M_ZERO); if (!peers) { printf("allowedips random self-test malloc: FAIL\n"); @@ -219,6 +235,12 @@ static bool randomized_test(void) peers[i]->p_aips_num = 0; } + if (!test_aip_init(&sc)) { + printf("allowedips random self-test malloc: FAIL\n"); + goto free; + } + horrible_allowedips_init(&h); + for (i = 0; i < NUM_RAND_ROUTES; ++i) { arc4random_buf(ip, 4); cidr = arc4random_uniform(32) + 1; @@ -330,6 +352,7 @@ free: free(peers[i], M_WG); } free(peers, M_WG); + test_aip_deinit(&sc); return ret; } #endif @@ -428,10 +451,10 @@ static bool wg_allowedips_selftest(void) struct in6_addr ip; uint64_t part; - rn_inithead((void **)&sc.sc_aip4, offsetof(struct aip_addr, in) * NBBY); - rn_inithead((void **)&sc.sc_aip6, offsetof(struct aip_addr, in6) * NBBY); - RADIX_NODE_HEAD_LOCK_INIT(sc.sc_aip4); - RADIX_NODE_HEAD_LOCK_INIT(sc.sc_aip6); + if (!test_aip_init(&sc)) { + printf("allowedips self-test malloc: FAIL\n"); + goto free; + } if (!a || !b || !c || !d || !e || !f || !g || !h) { printf("allowedips self-test malloc: FAIL\n"); @@ -587,6 +610,7 @@ free: free(f, M_WG); free(g, M_WG); free(h, M_WG); + test_aip_deinit(&sc); return success; } diff --git a/src/wg_noise.c b/src/wg_noise.c index b188ece..10673b7 100644 --- a/src/wg_noise.c +++ b/src/wg_noise.c @@ -175,7 +175,8 @@ noise_local_alloc(void *arg) struct noise_local *l; size_t i; - if ((l = malloc(sizeof(*l), M_NOISE, M_NOWAIT)) == NULL) + l = malloc(sizeof(*l), M_NOISE, M_NOWAIT | M_ZERO); + if (!l) return (NULL); rw_init(&l->l_identity_lock, "noise_identity"); |