Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion kernel-src/cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ static int __must_check make_cookie(u8 cookie[COOKIE_LEN], struct sk_buff *skb,
if ((ret == 0) && wg_birthdate_has_expired(checker->secret_birthdate,
COOKIE_SECRET_MAX_AGE)) {
down_write(&checker->secret_lock);
checker->secret_birthdate = ktime_get_coarse_boottime_ns();
ret = wc_get_random_bytes(checker->secret, NOISE_HASH_LEN);
if (ret == 0)
checker->secret_birthdate = ktime_get_coarse_boottime_ns();
up_write(&checker->secret_lock);
}

Expand Down
9 changes: 7 additions & 2 deletions kernel-src/receive.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ static int wg_receive_handshake_packet(struct wg_device *wg,
static u64 last_under_load;
bool packet_needs_cookie;
bool under_load;
int ret;

if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE)) {
net_dbg_skb_ratelimited("%s: Receiving cookie response from %pISpfsc\n",
Expand Down Expand Up @@ -167,12 +168,13 @@ static int wg_receive_handshake_packet(struct wg_device *wg,
wg->dev->name, peer->internal_id,
&peer->endpoint.addr);
{
int ret = wg_packet_send_handshake_response(peer);
ret = wg_packet_send_handshake_response(peer);
if (ret < 0) {
wg_peer_put(peer);
return ret;
}
}
ret = 0;
break;
}
case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): {
Expand Down Expand Up @@ -204,7 +206,10 @@ static int wg_receive_handshake_packet(struct wg_device *wg,
* immediate confirmation of the session.
*/
wg_packet_send_keepalive(peer);
ret = 0;
}
else
ret = -ECANCELED;
break;
}
}
Expand All @@ -222,7 +227,7 @@ static int wg_receive_handshake_packet(struct wg_device *wg,
wg_timers_any_authenticated_packet_traversal(peer);
wg_peer_put(peer);

return 0;
return ret;
}

