From 68441fb05412baebbd17f407bf984ad7a81af630 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 23 Jun 2018 19:02:18 +0200 Subject: global: use fast boottime instead of normal boottime Generally if we're inaccurate by a few nanoseconds, it doesn't matter. --- src/compat/compat.h | 6 +++--- src/cookie.c | 6 +++--- src/cookie.h | 4 ++-- src/device.c | 2 +- src/noise.c | 6 +++--- src/noise.h | 4 ++-- src/peer.c | 2 +- src/peer.h | 2 +- src/ratelimiter.c | 6 +++--- src/receive.c | 6 +++--- src/send.c | 4 ++-- src/timers.h | 4 ++-- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/compat/compat.h b/src/compat/compat.h index d0efdb9..d08557f 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -334,11 +334,11 @@ static inline u64 ktime_get_boot_ns(void) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) && !defined(ISRHEL7) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) #include -static inline bool ktime_after(const ktime_t cmp1, const ktime_t cmp2) +static inline u64 ktime_get_boot_fast_ns(void) { - return ktime_compare(cmp1, cmp2) > 0; + return ktime_get_boot_ns(); } #endif diff --git a/src/cookie.c b/src/cookie.c index b7054fa..7981227 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -18,7 +18,7 @@ void cookie_checker_init(struct cookie_checker *checker, struct wireguard_device *wg) { init_rwsem(&checker->secret_lock); - checker->secret_birthdate = ktime_get_boottime(); + checker->secret_birthdate = ktime_get_boot_fast_ns(); get_random_bytes(checker->secret, NOISE_HASH_LEN); checker->device = wg; } @@ -79,7 +79,7 @@ static void make_cookie(u8 cookie[COOKIE_LEN], struct sk_buff *skb, struct cooki if (has_expired(checker->secret_birthdate, COOKIE_SECRET_MAX_AGE)) { down_write(&checker->secret_lock); - checker->secret_birthdate = ktime_get_boottime(); + checker->secret_birthdate = ktime_get_boot_fast_ns(); get_random_bytes(checker->secret, NOISE_HASH_LEN); up_write(&checker->secret_lock); } @@ -182,7 +182,7 @@ void cookie_message_consume(struct message_handshake_cookie *src, struct wiregua if (ret) { down_write(&entry->peer->latest_cookie.lock); memcpy(entry->peer->latest_cookie.cookie, cookie, COOKIE_LEN); - entry->peer->latest_cookie.birthdate = ktime_get_boottime(); + entry->peer->latest_cookie.birthdate = ktime_get_boot_fast_ns(); entry->peer->latest_cookie.is_valid = true; entry->peer->latest_cookie.have_sent_mac1 = false; up_write(&entry->peer->latest_cookie.lock); diff --git a/src/cookie.h b/src/cookie.h index e83c256..9f519ef 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -15,13 +15,13 @@ struct cookie_checker { u8 secret[NOISE_HASH_LEN]; u8 cookie_encryption_key[NOISE_SYMMETRIC_KEY_LEN]; u8 message_mac1_key[NOISE_SYMMETRIC_KEY_LEN]; - ktime_t secret_birthdate; + u64 secret_birthdate; struct rw_semaphore secret_lock; struct wireguard_device *device; }; struct cookie { - ktime_t birthdate; + u64 birthdate; bool is_valid; u8 cookie[COOKIE_LEN]; bool have_sent_mac1; diff --git a/src/device.c b/src/device.c index 7d5df17..df9189b 100644 --- a/src/device.c +++ b/src/device.c @@ -105,7 +105,7 @@ static int stop(struct net_device *dev) timers_stop(peer); noise_handshake_clear(&peer->handshake); noise_keypairs_clear(&peer->keypairs); - peer->last_sent_handshake = ktime_sub_ns(ktime_get_boottime(), (u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC); + peer->last_sent_handshake = ktime_get_boot_fast_ns() - (u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC; } mutex_unlock(&wg->device_update_lock); skb_queue_purge(&wg->incoming_handshakes); diff --git a/src/noise.c b/src/noise.c index 7b3c4d6..84bde39 100644 --- a/src/noise.c +++ b/src/noise.c @@ -284,7 +284,7 @@ static void symmetric_key_init(struct noise_symmetric_key *key) spin_lock_init(&key->counter.receive.lock); atomic64_set(&key->counter.counter, 0); memset(key->counter.receive.backtrack, 0, sizeof(key->counter.receive.backtrack)); - key->birthdate = ktime_get_boottime(); + key->birthdate = ktime_get_boot_fast_ns(); key->is_valid = true; } @@ -461,7 +461,7 @@ struct wireguard_peer *noise_handshake_consume_initiation(struct message_handsha down_read(&handshake->lock); replay_attack = memcmp(t, handshake->latest_timestamp, NOISE_TIMESTAMP_LEN) <= 0; - flood_attack = ktime_after(ktime_add_ns(handshake->last_initiation_consumption, NSEC_PER_SEC / INITIATIONS_PER_SECOND), ktime_get_boottime()); + flood_attack = handshake->last_initiation_consumption + NSEC_PER_SEC / INITIATIONS_PER_SECOND > ktime_get_boot_fast_ns(); up_read(&handshake->lock); if (replay_attack || flood_attack) { peer_put(wg_peer); @@ -476,7 +476,7 @@ struct wireguard_peer *noise_handshake_consume_initiation(struct message_handsha 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_boottime(); + handshake->last_initiation_consumption = ktime_get_boot_fast_ns(); handshake->state = HANDSHAKE_CONSUMED_INITIATION; up_write(&handshake->lock); diff --git a/src/noise.h b/src/noise.h index ec1a59d..b8d18b9 100644 --- a/src/noise.h +++ b/src/noise.h @@ -31,7 +31,7 @@ union noise_counter { struct noise_symmetric_key { u8 key[NOISE_SYMMETRIC_KEY_LEN]; union noise_counter counter; - ktime_t birthdate; + u64 birthdate; bool is_valid; }; @@ -72,7 +72,7 @@ struct noise_handshake { struct index_hashtable_entry entry; enum noise_handshake_state state; - ktime_t last_initiation_consumption; + u64 last_initiation_consumption; struct noise_static_identity *static_identity; diff --git a/src/peer.c b/src/peer.c index ece5e7d..9669158 100644 --- a/src/peer.c +++ b/src/peer.c @@ -55,7 +55,7 @@ struct wireguard_peer *peer_create(struct wireguard_device *wg, const u8 public_ skb_queue_head_init(&peer->staged_packet_queue); list_add_tail(&peer->peer_list, &wg->peer_list); pubkey_hashtable_add(&wg->peer_hashtable, peer); - peer->last_sent_handshake = ktime_sub_ns(ktime_get_boottime(), (u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC); + peer->last_sent_handshake = ktime_get_boot_fast_ns() - (u64)(REKEY_TIMEOUT + 1) * NSEC_PER_SEC; pr_debug("%s: Peer %llu created\n", wg->dev->name, peer->internal_id); return peer; } diff --git a/src/peer.h b/src/peer.h index cb2dc42..867b9c3 100644 --- a/src/peer.h +++ b/src/peer.h @@ -43,7 +43,7 @@ struct wireguard_peer { struct dst_cache endpoint_cache; rwlock_t endpoint_lock; struct noise_handshake handshake; - ktime_t last_sent_handshake; + u64 last_sent_handshake; struct work_struct transmit_handshake_work, clear_peer_work; struct cookie latest_cookie; struct hlist_node pubkey_hash; diff --git a/src/ratelimiter.c b/src/ratelimiter.c index e35bf64..140d99e 100644 --- a/src/ratelimiter.c +++ b/src/ratelimiter.c @@ -57,7 +57,7 @@ static void gc_entries(struct work_struct *work) unsigned int i; struct ratelimiter_entry *entry; struct hlist_node *temp; - const u64 now = ktime_get_boot_ns(); + const u64 now = ktime_get_boot_fast_ns(); for (i = 0; i < table_size; ++i) { spin_lock(&table_lock); @@ -107,7 +107,7 @@ bool ratelimiter_allow(struct sk_buff *skb, struct net *net) * tokens, rather than as part of the rate. */ spin_lock(&entry->lock); - now = ktime_get_boot_ns(); + now = ktime_get_boot_fast_ns(); tokens = min_t(u64, TOKEN_MAX, entry->tokens + now - entry->last_time_ns); entry->last_time_ns = now; ret = tokens >= PACKET_COST; @@ -130,7 +130,7 @@ bool ratelimiter_allow(struct sk_buff *skb, struct net *net) entry->ip = data.ip; INIT_HLIST_NODE(&entry->hash); spin_lock_init(&entry->lock); - entry->last_time_ns = ktime_get_boot_ns(); + entry->last_time_ns = ktime_get_boot_fast_ns(); entry->tokens = TOKEN_MAX - PACKET_COST; spin_lock(&table_lock); hlist_add_head_rcu(&entry->hash, bucket); diff --git a/src/receive.c b/src/receive.c index 080e466..d150a0b 100644 --- a/src/receive.c +++ b/src/receive.c @@ -80,7 +80,7 @@ static inline int skb_prepare_header(struct sk_buff *skb, struct wireguard_devic static void receive_handshake_packet(struct wireguard_device *wg, struct sk_buff *skb) { - static ktime_t last_under_load; /* Yes this is global, so that our load calculation applies to the whole system. */ + static u64 last_under_load; /* Yes this is global, so that our load calculation applies to the whole system. */ struct wireguard_peer *peer = NULL; bool under_load; enum cookie_mac_state mac_state; @@ -94,8 +94,8 @@ static void receive_handshake_packet(struct wireguard_device *wg, struct sk_buff under_load = skb_queue_len(&wg->incoming_handshakes) >= MAX_QUEUED_INCOMING_HANDSHAKES / 8; if (under_load) - last_under_load = ktime_get_boottime(); - else if (ktime_to_ns(last_under_load)) + last_under_load = ktime_get_boot_fast_ns(); + else if (last_under_load) under_load = !has_expired(last_under_load, 1); mac_state = cookie_validate_packet(&wg->cookie_checker, skb, under_load); if ((under_load && mac_state == VALID_MAC_WITH_COOKIE) || (!under_load && mac_state == VALID_MAC_BUT_NO_COOKIE)) diff --git a/src/send.c b/src/send.c index f5ee629..7a8bea1 100644 --- a/src/send.c +++ b/src/send.c @@ -28,7 +28,7 @@ static void packet_send_handshake_initiation(struct wireguard_peer *peer) up_write(&peer->handshake.lock); return; /* This function is rate limited. */ } - peer->last_sent_handshake = ktime_get_boottime(); + peer->last_sent_handshake = ktime_get_boot_fast_ns(); up_write(&peer->handshake.lock); net_dbg_ratelimited("%s: Sending handshake initiation to peer %llu (%pISpfsc)\n", peer->device->dev->name, peer->internal_id, &peer->endpoint.addr); @@ -72,7 +72,7 @@ void packet_send_handshake_response(struct wireguard_peer *peer) struct message_handshake_response packet; net_dbg_ratelimited("%s: Sending handshake response to peer %llu (%pISpfsc)\n", peer->device->dev->name, peer->internal_id, &peer->endpoint.addr); - peer->last_sent_handshake = ktime_get_boottime(); + peer->last_sent_handshake = ktime_get_boot_fast_ns(); if (noise_handshake_create_response(&packet, &peer->handshake)) { cookie_add_mac_to_packet(&packet, sizeof(packet), peer); diff --git a/src/timers.h b/src/timers.h index 5a691c8..1c46555 100644 --- a/src/timers.h +++ b/src/timers.h @@ -19,9 +19,9 @@ void timers_handshake_complete(struct wireguard_peer *peer); void timers_session_derived(struct wireguard_peer *peer); void timers_any_authenticated_packet_traversal(struct wireguard_peer *peer); -static inline bool has_expired(ktime_t birthday, u64 expiration_seconds) +static inline bool has_expired(u64 birthday_nanoseconds, u64 expiration_seconds) { - return !ktime_after(ktime_add_ns(birthday, expiration_seconds * NSEC_PER_SEC), ktime_get_boottime()); + return (s64)(birthday_nanoseconds + expiration_seconds * NSEC_PER_SEC) <= (s64)ktime_get_boot_fast_ns(); } #endif /* _WG_TIMERS_H */ -- cgit v1.2.3-59-g8ed1b