diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-12-08 01:53:22 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-12-09 21:31:11 +0100 |
commit | ede883632b7ec00a58bfe061242654497d99a395 (patch) | |
tree | 45c89634ac782f1c3a0b4aaba83073d95d1975e4 /src/device.c | |
parent | f8c783d1df62700c1e4ede30f137f5013b6b729a (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.c | 35 |
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; } |