void wg_packet_handshake_receive_worker(struct work_struct *work)
Expand Down
52 changes: 39 additions & 13 deletions kernel-src/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,43 @@ static int __must_check wg_packet_send_handshake_initiation(struct wg_peer *peer
{
struct message_handshake_initiation packet;
int ret;
u64 cur_last_sent_handshake = atomic64_read(&peer->last_sent_handshake);
u64 speculative_last_sent_handshake;

if (!wg_birthdate_has_expired(atomic64_read(&peer->last_sent_handshake),
if (!wg_birthdate_has_expired(cur_last_sent_handshake,
REKEY_TIMEOUT))
return 0; /* This function is rate limited. */

atomic64_set(&peer->last_sent_handshake, ktime_get_coarse_boottime_ns());
speculative_last_sent_handshake = ktime_get_coarse_boottime_ns();
atomic64_set(&peer->last_sent_handshake, speculative_last_sent_handshake);
net_dbg_ratelimited("%s: Sending handshake initiation to peer %llu (%pISpfsc)\n",
peer->device->dev->name, peer->internal_id,
&peer->endpoint.addr);

if (wg_noise_handshake_create_initiation(&packet, &peer->handshake)) {
ret = wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer);
if (ret == 0) {
wg_timers_any_authenticated_packet_traversal(peer);
wg_timers_any_authenticated_packet_sent(peer);
atomic64_set(&peer->last_sent_handshake,
ktime_get_coarse_boottime_ns());
(void)wg_socket_send_buffer_to_peer(peer, &packet, sizeof(packet),
ret = wg_socket_send_buffer_to_peer(peer, &packet, sizeof(packet),
HANDSHAKE_DSCP);
if (ret == 0) {
atomic64_set(&peer->last_sent_handshake,
ktime_get_coarse_boottime_ns());
wg_timers_any_authenticated_packet_traversal(peer);
wg_timers_any_authenticated_packet_sent(peer);
}
}
wg_timers_handshake_initiated(peer);
wg_timers_handshake_initiated(peer); /* restart retry timer even
* if send failed.
*/
}
else
ret = -ECANCELED;

if (ret != 0)
(void)atomic64_cmpxchg_relaxed(&peer->last_sent_handshake,
speculative_last_sent_handshake,
cur_last_sent_handshake);

memzero_explicit(&packet, sizeof packet);

return ret;
Expand All @@ -60,8 +72,19 @@ void wg_packet_handshake_send_worker(struct work_struct *work)
transmit_handshake_work);
int ret = wg_packet_send_handshake_initiation(peer);
wg_peer_put(peer);
if (ret != 0)
pr_err("wg_packet_handshake_send_worker(): wg_packet_send_handshake_initiation() returned %d.\n", ret);
if (ret != 0) {
switch (ret) {
case -ENETUNREACH:
case -EHOSTUNREACH:
case -ENETDOWN:
case -EAGAIN:
pr_info_ratelimited("wg_packet_handshake_send_worker(): wg_packet_send_handshake_initiation() returned %d.\n", ret);
break;
default:
pr_err_ratelimited("wg_packet_handshake_send_worker(): wg_packet_send_handshake_initiation() returned %d.\n", ret);
break;
}
}
}

void wg_packet_send_queued_handshake_initiation(struct wg_peer *peer,
Expand Down Expand Up @@ -106,9 +129,12 @@ int __must_check wg_packet_send_handshake_response(struct wg_peer *peer)

if (wg_noise_handshake_create_response(&packet, &peer->handshake)) {
ret = wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer);
if ((ret == 0) &&
wg_noise_handshake_begin_session(&peer->handshake,
&peer->keypairs)) {
if (ret == 0) {
if (! wg_noise_handshake_begin_session(&peer->handshake,
&peer->keypairs))
ret = -ECANCELED;
}
if (ret == 0) {
wg_timers_session_derived(peer);
wg_timers_any_authenticated_packet_traversal(peer);
wg_timers_any_authenticated_packet_sent(peer);
Expand Down
2 changes: 1 addition & 1 deletion user-src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la
else if (new_allowedip->family == AF_INET6)
cidr = 128;
else
goto err;
goto err; /* defensive -- don't count on parse_ip() only succeeding for IPv4 and IPv6. */
new_allowedip->cidr = cidr;

if (!validate_netmask(new_allowedip))
Expand Down
14 changes: 7 additions & 7 deletions user-src/containers.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,23 @@ struct wgdevice {
#define for_each_wgpeer(__dev, __peer) for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
#define for_each_wgallowedip(__peer, __allowedip) for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); (__allowedip) = (__allowedip)->next_allowedip)

static inline void memzero_explicit(void *p, size_t len) {
static void *(* const volatile memset_func)(void *, int, size_t) = memset;
(void)memset_func(p, 0, len);
}

static inline void free_wgdevice(struct wgdevice *dev)
{
if (!dev)
return;
for (struct wgpeer *peer = dev->first_peer, *np = peer ? peer->next_peer : NULL; peer; peer = np, np = peer ? peer->next_peer : NULL) {
for (struct wgallowedip *allowedip = peer->first_allowedip, *na = allowedip ? allowedip->next_allowedip : NULL; allowedip; allowedip = na, na = allowedip ? allowedip->next_allowedip : NULL)
free(allowedip);
memset(peer->preshared_key, 0, sizeof peer->preshared_key);
memzero_explicit(peer->preshared_key, sizeof peer->preshared_key);
free(peer);
}
memset(dev->private_key, 0, sizeof dev->private_key);
memzero_explicit(dev->private_key, sizeof dev->private_key);
free(dev);
}

static inline void memzero_explicit(void *p, size_t len) {
static void *(* const volatile memset_func)(void *, int, size_t) = memset;
(void)memset_func(p, 0, len);
}

#endif
2 changes: 2 additions & 0 deletions user-src/ipc-linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ static void coalesce_peers(struct wgdevice *device)
}
old_next_peer = peer->next_peer;
peer->next_peer = old_next_peer->next_peer;
if (device->last_peer == old_next_peer)
device->last_peer = peer;
memzero_explicit(old_next_peer->preshared_key, sizeof old_next_peer->preshared_key);
free(old_next_peer);
}
Expand Down
2 changes: 1 addition & 1 deletion user-src/ipc-uapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ static int userspace_set_device(struct wgdevice *dev)

out:

memset(hex, 0, sizeof hex);
memzero_explicit(hex, sizeof hex);
fclose(f);
errno = -ret;
return ret;
Expand Down
10 changes: 6 additions & 4 deletions user-src/setconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ static bool sync_conf(struct wgdevice *file)
}
peer->flags = WGPEER_REMOVE_ME;
memcpy(peer->public_key, pubkeys[i].pubkey, WG_PUBLIC_KEY_LEN);
peer->next_peer = file->first_peer;
file->first_peer = peer;
if (!file->last_peer)
file->last_peer = peer;
if (! file->first_peer)
file->first_peer = peer;
if (file->last_peer)
file->last_peer->next_peer = peer;
file->last_peer = peer;

}
}
free_wgdevice(runtime);
Expand Down
1 change: 1 addition & 0 deletions user-src/show.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ static void sort_peers(struct wgdevice *device)
peers[i - 1]->next_peer = peers[i];
}
peers[peer_count - 1]->next_peer = NULL;
device->last_peer = peers[peer_count - 1];
free(peers);
}

Expand Down