aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-03-24 04:01:25 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2017-03-24 04:44:27 +0100
commit873d477c74a9e9be0044f17d59f124f9e6537e77 (patch)
tree0eb98593ee069aad200bd8f23de51640c5018711 /src
parentwg-quick: various cleanups (diff)
downloadwireguard-monolithic-historical-873d477c74a9e9be0044f17d59f124f9e6537e77.tar.xz
wireguard-monolithic-historical-873d477c74a9e9be0044f17d59f124f9e6537e77.zip
uapi: add version magic
Diffstat (limited to 'src')
-rw-r--r--src/config.c40
-rw-r--r--src/tools/config.c2
-rw-r--r--src/tools/ipc.c33
-rw-r--r--src/uapi.h6
4 files changed, 58 insertions, 23 deletions
diff --git a/src/config.c b/src/config.c
index 4191eb6..963f9e1 100644
--- a/src/config.c
+++ b/src/config.c
@@ -109,7 +109,7 @@ out:
int config_set_device(struct wireguard_device *wg, void __user *user_device)
{
- int ret = 0;
+ int ret;
size_t i, offset;
struct wgdevice in_device;
void __user *user_peer;
@@ -120,10 +120,13 @@ int config_set_device(struct wireguard_device *wg, void __user *user_device)
mutex_lock(&wg->device_update_lock);
- if (copy_from_user(&in_device, user_device, sizeof(in_device))) {
- ret = -EFAULT;
+ ret = -EFAULT;
+ if (copy_from_user(&in_device, user_device, sizeof(in_device)))
+ goto out;
+
+ ret = -EPROTO;
+ if (in_device.version_magic != WG_API_VERSION_MAGIC)
goto out;
- }
if (in_device.fwmark || (!in_device.fwmark && (in_device.flags & WGDEVICE_REMOVE_FWMARK))) {
wg->fwmark = in_device.fwmark;
@@ -161,9 +164,9 @@ int config_set_device(struct wireguard_device *wg, void __user *user_device)
for (i = 0, offset = 0, user_peer = user_device + sizeof(struct wgdevice); i < in_device.num_peers; ++i, user_peer += offset) {
ret = set_peer(wg, user_peer, &offset);
if (ret)
- break;
+ goto out;
}
-
+ ret = 0;
out:
mutex_unlock(&wg->device_update_lock);
memzero_explicit(&in_device.private_key, NOISE_PUBLIC_KEY_LEN);
@@ -266,9 +269,9 @@ static int populate_peer(struct wireguard_peer *peer, void *ctx)
return ret;
}
-int config_get_device(struct wireguard_device *wg, void __user *udevice)
+int config_get_device(struct wireguard_device *wg, void __user *user_device)
{
- int ret = 0;
+ int ret;
struct net_device *dev = netdev_pub(wg);
struct data_remaining peer_data = { NULL };
struct wgdevice out_device;
@@ -281,16 +284,20 @@ int config_get_device(struct wireguard_device *wg, void __user *udevice)
mutex_lock(&wg->device_update_lock);
- if (!udevice) {
+ if (!user_device) {
ret = calculate_peers_size(wg);
goto out;
}
- if (copy_from_user(&in_device, udevice, sizeof(in_device))) {
- ret = -EFAULT;
+ ret = -EFAULT;
+ if (copy_from_user(&in_device, user_device, sizeof(in_device)))
goto out;
- }
+ ret = -EPROTO;
+ if (in_device.version_magic != WG_API_VERSION_MAGIC)
+ goto out;
+
+ out_device.version_magic = WG_API_VERSION_MAGIC;
out_device.port = wg->incoming_port;
out_device.fwmark = wg->fwmark;
strncpy(out_device.interface, dev->name, IFNAMSIZ - 1);
@@ -305,14 +312,17 @@ int config_get_device(struct wireguard_device *wg, void __user *udevice)
up_read(&wg->static_identity.lock);
peer_data.out_len = in_device.peers_size;
- peer_data.data = udevice + sizeof(struct wgdevice);
+ peer_data.data = user_device + sizeof(struct wgdevice);
ret = peer_for_each_unlocked(wg, populate_peer, &peer_data);
if (ret)
goto out;
out_device.num_peers = peer_data.count;
- if (copy_to_user(udevice, &out_device, sizeof(out_device)))
- ret = -EFAULT;
+ ret = -EFAULT;
+ if (copy_to_user(user_device, &out_device, sizeof(out_device)))
+ goto out;
+
+ ret = 0;
out:
mutex_unlock(&wg->device_update_lock);
diff --git a/src/tools/config.c b/src/tools/config.c
index b9a65c1..20bd22a 100644
--- a/src/tools/config.c
+++ b/src/tools/config.c
@@ -465,7 +465,7 @@ bool config_read_cmd(struct wgdevice **device, char *argv[], int argc)
{
struct inflatable_device buf = { 0 };
size_t peer_offset = 0;
- buf.dev = calloc(sizeof(struct wgdevice), 1);
+ buf.dev = calloc(1, sizeof(struct wgdevice));
if (!buf.dev) {
perror("calloc");
return false;
diff --git a/src/tools/ipc.c b/src/tools/ipc.c
index a926261..c26da21 100644
--- a/src/tools/ipc.c
+++ b/src/tools/ipc.c
@@ -42,6 +42,15 @@ struct inflatable_buffer {
#define max(a, b) ((a) > (b) ? (a) : (b))
+static int check_version_magic(struct wgdevice *device, int ret)
+{
+ if (ret == -EPROTO || (!ret && device->version_magic != WG_API_VERSION_MAGIC)) {
+ fprintf(stderr, "This program was built for a different version of WireGuard than\nwhat is currently running. Either this version of wg(8) is out\nof date, or the currently loaded WireGuard module is out of date.\nIf you have just updated your WireGuard installation, you may have\nforgotten to unload the previous running WireGuard module. Try\nrunning `rmmod wireguard` as root, and then try re-adding the device\nand trying again.\n\n");
+ return -EPROTO;
+ }
+ return ret;
+}
+
static int add_next_to_inflatable_buffer(struct inflatable_buffer *buffer)
{
size_t len, expand_to;
@@ -172,6 +181,7 @@ static int userspace_set_device(struct wgdevice *dev)
ret = -EBADMSG;
if (!len)
goto out;
+ dev->version_magic = WG_API_VERSION_MAGIC;
ret = write(fd, dev, len);
if (ret < 0)
goto out;
@@ -243,6 +253,9 @@ static int userspace_get_device(struct wgdevice **dev, const char *interface)
goto out;
len = ((struct wgdevice *)READ_BYTES(sizeof(struct wgdevice)))->num_peers;
+ ret = check_version_magic((struct wgdevice *)buffer, ret);
+ if (ret)
+ goto out;
for (i = 0; i < len; ++i)
READ_BYTES(sizeof(struct wgipmask) * ((struct wgpeer *)READ_BYTES(sizeof(struct wgpeer)))->num_ipmasks);
ret = 0;
@@ -361,7 +374,7 @@ static bool kernel_has_wireguard_interface(const char *interface)
char *this_interface;
struct inflatable_buffer buffer = { .len = 4096 };
- buffer.buffer = calloc(buffer.len, 1);
+ buffer.buffer = calloc(1, buffer.len);
if (!buffer.buffer)
return false;
if (kernel_get_wireguard_interfaces(&buffer) < 0) {
@@ -382,12 +395,16 @@ static bool kernel_has_wireguard_interface(const char *interface)
static int do_ioctl(int req, struct ifreq *ifreq)
{
static int fd = -1;
+ int ret;
if (fd < 0) {
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return fd;
}
- return ioctl(fd, req, ifreq);
+ ret = ioctl(fd, req, ifreq);
+ if (ret == -1)
+ ret = -errno;
+ return ret;
}
static int kernel_set_device(struct wgdevice *dev)
@@ -395,6 +412,7 @@ static int kernel_set_device(struct wgdevice *dev)
struct ifreq ifreq = { .ifr_data = (char *)dev };
memcpy(&ifreq.ifr_name, dev->interface, IFNAMSIZ);
ifreq.ifr_name[IFNAMSIZ - 1] = 0;
+ dev->version_magic = WG_API_VERSION_MAGIC;
return do_ioctl(WG_SET_DEVICE, &ifreq);
}
@@ -410,17 +428,18 @@ static int kernel_get_device(struct wgdevice **dev, const char *interface)
ret = do_ioctl(WG_GET_DEVICE, &ifreq);
if (ret < 0)
goto out;
- *dev = calloc(ret + sizeof(struct wgdevice), 1);
- if (!*dev) {
- ret = -ENOMEM;
+ *dev = calloc(1, ret + sizeof(struct wgdevice));
+ ret = -ENOMEM;
+ if (!*dev)
goto out;
- }
(*dev)->peers_size = ret;
+ (*dev)->version_magic = WG_API_VERSION_MAGIC;
ifreq.ifr_data = (char *)*dev;
memcpy(&ifreq.ifr_name, interface, IFNAMSIZ);
ifreq.ifr_name[IFNAMSIZ - 1] = 0;
ret = do_ioctl(WG_GET_DEVICE, &ifreq);
} while (ret == -EMSGSIZE);
+ ret = check_version_magic(*dev, ret);
if (ret < 0) {
free(*dev);
*dev = NULL;
@@ -438,7 +457,7 @@ char *ipc_list_devices(void)
int ret;
ret = -ENOMEM;
- buffer.buffer = calloc(buffer.len, 1);
+ buffer.buffer = calloc(1, buffer.len);
if (!buffer.buffer)
goto cleanup;
diff --git a/src/uapi.h b/src/uapi.h
index 9cf9b2c..130f30a 100644
--- a/src/uapi.h
+++ b/src/uapi.h
@@ -124,7 +124,13 @@ enum {
WGDEVICE_REMOVE_PRESHARED_KEY = (1 << 2),
WGDEVICE_REMOVE_FWMARK = (1 << 3)
};
+
+enum {
+ WG_API_VERSION_MAGIC = 0xbeef0001
+};
+
struct wgdevice {
+ __u32 version_magic; /* Must be value of WG_API_VERSION_MAGIC */
char interface[IFNAMSIZ]; /* Get */
__u32 flags; /* Set */