From ede883632b7ec00a58bfe061242654497d99a395 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 8 Dec 2016 01:53:22 +0100 Subject: device: clear all peer ephemeral keys on sleep Signed-off-by: Jason A. Donenfeld --- src/device.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'src/device.c') 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 #include #include +#include #include #include #include @@ -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; } -- cgit v1.2.3