aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO.md2
-rw-r--r--src/if_wg.c43
-rw-r--r--src/selftest/allowedips.c46
-rw-r--r--src/wg_noise.c3
4 files changed, 59 insertions, 35 deletions
diff --git a/TODO.md b/TODO.md
index 3d13a8f..5685531 100644
--- a/TODO.md
+++ b/TODO.md
@@ -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");