summaryrefslogtreecommitdiffhomepage
path: root/src/device.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2016-12-08 01:53:22 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2016-12-09 21:31:11 +0100
commitede883632b7ec00a58bfe061242654497d99a395 (patch)
tree45c89634ac782f1c3a0b4aaba83073d95d1975e4 /src/device.c
parentf8c783d1df62700c1e4ede30f137f5013b6b729a (diff)
device: clear all peer ephemeral keys on sleep
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/device.c')
-rw-r--r--src/device.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/device.c b/src/device.c
index 478efef..3b32a75 100644
--- a/src/device.c
+++ b/src/device.c
@@ -15,6 +15,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/icmp.h>
+#include <linux/suspend.h>
#include <net/icmp.h>
#include <net/rtnetlink.h>
#include <net/ip_tunnels.h>
@@ -54,11 +55,31 @@ static int open(struct net_device *dev)
return 0;
}
-static int stop_peer(struct wireguard_peer *peer, void *data)
+static int clear_noise_peer(struct wireguard_peer *peer, void *data)
{
- timers_uninit_peer_wait(peer);
noise_handshake_clear(&peer->handshake);
noise_keypairs_clear(&peer->keypairs);
+ if (peer->timer_kill_ephemerals.data)
+ del_timer(&peer->timer_kill_ephemerals);
+ return 0;
+}
+
+static int suspending_clear_noise_peers(struct notifier_block *nb, unsigned long action, void *data)
+{
+ struct wireguard_device *wg = container_of(nb, struct wireguard_device, clear_peers_on_suspend);
+ switch (action) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ peer_for_each(wg, clear_noise_peer, NULL);
+ rcu_barrier();
+ }
+ return 0;
+}
+
+static int stop_peer(struct wireguard_peer *peer, void *data)
+{
+ timers_uninit_peer_wait(peer);
+ clear_noise_peer(peer, data);
return 0;
}
@@ -215,6 +236,7 @@ static void destruct(struct net_device *dev)
skb_queue_purge(&wg->incoming_handshakes);
socket_uninit(wg);
cookie_checker_uninit(&wg->cookie_checker);
+ unregister_pm_notifier(&wg->clear_peers_on_suspend);
mutex_unlock(&wg->device_update_lock);
put_net(wg->creating_net);
@@ -304,6 +326,13 @@ static int newlink(struct net *src_net, struct net_device *dev, struct nlattr *t
if (ret < 0)
goto err;
+ wg->clear_peers_on_suspend.notifier_call = suspending_clear_noise_peers;
+ ret = register_pm_notifier(&wg->clear_peers_on_suspend);
+ if (ret < 0) {
+ wg->clear_peers_on_suspend.notifier_call = NULL;
+ goto err;
+ }
+
ret = register_netdevice(dev);
if (ret < 0)
goto err;
@@ -326,6 +355,8 @@ err:
#endif
if (wg->cookie_checker.device)
cookie_checker_uninit(&wg->cookie_checker);
+ if (wg->clear_peers_on_suspend.notifier_call)
+ unregister_pm_notifier(&wg->clear_peers_on_suspend);
return ret;
}