mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 06:41:39 -04:00
Merge branch 'wireguard-fixes-for-7-1-rc1'
Jason A. Donenfeld says: ==================== WireGuard fixes for 7.1-rc1 1) Asbjørn's YNL sample, finally merged. Sorry for the wait on this one. 2) A simplification to use kfree_rcu instead of call_rcu, since kfree_rcu now works with kmem caches. 3) A trivial formatting derp. 4) Fix for a deadlock by moving to using exit_rtnl instead of pre_exit. ==================== Link: https://patch.msgid.link/20260414153944.2742252-1-Jason@zx2c4.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -48,11 +48,6 @@ static void push_rcu(struct allowedips_node **stack,
|
||||
}
|
||||
}
|
||||
|
||||
static void node_free_rcu(struct rcu_head *rcu)
|
||||
{
|
||||
kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu));
|
||||
}
|
||||
|
||||
static void root_free_rcu(struct rcu_head *rcu)
|
||||
{
|
||||
struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = {
|
||||
@@ -271,13 +266,13 @@ static void remove_node(struct allowedips_node *node, struct mutex *lock)
|
||||
if (free_parent)
|
||||
child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)],
|
||||
lockdep_is_held(lock));
|
||||
call_rcu(&node->rcu, node_free_rcu);
|
||||
kfree_rcu(node, rcu);
|
||||
if (!free_parent)
|
||||
return;
|
||||
if (child)
|
||||
child->parent_bit_packed = parent->parent_bit_packed;
|
||||
*(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child;
|
||||
call_rcu(&parent->rcu, node_free_rcu);
|
||||
kfree_rcu(parent, rcu);
|
||||
}
|
||||
|
||||
static int remove(struct allowedips_node __rcu **trie, u8 bits, const u8 *key,
|
||||
|
||||
@@ -411,12 +411,11 @@ static struct rtnl_link_ops link_ops __read_mostly = {
|
||||
.newlink = wg_newlink,
|
||||
};
|
||||
|
||||
static void wg_netns_pre_exit(struct net *net)
|
||||
static void __net_exit wg_netns_exit_rtnl(struct net *net, struct list_head *dev_kill_list)
|
||||
{
|
||||
struct wg_device *wg;
|
||||
struct wg_peer *peer;
|
||||
|
||||
rtnl_lock();
|
||||
list_for_each_entry(wg, &device_list, device_list) {
|
||||
if (rcu_access_pointer(wg->creating_net) == net) {
|
||||
pr_debug("%s: Creating namespace exiting\n", wg->dev->name);
|
||||
@@ -429,11 +428,10 @@ static void wg_netns_pre_exit(struct net *net)
|
||||
mutex_unlock(&wg->device_update_lock);
|
||||
}
|
||||
}
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static struct pernet_operations pernet_ops = {
|
||||
.pre_exit = wg_netns_pre_exit
|
||||
static struct pernet_operations pernet_ops __read_mostly = {
|
||||
.exit_rtnl = wg_netns_exit_rtnl
|
||||
};
|
||||
|
||||
int __init wg_device_init(void)
|
||||
|
||||
@@ -623,7 +623,7 @@ bool __init wg_allowedips_selftest(void)
|
||||
test_boolean(!remove(6, b, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128));
|
||||
test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef);
|
||||
/* invalid CIDR should have no effect and return -EINVAL */
|
||||
test_boolean(remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 129) == -EINVAL);
|
||||
test_boolean(remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 129) == -EINVAL);
|
||||
test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef);
|
||||
remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128);
|
||||
test_negative(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef);
|
||||
|
||||
1
tools/net/ynl/tests/.gitignore
vendored
1
tools/net/ynl/tests/.gitignore
vendored
@@ -7,3 +7,4 @@ rt-link
|
||||
rt-route
|
||||
tc
|
||||
tc-filter-add
|
||||
wireguard
|
||||
|
||||
106
tools/net/ynl/tests/wireguard.c
Normal file
106
tools/net/ynl/tests/wireguard.c
Normal file
@@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ynl.h>
|
||||
|
||||
#include "wireguard-user.h"
|
||||
|
||||
static void print_allowed_ip(const struct wireguard_wgallowedip *aip)
|
||||
{
|
||||
char addr_out[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!inet_ntop(aip->family, aip->ipaddr, addr_out, sizeof(addr_out))) {
|
||||
addr_out[0] = '?';
|
||||
addr_out[1] = '\0';
|
||||
}
|
||||
printf("\t\t\t%s/%u\n", addr_out, aip->cidr_mask);
|
||||
}
|
||||
|
||||
/* Only printing public key in this demo. For better key formatting,
|
||||
* use the constant-time implementation as found in wireguard-tools.
|
||||
*/
|
||||
static void print_peer_header(const struct wireguard_wgpeer *peer)
|
||||
{
|
||||
unsigned int len = peer->_len.public_key;
|
||||
uint8_t *key = peer->public_key;
|
||||
unsigned int i;
|
||||
|
||||
if (len != 32)
|
||||
return;
|
||||
printf("\tPeer ");
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02x", key[i]);
|
||||
printf(":\n");
|
||||
}
|
||||
|
||||
static void print_peer(const struct wireguard_wgpeer *peer)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
print_peer_header(peer);
|
||||
printf("\t\tData: rx: %llu / tx: %llu bytes\n",
|
||||
peer->rx_bytes, peer->tx_bytes);
|
||||
printf("\t\tAllowed IPs:\n");
|
||||
for (i = 0; i < peer->_count.allowedips; i++)
|
||||
print_allowed_ip(&peer->allowedips[i]);
|
||||
}
|
||||
|
||||
static void build_request(struct wireguard_get_device_req *req, char *arg)
|
||||
{
|
||||
char *endptr;
|
||||
int ifindex;
|
||||
|
||||
ifindex = strtol(arg, &endptr, 0);
|
||||
if (endptr != arg + strlen(arg) || errno != 0)
|
||||
ifindex = 0;
|
||||
if (ifindex > 0)
|
||||
wireguard_get_device_req_set_ifindex(req, ifindex);
|
||||
else
|
||||
wireguard_get_device_req_set_ifname(req, arg);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct wireguard_get_device_list *devs;
|
||||
struct wireguard_get_device_req *req;
|
||||
struct ynl_error yerr;
|
||||
struct ynl_sock *ys;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s <ifindex|ifname>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ys = ynl_sock_create(&ynl_wireguard_family, &yerr);
|
||||
if (!ys) {
|
||||
fprintf(stderr, "YNL: %s\n", yerr.msg);
|
||||
return 2;
|
||||
}
|
||||
|
||||
req = wireguard_get_device_req_alloc();
|
||||
build_request(req, argv[1]);
|
||||
|
||||
devs = wireguard_get_device_dump(ys, req);
|
||||
if (!devs) {
|
||||
fprintf(stderr, "YNL (%d): %s\n", ys->err.code, ys->err.msg);
|
||||
wireguard_get_device_req_free(req);
|
||||
ynl_sock_destroy(ys);
|
||||
return 3;
|
||||
}
|
||||
|
||||
ynl_dump_foreach(devs, d) {
|
||||
unsigned int i;
|
||||
|
||||
printf("Interface %d: %s\n", d->ifindex, d->ifname);
|
||||
for (i = 0; i < d->_count.peers; i++)
|
||||
print_peer(&d->peers[i]);
|
||||
}
|
||||
|
||||
wireguard_get_device_list_free(devs);
|
||||
wireguard_get_device_req_free(req);
|
||||
ynl_sock_destroy(ys);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user