Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'wireguard-fixes'

Jason A. Donenfeld says:

====================
wireguard fixes for 6.4.2/6.5-rc1

Sorry to send these patches during the merge window, but they're net
fixes, not netdev enhancements, and while I'd ordinarily wait anyway,
I just got a first bug report for one of these fixes, which I originally
had thought was mostly unlikely. So please apply the following three
patches to net:

1) Make proper use of nr_cpu_ids with cpumask_next(), rather than
awkwardly using modulo, to handle dynamic CPU topology changes.
Linus noticed this a while ago and pointed it out, and today a user
actually got hit by it.

2) Respect persistent keepalive and other staged packets when setting
the private key after the interface is already up.

3) Use timer_delete_sync() instead of del_timer_sync(), per the
documentation.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+54 -30
+9 -5
drivers/net/wireguard/netlink.c
··· 546 546 u8 *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]); 547 547 u8 public_key[NOISE_PUBLIC_KEY_LEN]; 548 548 struct wg_peer *peer, *temp; 549 + bool send_staged_packets; 549 550 550 551 if (!crypto_memneq(wg->static_identity.static_private, 551 552 private_key, NOISE_PUBLIC_KEY_LEN)) ··· 565 564 } 566 565 567 566 down_write(&wg->static_identity.lock); 568 - wg_noise_set_static_identity_private_key(&wg->static_identity, 569 - private_key); 570 - list_for_each_entry_safe(peer, temp, &wg->peer_list, 571 - peer_list) { 567 + send_staged_packets = !wg->static_identity.has_identity && netif_running(wg->dev); 568 + wg_noise_set_static_identity_private_key(&wg->static_identity, private_key); 569 + send_staged_packets = send_staged_packets && wg->static_identity.has_identity; 570 + 571 + wg_cookie_checker_precompute_device_keys(&wg->cookie_checker); 572 + list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) { 572 573 wg_noise_precompute_static_static(peer); 573 574 wg_noise_expire_current_peer_keypairs(peer); 575 + if (send_staged_packets) 576 + wg_packet_send_staged_packets(peer); 574 577 } 575 - wg_cookie_checker_precompute_device_keys(&wg->cookie_checker); 576 578 up_write(&wg->static_identity.lock); 577 579 } 578 580 skip_set_private_key:
+1
drivers/net/wireguard/queueing.c
··· 28 28 int ret; 29 29 30 30 memset(queue, 0, sizeof(*queue)); 31 + queue->last_cpu = -1; 31 32 ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL); 32 33 if (ret) 33 34 return ret;
+11 -14
drivers/net/wireguard/queueing.h
··· 117 117 return cpu; 118 118 } 119 119 120 - /* This function is racy, in the sense that next is unlocked, so it could return 121 - * the same CPU twice. A race-free version of this would be to instead store an 122 - * atomic sequence number, do an increment-and-return, and then iterate through 123 - * every possible CPU until we get to that index -- choose_cpu. However that's 124 - * a bit slower, and it doesn't seem like this potential race actually 125 - * introduces any performance loss, so we live with it. 120 + /* This function is racy, in the sense that it's called while last_cpu is 121 + * unlocked, so it could return the same CPU twice. Adding locking or using 122 + * atomic sequence numbers is slower though, and the consequences of racing are 123 + * harmless, so live with it. 126 124 */ 127 - static inline int wg_cpumask_next_online(int *next) 125 + static inline int wg_cpumask_next_online(int *last_cpu) 128 126 { 129 - int cpu = *next; 130 - 131 - while (unlikely(!cpumask_test_cpu(cpu, cpu_online_mask))) 132 - cpu = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits; 133 - *next = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits; 127 + int cpu = cpumask_next(*last_cpu, cpu_online_mask); 128 + if (cpu >= nr_cpu_ids) 129 + cpu = cpumask_first(cpu_online_mask); 130 + *last_cpu = cpu; 134 131 return cpu; 135 132 } 136 133 ··· 156 159 157 160 static inline int wg_queue_enqueue_per_device_and_peer( 158 161 struct crypt_queue *device_queue, struct prev_queue *peer_queue, 159 - struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu) 162 + struct sk_buff *skb, struct workqueue_struct *wq) 160 163 { 161 164 int cpu; 162 165 ··· 170 173 /* Then we queue it up in the device queue, which consumes the 171 174 * packet as soon as it can. 172 175 */ 173 - cpu = wg_cpumask_next_online(next_cpu); 176 + cpu = wg_cpumask_next_online(&device_queue->last_cpu); 174 177 if (unlikely(ptr_ring_produce_bh(&device_queue->ring, skb))) 175 178 return -EPIPE; 176 179 queue_work_on(cpu, wq, &per_cpu_ptr(device_queue->worker, cpu)->work);
+1 -1
drivers/net/wireguard/receive.c
··· 524 524 goto err; 525 525 526 526 ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb, 527 - wg->packet_crypt_wq, &wg->decrypt_queue.last_cpu); 527 + wg->packet_crypt_wq); 528 528 if (unlikely(ret == -EPIPE)) 529 529 wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD); 530 530 if (likely(!ret || ret == -EPIPE)) {
+1 -1
drivers/net/wireguard/send.c
··· 318 318 goto err; 319 319 320 320 ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, &peer->tx_queue, first, 321 - wg->packet_crypt_wq, &wg->encrypt_queue.last_cpu); 321 + wg->packet_crypt_wq); 322 322 if (unlikely(ret == -EPIPE)) 323 323 wg_queue_enqueue_per_peer_tx(first, PACKET_STATE_DEAD); 324 324 err:
+5 -5
drivers/net/wireguard/timers.c
··· 234 234 235 235 void wg_timers_stop(struct wg_peer *peer) 236 236 { 237 - del_timer_sync(&peer->timer_retransmit_handshake); 238 - del_timer_sync(&peer->timer_send_keepalive); 239 - del_timer_sync(&peer->timer_new_handshake); 240 - del_timer_sync(&peer->timer_zero_key_material); 241 - del_timer_sync(&peer->timer_persistent_keepalive); 237 + timer_delete_sync(&peer->timer_retransmit_handshake); 238 + timer_delete_sync(&peer->timer_send_keepalive); 239 + timer_delete_sync(&peer->timer_new_handshake); 240 + timer_delete_sync(&peer->timer_zero_key_material); 241 + timer_delete_sync(&peer->timer_persistent_keepalive); 242 242 flush_work(&peer->clear_peer_work); 243 243 }
+26 -4
tools/testing/selftests/wireguard/netns.sh
··· 514 514 n1 ping -W 1 -c 1 192.168.241.2 515 515 [[ $(n2 wg show wg0 endpoints) == "$pub1 10.0.0.3:1" ]] 516 516 517 - ip1 link del veth1 518 - ip1 link del veth3 519 - ip1 link del wg0 520 - ip2 link del wg0 517 + ip1 link del dev veth3 518 + ip1 link del dev wg0 519 + ip2 link del dev wg0 520 + 521 + # Make sure persistent keep alives are sent when an adapter comes up 522 + ip1 link add dev wg0 type wireguard 523 + n1 wg set wg0 private-key <(echo "$key1") peer "$pub2" endpoint 10.0.0.1:1 persistent-keepalive 1 524 + read _ _ tx_bytes < <(n1 wg show wg0 transfer) 525 + [[ $tx_bytes -eq 0 ]] 526 + ip1 link set dev wg0 up 527 + read _ _ tx_bytes < <(n1 wg show wg0 transfer) 528 + [[ $tx_bytes -gt 0 ]] 529 + ip1 link del dev wg0 530 + # This should also happen even if the private key is set later 531 + ip1 link add dev wg0 type wireguard 532 + n1 wg set wg0 peer "$pub2" endpoint 10.0.0.1:1 persistent-keepalive 1 533 + read _ _ tx_bytes < <(n1 wg show wg0 transfer) 534 + [[ $tx_bytes -eq 0 ]] 535 + ip1 link set dev wg0 up 536 + read _ _ tx_bytes < <(n1 wg show wg0 transfer) 537 + [[ $tx_bytes -eq 0 ]] 538 + n1 wg set wg0 private-key <(echo "$key1") 539 + read _ _ tx_bytes < <(n1 wg show wg0 transfer) 540 + [[ $tx_bytes -gt 0 ]] 541 + ip1 link del dev veth1 542 + ip1 link del dev wg0 521 543 522 544 # We test that Netlink/IPC is working properly by doing things that usually cause split responses 523 545 ip0 link add dev wg0 type wireguard