summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-11-07 20:14:43 +0900
committerJason A. Donenfeld <Jason@zx2c4.com>2017-11-10 16:20:09 +0900
commitf283e17e12ce2199ce75b92d3a778ac8830cc2f9 (patch)
treee17a9b2e9ef612d8637b9ab3b93f2fa749eeb436 /src
parent28070c6ba07d90a6c7dff558042674fc78e6ba1c (diff)
netlink: make sure we reserve space for NLMSG_DONE
Otherwise, if messages pack really close together, we'll exceed the size of the sk_buff and return ENOBUFS. I suspect this has been the cause of a lot of weird bugs that people just worked around by increasing the receive buffer size. This actually addresses the root cause. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src')
-rw-r--r--src/compat/compat.h17
-rwxr-xr-xsrc/tests/netns.sh9
2 files changed, 25 insertions, 1 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h
index 9ec73ba..e4dd226 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -454,16 +454,31 @@ static inline struct nlattr **genl_family_attrbuf(const struct genl_family *fami
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
#define get_device_dump(a, b) get_device_dump_real(a, b); \
static int get_device_dump(a, b) { \
+ int ret; \
struct wireguard_device *wg = (struct wireguard_device *)cb->args[0]; \
if (!wg) { \
int ret = get_device_start(cb); \
if (ret) \
return ret; \
} \
- return get_device_dump_real(skb, cb); \
+ /* https://patchwork.kernel.org/patch/10046511/ */ \
+ skb->end -= nlmsg_total_size(sizeof(int)); \
+ ret = get_device_dump_real(skb, cb); \
+ skb->end += nlmsg_total_size(sizeof(int)); \
+ return ret; \
} \
static int get_device_dump_real(a, b)
#define COMPAT_CANNOT_USE_NETLINK_START
+#else /* https://patchwork.kernel.org/patch/10046511/ */
+#define get_device_dump(a, b) get_device_dump_real(a, b); \
+static int get_device_dump(a, b) { \
+ int ret; \
+ skb->end -= nlmsg_total_size(sizeof(int)); \
+ ret = get_device_dump_real(skb, cb); \
+ skb->end += nlmsg_total_size(sizeof(int)); \
+ return ret; \
+} \
+static int get_device_dump_real(a, b)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
diff --git a/src/tests/netns.sh b/src/tests/netns.sh
index 9a12a19..2ad8d88 100755
--- a/src/tests/netns.sh
+++ b/src/tests/netns.sh
@@ -415,6 +415,15 @@ while read -r line; do
done < <(n0 wg show wg0 allowed-ips)
((i == 40))
ip0 link del wg0
+ip0 link add wg0 type wireguard
+config=( )
+for i in {1..29}; do
+ config+=( "[Peer]" "PublicKey=$(wg genkey)" )
+done
+config+=( "[Peer]" "PublicKey=$(wg genkey)" "AllowedIPs=255.2.3.4/32,abcd::255/128" )
+n0 wg setconf wg0 <(printf '%s\n' "${config[@]}")
+n0 wg showconf wg0 > /dev/null
+ip0 link del wg0
! n0 wg show doesnotexist || false