From ab9befbe4118850bcd58b33064f020d69b44dea6 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 7 Nov 2017 20:14:43 +0900 Subject: 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. --- src/compat/compat.h | 17 ++++++++++++++++- src/tests/netns.sh | 9 +++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3-59-g8ed1b