diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-11-07 20:14:43 +0900 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-11-10 16:20:09 +0900 |
commit | ab9befbe4118850bcd58b33064f020d69b44dea6 (patch) | |
tree | 49c91f885ae48184d61f0175f6ca9c1bd13fa801 /src/compat | |
parent | compat: 4.4.0 has strange ECN function (diff) | |
download | wireguard-monolithic-historical-ab9befbe4118850bcd58b33064f020d69b44dea6.tar.xz wireguard-monolithic-historical-ab9befbe4118850bcd58b33064f020d69b44dea6.zip |
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.
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/compat.h | 17 |
1 files changed, 16 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) |