Skip to content
This repository has been archived by the owner on Dec 27, 2019. It is now read-only.

Commit

Permalink
global: switch to coarse ktime
Browse files Browse the repository at this point in the history
Coarse ktime is broken until [1] in 5.2, so we provide compat for all
prior kernels.

[1] https://lore.kernel.org/lkml/[email protected]/

Suggested-by: Arnd Bergmann <[email protected]>
  • Loading branch information
zx2c4 committed Jun 24, 2019
1 parent 7d47894 commit 0d9758d
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 19 deletions.
20 changes: 20 additions & 0 deletions src/compat/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,26 @@ static inline u64 __compat_ktime_get_boot_fast_ns(void)
#define ktime_get_boot_fast_ns __compat_ktime_get_boot_fast_ns
#endif

#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 12) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) || LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 53)
#include <linux/ktime.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
#include <linux/timekeeping.h>
#endif
/* This function exists in earlier versions, but the sub-seconds portion is always zero until 5.2 and backports to 5.1 and 4.19. */
#define ktime_get_coarse_boottime ktime_get_boot_fast_ns
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0)
#include <linux/ktime.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
#include <linux/timekeeping.h>
#endif
static inline u64 ktime_get_coarse_boottime_ns(void)
{
return ktime_to_ns(ktime_get_coarse_boottime());
}
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
#include <linux/inetdevice.h>
static inline __be32 __compat_confirm_addr_indev(struct in_device *in_dev, __be32 dst, __be32 local, int scope)
Expand Down
6 changes: 3 additions & 3 deletions src/cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void wg_cookie_checker_init(struct cookie_checker *checker,
struct wg_device *wg)
{
init_rwsem(&checker->secret_lock);
checker->secret_birthdate = ktime_get_boot_fast_ns();
checker->secret_birthdate = ktime_get_coarse_boottime_ns();
get_random_bytes(checker->secret, NOISE_HASH_LEN);
checker->device = wg;
}
Expand Down Expand Up @@ -96,7 +96,7 @@ static void make_cookie(u8 cookie[COOKIE_LEN], struct sk_buff *skb,
if (wg_birthdate_has_expired(checker->secret_birthdate,
COOKIE_SECRET_MAX_AGE)) {
down_write(&checker->secret_lock);
checker->secret_birthdate = ktime_get_boot_fast_ns();
checker->secret_birthdate = ktime_get_coarse_boottime_ns();
get_random_bytes(checker->secret, NOISE_HASH_LEN);
up_write(&checker->secret_lock);
}
Expand Down Expand Up @@ -222,7 +222,7 @@ void wg_cookie_message_consume(struct message_handshake_cookie *src,
if (ret) {
down_write(&peer->latest_cookie.lock);
memcpy(peer->latest_cookie.cookie, cookie, COOKIE_LEN);
peer->latest_cookie.birthdate = ktime_get_boot_fast_ns();
peer->latest_cookie.birthdate = ktime_get_coarse_boottime_ns();
peer->latest_cookie.is_valid = true;
peer->latest_cookie.have_sent_mac1 = false;
up_write(&peer->latest_cookie.lock);
Expand Down
2 changes: 1 addition & 1 deletion src/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static int wg_stop(struct net_device *dev)
wg_noise_handshake_clear(&peer->handshake);
wg_noise_keypairs_clear(&peer->keypairs);
atomic64_set(&peer->last_sent_handshake,
ktime_get_boot_fast_ns() -
ktime_get_coarse_boottime_ns() -
(u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC);
}
mutex_unlock(&wg->device_update_lock);
Expand Down
8 changes: 4 additions & 4 deletions src/noise.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ static void symmetric_key_init(struct noise_symmetric_key *key)
atomic64_set(&key->counter.counter, 0);
memset(key->counter.receive.backtrack, 0,
sizeof(key->counter.receive.backtrack));
key->birthdate = ktime_get_boot_fast_ns();
key->birthdate = ktime_get_coarse_boottime_ns();
key->is_valid = true;
}

Expand Down Expand Up @@ -585,9 +585,9 @@ wg_noise_handshake_consume_initiation(struct message_handshake_initiation *src,
down_read(&handshake->lock);
replay_attack = memcmp(t, handshake->latest_timestamp,
NOISE_TIMESTAMP_LEN) <= 0;
flood_attack = handshake->last_initiation_consumption +
flood_attack = (s64)handshake->last_initiation_consumption +
NSEC_PER_SEC / INITIATIONS_PER_SECOND >
ktime_get_boot_fast_ns();
(s64)ktime_get_coarse_boottime_ns();
up_read(&handshake->lock);
if (replay_attack || flood_attack)
goto out;
Expand All @@ -599,7 +599,7 @@ wg_noise_handshake_consume_initiation(struct message_handshake_initiation *src,
memcpy(handshake->hash, hash, NOISE_HASH_LEN);
memcpy(handshake->chaining_key, chaining_key, NOISE_HASH_LEN);
handshake->remote_index = src->sender_index;
handshake->last_initiation_consumption = ktime_get_boot_fast_ns();
handshake->last_initiation_consumption = ktime_get_coarse_boottime_ns();
handshake->state = HANDSHAKE_CONSUMED_INITIATION;
up_write(&handshake->lock);
ret_peer = peer;
Expand Down
1 change: 0 additions & 1 deletion src/noise.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <linux/atomic.h>
#include <linux/rwsem.h>
#include <linux/mutex.h>
#include <linux/ktime.h>
#include <linux/kref.h>

union noise_counter {
Expand Down
2 changes: 1 addition & 1 deletion src/peer.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
kref_init(&peer->refcount);
skb_queue_head_init(&peer->staged_packet_queue);
atomic64_set(&peer->last_sent_handshake,
ktime_get_boot_fast_ns() -
ktime_get_coarse_boottime_ns() -
(u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC);
set_bit(NAPI_STATE_NO_BUSY_POLL, &peer->napi.state);
netif_napi_add(wg->dev, &peer->napi, wg_packet_rx_poll,
Expand Down
6 changes: 3 additions & 3 deletions src/ratelimiter.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static void entry_uninit(struct ratelimiter_entry *entry)
/* Calling this function with a NULL work uninits all entries. */
static void wg_ratelimiter_gc_entries(struct work_struct *work)
{
const u64 now = ktime_get_boot_fast_ns();
const u64 now = ktime_get_coarse_boottime_ns();
struct ratelimiter_entry *entry;
struct hlist_node *temp;
unsigned int i;
Expand Down Expand Up @@ -130,7 +130,7 @@ bool wg_ratelimiter_allow(struct sk_buff *skb, struct net *net)
* as part of the rate.
*/
spin_lock(&entry->lock);
now = ktime_get_boot_fast_ns();
now = ktime_get_coarse_boottime_ns();
tokens = min_t(u64, TOKEN_MAX,
entry->tokens + now -
entry->last_time_ns);
Expand All @@ -155,7 +155,7 @@ bool wg_ratelimiter_allow(struct sk_buff *skb, struct net *net)
entry->ip = ip;
INIT_HLIST_NODE(&entry->hash);
spin_lock_init(&entry->lock);
entry->last_time_ns = ktime_get_boot_fast_ns();
entry->last_time_ns = ktime_get_coarse_boottime_ns();
entry->tokens = TOKEN_MAX - PACKET_COST;
spin_lock(&table_lock);
hlist_add_head_rcu(&entry->hash, bucket);
Expand Down
2 changes: 1 addition & 1 deletion src/receive.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static void wg_receive_handshake_packet(struct wg_device *wg,
under_load = skb_queue_len(&wg->incoming_handshakes) >=
MAX_QUEUED_INCOMING_HANDSHAKES / 8;
if (under_load)
last_under_load = ktime_get_boot_fast_ns();
last_under_load = ktime_get_coarse_boottime_ns();
else if (last_under_load)
under_load = !wg_birthdate_has_expired(last_under_load, 1);
mac_state = wg_cookie_validate_packet(&wg->cookie_checker, skb,
Expand Down
8 changes: 4 additions & 4 deletions src/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static void wg_packet_send_handshake_initiation(struct wg_peer *peer)
REKEY_TIMEOUT))
return; /* This function is rate limited. */

atomic64_set(&peer->last_sent_handshake, ktime_get_boot_fast_ns());
atomic64_set(&peer->last_sent_handshake, ktime_get_coarse_boottime_ns());
net_dbg_ratelimited("%s: Sending handshake initiation to peer %llu (%pISpfsc)\n",
peer->device->dev->name, peer->internal_id,
&peer->endpoint.addr);
Expand All @@ -37,7 +37,7 @@ static void wg_packet_send_handshake_initiation(struct wg_peer *peer)
wg_timers_any_authenticated_packet_traversal(peer);
wg_timers_any_authenticated_packet_sent(peer);
atomic64_set(&peer->last_sent_handshake,
ktime_get_boot_fast_ns());
ktime_get_coarse_boottime_ns());
wg_socket_send_buffer_to_peer(peer, &packet, sizeof(packet),
HANDSHAKE_DSCP);
wg_timers_handshake_initiated(peer);
Expand Down Expand Up @@ -87,7 +87,7 @@ void wg_packet_send_handshake_response(struct wg_peer *peer)
{
struct message_handshake_response packet;

atomic64_set(&peer->last_sent_handshake, ktime_get_boot_fast_ns());
atomic64_set(&peer->last_sent_handshake, ktime_get_coarse_boottime_ns());
net_dbg_ratelimited("%s: Sending handshake response to peer %llu (%pISpfsc)\n",
peer->device->dev->name, peer->internal_id,
&peer->endpoint.addr);
Expand All @@ -100,7 +100,7 @@ void wg_packet_send_handshake_response(struct wg_peer *peer)
wg_timers_any_authenticated_packet_traversal(peer);
wg_timers_any_authenticated_packet_sent(peer);
atomic64_set(&peer->last_sent_handshake,
ktime_get_boot_fast_ns());
ktime_get_coarse_boottime_ns());
wg_socket_send_buffer_to_peer(peer, &packet,
sizeof(packet),
HANDSHAKE_DSCP);
Expand Down
2 changes: 1 addition & 1 deletion src/timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static inline bool wg_birthdate_has_expired(u64 birthday_nanoseconds,
u64 expiration_seconds)
{
return (s64)(birthday_nanoseconds + expiration_seconds * NSEC_PER_SEC)
<= (s64)ktime_get_boot_fast_ns();
<= (s64)ktime_get_coarse_boottime_ns();
}

#endif /* _WG_TIMERS_H */

0 comments on commit 0d9758d

Please sign in to comment.