net-vpn/wireguard: backport stability fix for lxd users
authorJason A. Donenfeld <zx2c4@gentoo.org>
Wed, 7 Jun 2017 12:26:10 +0000 (14:26 +0200)
committerJason A. Donenfeld <zx2c4@gentoo.org>
Wed, 7 Jun 2017 12:26:43 +0000 (14:26 +0200)
Package-Manager: Portage-2.3.6, Repoman-2.3.2

net-vpn/wireguard/files/wireguard-0.0.20170531-simultaneous-start.patch [new file with mode: 0644]
net-vpn/wireguard/wireguard-0.0.20170531-r2.ebuild [moved from net-vpn/wireguard/wireguard-0.0.20170531-r1.ebuild with 97% similarity]
net-vpn/wireguard/wireguard-0.0.20170531.ebuild [deleted file]

diff --git a/net-vpn/wireguard/files/wireguard-0.0.20170531-simultaneous-start.patch b/net-vpn/wireguard/files/wireguard-0.0.20170531-simultaneous-start.patch
new file mode 100644 (file)
index 0000000..5d5ef64
--- /dev/null
@@ -0,0 +1,135 @@
+From 156280bcb881915701b25ad57e1efe2dcef73c6b Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Tue, 6 Jun 2017 21:49:29 +0200
+Subject: noise: fix race when replacing handshake
+
+Replacing an entry that's already been replaced is something that could
+happen when processing handshake messages in parallel, when starting up
+multiple instances on the same machine.
+
+Reported-by: Hubert Goisern <zweizweizwoelf@gmail.com>
+---
+ src/hashtables.c |  5 ++++-
+ src/hashtables.h |  2 +-
+ src/noise.c      | 28 +++++++++++++++++++---------
+ 3 files changed, 24 insertions(+), 11 deletions(-)
+
+diff --git a/src/hashtables.c b/src/hashtables.c
+index db97f7e..a01a899 100644
+--- a/src/hashtables.c
++++ b/src/hashtables.c
+@@ -97,13 +97,16 @@ search_unused_slot:
+       return entry->index;
+ }
+-void index_hashtable_replace(struct index_hashtable *table, struct index_hashtable_entry *old, struct index_hashtable_entry *new)
++bool index_hashtable_replace(struct index_hashtable *table, struct index_hashtable_entry *old, struct index_hashtable_entry *new)
+ {
++      if (unlikely(hlist_unhashed(&old->index_hash)))
++              return false;
+       spin_lock_bh(&table->lock);
+       new->index = old->index;
+       hlist_replace_rcu(&old->index_hash, &new->index_hash);
+       INIT_HLIST_NODE(&old->index_hash);
+       spin_unlock_bh(&table->lock);
++      return true;
+ }
+ void index_hashtable_remove(struct index_hashtable *table, struct index_hashtable_entry *entry)
+diff --git a/src/hashtables.h b/src/hashtables.h
+index 9fa47d5..08a2a5d 100644
+--- a/src/hashtables.h
++++ b/src/hashtables.h
+@@ -40,7 +40,7 @@ struct index_hashtable_entry {
+ };
+ void index_hashtable_init(struct index_hashtable *table);
+ __le32 index_hashtable_insert(struct index_hashtable *table, struct index_hashtable_entry *entry);
+-void index_hashtable_replace(struct index_hashtable *table, struct index_hashtable_entry *old, struct index_hashtable_entry *new);
++bool index_hashtable_replace(struct index_hashtable *table, struct index_hashtable_entry *old, struct index_hashtable_entry *new);
+ void index_hashtable_remove(struct index_hashtable *table, struct index_hashtable_entry *entry);
+ struct index_hashtable_entry *index_hashtable_lookup(struct index_hashtable *table, const enum index_hashtable_type type_mask, const __le32 index);
+diff --git a/src/noise.c b/src/noise.c
+index 7ca2a67..9583ab1 100644
+--- a/src/noise.c
++++ b/src/noise.c
+@@ -59,16 +59,21 @@ bool noise_handshake_init(struct noise_handshake *handshake, struct noise_static
+       return noise_precompute_static_static(peer);
+ }
+-void noise_handshake_clear(struct noise_handshake *handshake)
++static void handshake_zero(struct noise_handshake *handshake)
+ {
+-      index_hashtable_remove(&handshake->entry.peer->device->index_hashtable, &handshake->entry);
+-      down_write(&handshake->lock);
+       memset(&handshake->ephemeral_private, 0, NOISE_PUBLIC_KEY_LEN);
+       memset(&handshake->remote_ephemeral, 0, NOISE_PUBLIC_KEY_LEN);
+       memset(&handshake->hash, 0, NOISE_HASH_LEN);
+       memset(&handshake->chaining_key, 0, NOISE_HASH_LEN);
+       handshake->remote_index = 0;
+       handshake->state = HANDSHAKE_ZEROED;
++}
++
++void noise_handshake_clear(struct noise_handshake *handshake)
++{
++      index_hashtable_remove(&handshake->entry.peer->device->index_hashtable, &handshake->entry);
++      down_write(&handshake->lock);
++      handshake_zero(handshake);
+       up_write(&handshake->lock);
+       index_hashtable_remove(&handshake->entry.peer->device->index_hashtable, &handshake->entry);
+ }
+@@ -371,8 +376,8 @@ bool noise_handshake_create_initiation(struct message_handshake_initiation *dst,
+       dst->sender_index = index_hashtable_insert(&handshake->entry.peer->device->index_hashtable, &handshake->entry);
+-      ret = true;
+       handshake->state = HANDSHAKE_CREATED_INITIATION;
++      ret = true;
+ out:
+       up_write(&handshake->lock);
+@@ -548,6 +553,11 @@ struct wireguard_peer *noise_handshake_consume_response(struct message_handshake
+       /* Success! Copy everything to peer */
+       down_write(&handshake->lock);
++      /* It's important to check that the state is still the same, while we have an exclusive lock */
++      if (handshake->state != state) {
++              up_write(&handshake->lock);
++              goto fail;
++      }
+       memcpy(handshake->remote_ephemeral, e, NOISE_PUBLIC_KEY_LEN);
+       memcpy(handshake->hash, hash, NOISE_HASH_LEN);
+       memcpy(handshake->chaining_key, chaining_key, NOISE_HASH_LEN);
+@@ -573,7 +583,7 @@ bool noise_handshake_begin_session(struct noise_handshake *handshake, struct noi
+ {
+       struct noise_keypair *new_keypair;
+-      down_read(&handshake->lock);
++      down_write(&handshake->lock);
+       if (handshake->state != HANDSHAKE_CREATED_RESPONSE && handshake->state != HANDSHAKE_CONSUMED_RESPONSE)
+               goto fail;
+@@ -587,16 +597,16 @@ bool noise_handshake_begin_session(struct noise_handshake *handshake, struct noi
+               derive_keys(&new_keypair->sending, &new_keypair->receiving, handshake->chaining_key);
+       else
+               derive_keys(&new_keypair->receiving, &new_keypair->sending, handshake->chaining_key);
+-      up_read(&handshake->lock);
++      handshake_zero(handshake);
+       add_new_keypair(keypairs, new_keypair);
+-      index_hashtable_replace(&handshake->entry.peer->device->index_hashtable, &handshake->entry, &new_keypair->entry);
+-      noise_handshake_clear(handshake);
+       net_dbg_ratelimited("%s: Keypair %Lu created for peer %Lu\n", netdev_pub(new_keypair->entry.peer->device)->name, new_keypair->internal_id, new_keypair->entry.peer->internal_id);
++      WARN_ON(!index_hashtable_replace(&handshake->entry.peer->device->index_hashtable, &handshake->entry, &new_keypair->entry));
++      up_write(&handshake->lock);
+       return true;
+ fail:
+-      up_read(&handshake->lock);
++      up_write(&handshake->lock);
+       return false;
+ }
+-- 
+cgit v1.1-9-ge9c1d
+
similarity index 97%
rename from net-vpn/wireguard/wireguard-0.0.20170531-r1.ebuild
rename to net-vpn/wireguard/wireguard-0.0.20170531-r2.ebuild
index 3d5b1b746f0bb92c31998eb4e351c80062405966..db171b012c3b21a63347a8f828d3a9b1671aba30 100644 (file)
@@ -39,10 +39,10 @@ pkg_setup() {
        fi
 }
 
-src_prepare() {
-       epatch "${FILESDIR}/${P}-remove-padata-hotplug.patch"
-       default
-}
+PATCHES=(
+       "${FILESDIR}/${P}-remove-padata-hotplug.patch"
+       "${FILESDIR}/${P}-simultaneous-start.patch"
+)
 
 src_compile() {
        use debug && BUILD_PARAMS="CONFIG_WIREGUARD_DEBUG=y ${BUILD_PARAMS}"
diff --git a/net-vpn/wireguard/wireguard-0.0.20170531.ebuild b/net-vpn/wireguard/wireguard-0.0.20170531.ebuild
deleted file mode 100644 (file)
index 1406c6d..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 1999-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=6
-
-inherit linux-mod bash-completion-r1
-
-DESCRIPTION="Simple yet fast and modern VPN that utilizes state-of-the-art cryptography."
-HOMEPAGE="https://www.wireguard.io/"
-
-if [[ ${PV} == 9999 ]]; then
-       inherit git-r3
-       EGIT_REPO_URI="https://git.zx2c4.com/WireGuard"
-       KEYWORDS=""
-else
-       SRC_URI="https://git.zx2c4.com/WireGuard/snapshot/WireGuard-${PV}.tar.xz"
-       S="${WORKDIR}/WireGuard-${PV}"
-       KEYWORDS="~amd64 ~x86 ~mips ~arm ~arm64"
-fi
-
-LICENSE="GPL-2"
-SLOT="0"
-IUSE="debug +module +tools module-src"
-
-DEPEND="tools? ( net-libs/libmnl )"
-RDEPEND="${DEPEND}"
-
-MODULE_NAMES="wireguard(net:src)"
-BUILD_PARAMS="KERNELDIR=${KERNEL_DIR} V=1"
-BUILD_TARGETS="module"
-CONFIG_CHECK="NET INET NET_UDP_TUNNEL NF_CONNTRACK NETFILTER_XT_MATCH_HASHLIMIT CRYPTO_BLKCIPHER ~PADATA ~IP6_NF_IPTABLES"
-WARNING_PADATA="If you're running a multicore system you likely should enable CONFIG_PADATA for improved performance and parallel crypto."
-WARNING_IP6_NF_IPTABLES="If your kernel has CONFIG_IPV6, you need CONFIG_IP6_NF_IPTABLES; otherwise WireGuard will not insert."
-
-pkg_setup() {
-       if use module; then
-               linux-mod_pkg_setup
-               kernel_is -lt 3 10 0 && die "This version of ${PN} requires Linux >= 3.10"
-       fi
-}
-
-src_compile() {
-       use debug && BUILD_PARAMS="CONFIG_WIREGUARD_DEBUG=y ${BUILD_PARAMS}"
-       use module && linux-mod_src_compile
-       use tools && emake RUNSTATEDIR="${EPREFIX}/run" -C src/tools
-}
-
-src_install() {
-       use module && linux-mod_src_install
-       if use tools; then
-               dodoc README.md
-               dodoc -r contrib/examples
-               emake \
-                       WITH_BASHCOMPLETION=yes \
-                       WITH_SYSTEMDUNITS=yes \
-                       WITH_WGQUICK=yes \
-                       DESTDIR="${D}" \
-                       BASHCOMPDIR="$(get_bashcompdir)" \
-                       PREFIX="${EPREFIX}/usr" \
-                       -C src/tools install
-               insinto /$(get_libdir)/netifrc/net
-               newins "${FILESDIR}"/wireguard-openrc.sh wireguard.sh
-       fi
-       use module-src && emake DESTDIR="${D}" PREFIX="${EPREFIX}/usr" -C src dkms-install
-}
-
-pkg_postinst() {
-       if use module-src && ! use module; then
-               einfo
-               einfo "You have enabled the module-src USE flag without the module USE"
-               einfo "flag. This means that sources are installed to"
-               einfo "${ROOT}usr/src/wireguard instead of having the"
-               einfo "kernel module compiled. You will need to compile the module"
-               einfo "yourself. Most likely, you don't want this USE flag, and should"
-               einfo "rather use USE=module"
-               einfo
-       fi
-       use module && linux-mod_pkg_postinst
-
-       ewarn
-       ewarn "This software is experimental and has not yet been released."
-       ewarn "As such, it may contain significant issues. Please do not file"
-       ewarn "bug reports with Gentoo, but rather direct them upstream to:"
-       ewarn
-       ewarn "    team@wireguard.io    security@wireguard.io"
-       ewarn
-
-       if use tools; then
-               einfo
-               einfo "After installing WireGuard, if you'd like to try sending some packets through"
-               einfo "WireGuard, you may use, for testing purposes only, the insecure client.sh"
-               einfo "test example script:"
-               einfo
-               einfo "  \$ bzcat ${ROOT}usr/share/doc/${PF}/examples/ncat-client-server/client.sh.bz2 | sudo bash -"
-               einfo
-               einfo "This will automatically setup interface wg0, through a very insecure transport"
-               einfo "that is only suitable for demonstration purposes. You can then try loading the"
-               einfo "hidden website or sending pings:"
-               einfo
-               einfo "  \$ chromium http://192.168.4.1"
-               einfo "  \$ ping 192.168.4.1"
-               einfo
-               einfo "If you'd like to redirect your internet traffic, you can run it with the"
-               einfo "\"default-route\" argument. You may not use this server for any abusive or illegal"
-               einfo "purposes. It is for quick testing only."
-               einfo
-               einfo "More info on getting started can be found at: https://www.wireguard.io/quickstart/"
-               einfo
-       fi
-}