18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "peer.h" 78c2ecf20Sopenharmony_ci#include "device.h" 88c2ecf20Sopenharmony_ci#include "queueing.h" 98c2ecf20Sopenharmony_ci#include "timers.h" 108c2ecf20Sopenharmony_ci#include "peerlookup.h" 118c2ecf20Sopenharmony_ci#include "noise.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/kref.h> 148c2ecf20Sopenharmony_ci#include <linux/lockdep.h> 158c2ecf20Sopenharmony_ci#include <linux/rcupdate.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic struct kmem_cache *peer_cache; 198c2ecf20Sopenharmony_cistatic atomic64_t peer_counter = ATOMIC64_INIT(0); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistruct wg_peer *wg_peer_create(struct wg_device *wg, 228c2ecf20Sopenharmony_ci const u8 public_key[NOISE_PUBLIC_KEY_LEN], 238c2ecf20Sopenharmony_ci const u8 preshared_key[NOISE_SYMMETRIC_KEY_LEN]) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci struct wg_peer *peer; 268c2ecf20Sopenharmony_ci int ret = -ENOMEM; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci lockdep_assert_held(&wg->device_update_lock); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci if (wg->num_peers >= MAX_PEERS_PER_DEVICE) 318c2ecf20Sopenharmony_ci return ERR_PTR(ret); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci peer = kmem_cache_zalloc(peer_cache, GFP_KERNEL); 348c2ecf20Sopenharmony_ci if (unlikely(!peer)) 358c2ecf20Sopenharmony_ci return ERR_PTR(ret); 368c2ecf20Sopenharmony_ci if (unlikely(dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))) 378c2ecf20Sopenharmony_ci goto err; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci peer->device = wg; 408c2ecf20Sopenharmony_ci wg_noise_handshake_init(&peer->handshake, &wg->static_identity, 418c2ecf20Sopenharmony_ci public_key, preshared_key, peer); 428c2ecf20Sopenharmony_ci peer->internal_id = atomic64_inc_return(&peer_counter); 438c2ecf20Sopenharmony_ci peer->serial_work_cpu = nr_cpumask_bits; 448c2ecf20Sopenharmony_ci wg_cookie_init(&peer->latest_cookie); 458c2ecf20Sopenharmony_ci wg_timers_init(peer); 468c2ecf20Sopenharmony_ci wg_cookie_checker_precompute_peer_keys(peer); 478c2ecf20Sopenharmony_ci spin_lock_init(&peer->keypairs.keypair_update_lock); 488c2ecf20Sopenharmony_ci INIT_WORK(&peer->transmit_handshake_work, wg_packet_handshake_send_worker); 498c2ecf20Sopenharmony_ci INIT_WORK(&peer->transmit_packet_work, wg_packet_tx_worker); 508c2ecf20Sopenharmony_ci wg_prev_queue_init(&peer->tx_queue); 518c2ecf20Sopenharmony_ci wg_prev_queue_init(&peer->rx_queue); 528c2ecf20Sopenharmony_ci rwlock_init(&peer->endpoint_lock); 538c2ecf20Sopenharmony_ci kref_init(&peer->refcount); 548c2ecf20Sopenharmony_ci skb_queue_head_init(&peer->staged_packet_queue); 558c2ecf20Sopenharmony_ci wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake); 568c2ecf20Sopenharmony_ci set_bit(NAPI_STATE_NO_BUSY_POLL, &peer->napi.state); 578c2ecf20Sopenharmony_ci netif_napi_add(wg->dev, &peer->napi, wg_packet_rx_poll, 588c2ecf20Sopenharmony_ci NAPI_POLL_WEIGHT); 598c2ecf20Sopenharmony_ci napi_enable(&peer->napi); 608c2ecf20Sopenharmony_ci list_add_tail(&peer->peer_list, &wg->peer_list); 618c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&peer->allowedips_list); 628c2ecf20Sopenharmony_ci wg_pubkey_hashtable_add(wg->peer_hashtable, peer); 638c2ecf20Sopenharmony_ci ++wg->num_peers; 648c2ecf20Sopenharmony_ci pr_debug("%s: Peer %llu created\n", wg->dev->name, peer->internal_id); 658c2ecf20Sopenharmony_ci return peer; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cierr: 688c2ecf20Sopenharmony_ci kmem_cache_free(peer_cache, peer); 698c2ecf20Sopenharmony_ci return ERR_PTR(ret); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistruct wg_peer *wg_peer_get_maybe_zero(struct wg_peer *peer) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci RCU_LOCKDEP_WARN(!rcu_read_lock_bh_held(), 758c2ecf20Sopenharmony_ci "Taking peer reference without holding the RCU read lock"); 768c2ecf20Sopenharmony_ci if (unlikely(!peer || !kref_get_unless_zero(&peer->refcount))) 778c2ecf20Sopenharmony_ci return NULL; 788c2ecf20Sopenharmony_ci return peer; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic void peer_make_dead(struct wg_peer *peer) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci /* Remove from configuration-time lookup structures. */ 848c2ecf20Sopenharmony_ci list_del_init(&peer->peer_list); 858c2ecf20Sopenharmony_ci wg_allowedips_remove_by_peer(&peer->device->peer_allowedips, peer, 868c2ecf20Sopenharmony_ci &peer->device->device_update_lock); 878c2ecf20Sopenharmony_ci wg_pubkey_hashtable_remove(peer->device->peer_hashtable, peer); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* Mark as dead, so that we don't allow jumping contexts after. */ 908c2ecf20Sopenharmony_ci WRITE_ONCE(peer->is_dead, true); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* The caller must now synchronize_net() for this to take effect. */ 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic void peer_remove_after_dead(struct wg_peer *peer) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci WARN_ON(!peer->is_dead); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* No more keypairs can be created for this peer, since is_dead protects 1008c2ecf20Sopenharmony_ci * add_new_keypair, so we can now destroy existing ones. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_ci wg_noise_keypairs_clear(&peer->keypairs); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* Destroy all ongoing timers that were in-flight at the beginning of 1058c2ecf20Sopenharmony_ci * this function. 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci wg_timers_stop(peer); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* The transition between packet encryption/decryption queues isn't 1108c2ecf20Sopenharmony_ci * guarded by is_dead, but each reference's life is strictly bounded by 1118c2ecf20Sopenharmony_ci * two generations: once for parallel crypto and once for serial 1128c2ecf20Sopenharmony_ci * ingestion, so we can simply flush twice, and be sure that we no 1138c2ecf20Sopenharmony_ci * longer have references inside these queues. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* a) For encrypt/decrypt. */ 1178c2ecf20Sopenharmony_ci flush_workqueue(peer->device->packet_crypt_wq); 1188c2ecf20Sopenharmony_ci /* b.1) For send (but not receive, since that's napi). */ 1198c2ecf20Sopenharmony_ci flush_workqueue(peer->device->packet_crypt_wq); 1208c2ecf20Sopenharmony_ci /* b.2.1) For receive (but not send, since that's wq). */ 1218c2ecf20Sopenharmony_ci napi_disable(&peer->napi); 1228c2ecf20Sopenharmony_ci /* b.2.1) It's now safe to remove the napi struct, which must be done 1238c2ecf20Sopenharmony_ci * here from process context. 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci netif_napi_del(&peer->napi); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Ensure any workstructs we own (like transmit_handshake_work or 1288c2ecf20Sopenharmony_ci * clear_peer_work) no longer are in use. 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_ci flush_workqueue(peer->device->handshake_send_wq); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* After the above flushes, a peer might still be active in a few 1338c2ecf20Sopenharmony_ci * different contexts: 1) from xmit(), before hitting is_dead and 1348c2ecf20Sopenharmony_ci * returning, 2) from wg_packet_consume_data(), before hitting is_dead 1358c2ecf20Sopenharmony_ci * and returning, 3) from wg_receive_handshake_packet() after a point 1368c2ecf20Sopenharmony_ci * where it has processed an incoming handshake packet, but where 1378c2ecf20Sopenharmony_ci * all calls to pass it off to timers fails because of is_dead. We won't 1388c2ecf20Sopenharmony_ci * have new references in (1) eventually, because we're removed from 1398c2ecf20Sopenharmony_ci * allowedips; we won't have new references in (2) eventually, because 1408c2ecf20Sopenharmony_ci * wg_index_hashtable_lookup will always return NULL, since we removed 1418c2ecf20Sopenharmony_ci * all existing keypairs and no more can be created; we won't have new 1428c2ecf20Sopenharmony_ci * references in (3) eventually, because we're removed from the pubkey 1438c2ecf20Sopenharmony_ci * hash table, which allows for a maximum of one handshake response, 1448c2ecf20Sopenharmony_ci * via the still-uncleared index hashtable entry, but not more than one, 1458c2ecf20Sopenharmony_ci * and in wg_cookie_message_consume, the lookup eventually gets a peer 1468c2ecf20Sopenharmony_ci * with a refcount of zero, so no new reference is taken. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci --peer->device->num_peers; 1508c2ecf20Sopenharmony_ci wg_peer_put(peer); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* We have a separate "remove" function make sure that all active places where 1548c2ecf20Sopenharmony_ci * a peer is currently operating will eventually come to an end and not pass 1558c2ecf20Sopenharmony_ci * their reference onto another context. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_civoid wg_peer_remove(struct wg_peer *peer) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci if (unlikely(!peer)) 1608c2ecf20Sopenharmony_ci return; 1618c2ecf20Sopenharmony_ci lockdep_assert_held(&peer->device->device_update_lock); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci peer_make_dead(peer); 1648c2ecf20Sopenharmony_ci synchronize_net(); 1658c2ecf20Sopenharmony_ci peer_remove_after_dead(peer); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_civoid wg_peer_remove_all(struct wg_device *wg) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci struct wg_peer *peer, *temp; 1718c2ecf20Sopenharmony_ci LIST_HEAD(dead_peers); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci lockdep_assert_held(&wg->device_update_lock); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Avoid having to traverse individually for each one. */ 1768c2ecf20Sopenharmony_ci wg_allowedips_free(&wg->peer_allowedips, &wg->device_update_lock); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) { 1798c2ecf20Sopenharmony_ci peer_make_dead(peer); 1808c2ecf20Sopenharmony_ci list_add_tail(&peer->peer_list, &dead_peers); 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci synchronize_net(); 1838c2ecf20Sopenharmony_ci list_for_each_entry_safe(peer, temp, &dead_peers, peer_list) 1848c2ecf20Sopenharmony_ci peer_remove_after_dead(peer); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic void rcu_release(struct rcu_head *rcu) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci struct wg_peer *peer = container_of(rcu, struct wg_peer, rcu); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci dst_cache_destroy(&peer->endpoint_cache); 1928c2ecf20Sopenharmony_ci WARN_ON(wg_prev_queue_peek(&peer->tx_queue) || wg_prev_queue_peek(&peer->rx_queue)); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* The final zeroing takes care of clearing any remaining handshake key 1958c2ecf20Sopenharmony_ci * material and other potentially sensitive information. 1968c2ecf20Sopenharmony_ci */ 1978c2ecf20Sopenharmony_ci memzero_explicit(peer, sizeof(*peer)); 1988c2ecf20Sopenharmony_ci kmem_cache_free(peer_cache, peer); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic void kref_release(struct kref *refcount) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci struct wg_peer *peer = container_of(refcount, struct wg_peer, refcount); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci pr_debug("%s: Peer %llu (%pISpfsc) destroyed\n", 2068c2ecf20Sopenharmony_ci peer->device->dev->name, peer->internal_id, 2078c2ecf20Sopenharmony_ci &peer->endpoint.addr); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* Remove ourself from dynamic runtime lookup structures, now that the 2108c2ecf20Sopenharmony_ci * last reference is gone. 2118c2ecf20Sopenharmony_ci */ 2128c2ecf20Sopenharmony_ci wg_index_hashtable_remove(peer->device->index_hashtable, 2138c2ecf20Sopenharmony_ci &peer->handshake.entry); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* Remove any lingering packets that didn't have a chance to be 2168c2ecf20Sopenharmony_ci * transmitted. 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci wg_packet_purge_staged_packets(peer); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* Free the memory used. */ 2218c2ecf20Sopenharmony_ci call_rcu(&peer->rcu, rcu_release); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_civoid wg_peer_put(struct wg_peer *peer) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci if (unlikely(!peer)) 2278c2ecf20Sopenharmony_ci return; 2288c2ecf20Sopenharmony_ci kref_put(&peer->refcount, kref_release); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciint __init wg_peer_init(void) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci peer_cache = KMEM_CACHE(wg_peer, 0); 2348c2ecf20Sopenharmony_ci return peer_cache ? 0 : -ENOMEM; 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_civoid wg_peer_uninit(void) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci kmem_cache_destroy(peer_cache); 2408c2ecf20Sopenharmony_ci} 241