aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/ipc-freebsd.h
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2022-11-03 12:59:01 -0500
committerJason A. Donenfeld <Jason@zx2c4.com>2022-11-03 19:57:21 +0100
commitdbf49a7d17d69b8af365ce2521df110a4710c819 (patch)
treeaa779b1d9233c4f5838e57f0e542a70b6d1f13a8 /src/ipc-freebsd.h
parentshow: apply const to right part of pointer (diff)
downloadwireguard-tools-dbf49a7d17d69b8af365ce2521df110a4710c819.tar.xz
wireguard-tools-dbf49a7d17d69b8af365ce2521df110a4710c819.zip
ipc: freebsd: avoid leaking memory in kernel_get_device()
Primarily, front-load validation of an allowed-ip entry to before we allocate `aip`, so that we don't need to free() it if we end up skipping this entry. Assert that `aip` is NULL after we exit the loop, as we should have transfered ownership to the `peer` or freed it in all paths through the allowed-ip loop. FreeBSD-Coverity: 1500405 Signed-off-by: Kyle Evans <kevans@FreeBSD.org> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r--src/ipc-freebsd.h19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/ipc-freebsd.h b/src/ipc-freebsd.h
index b5be15b..b78b6c8 100644
--- a/src/ipc-freebsd.h
+++ b/src/ipc-freebsd.h
@@ -4,6 +4,7 @@
*
*/
+#include <assert.h>
#include <sys/nv.h>
#include <sys/sockio.h>
#include <dev/wg/if_wg.h>
@@ -118,7 +119,7 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
goto skip_peers;
for (i = 0; i < peer_count; ++i) {
struct wgpeer *peer;
- struct wgallowedip *aip;
+ struct wgallowedip *aip = NULL;
const nvlist_t *const *nvl_aips;
size_t aip_count, j;
@@ -169,11 +170,13 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
if (!aip_count || !nvl_aips)
goto skip_allowed_ips;
for (j = 0; j < aip_count; ++j) {
+ if (!nvlist_exists_number(nvl_aips[j], "cidr"))
+ continue;
+ if (!nvlist_exists_binary(nvl_aips[j], "ipv4") && !nvlist_exists_binary(nvl_aips[j], "ipv6"))
+ continue;
aip = calloc(1, sizeof(*aip));
if (!aip)
goto err_allowed_ips;
- if (!nvlist_exists_number(nvl_aips[j], "cidr"))
- continue;
number = nvlist_get_number(nvl_aips[j], "cidr");
if (nvlist_exists_binary(nvl_aips[j], "ipv4")) {
binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size);
@@ -184,7 +187,8 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
aip->family = AF_INET;
aip->cidr = number;
memcpy(&aip->ip4, binary, sizeof(aip->ip4));
- } else if (nvlist_exists_binary(nvl_aips[j], "ipv6")) {
+ } else {
+ assert(nvlist_exists_binary(nvl_aips[j], "ipv6"));
binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size);
if (!binary || number > 128) {
ret = EINVAL;
@@ -193,14 +197,14 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
aip->family = AF_INET6;
aip->cidr = number;
memcpy(&aip->ip6, binary, sizeof(aip->ip6));
- } else
- continue;
+ }
if (!peer->first_allowedip)
peer->first_allowedip = aip;
else
peer->last_allowedip->next_allowedip = aip;
peer->last_allowedip = aip;
+ aip = NULL;
continue;
err_allowed_ips:
@@ -209,6 +213,9 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
free(aip);
goto err_peer;
}
+
+ /* Nothing leaked, hopefully -- ownership transferred or aip freed. */
+ assert(aip == NULL);
skip_allowed_ips:
if (!dev->first_peer)
dev->first_peer = peer;