summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-06-12 15:05:50 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-06-25 16:42:42 +0200
commit21c6bb547d0d46a6ce36b7e1026b62548c6acfc1 (patch)
treebce4d65b9f48ec337f92172572767c25f43a3416 /src
parentcompat: unify custom function prefix/suffix (diff)
downloadwireguard-monolithic-historical-21c6bb547d0d46a6ce36b7e1026b62548c6acfc1.tar.xz
wireguard-monolithic-historical-21c6bb547d0d46a6ce36b7e1026b62548c6acfc1.zip
global: switch to coarse ktime
Coarse ktime is broken until [1] in 5.2 and kernels without the backport, so we use fallback code there. The fallback code has also been improved significantly. It now only uses slower clocks on kernels < 3.17, at the expense of some accuracy we're not overly concerned about. [1] https://lore.kernel.org/lkml/tip-e3ff9c3678b4d80e22d2557b68726174578eaf52@git.kernel.org/ Suggested-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'src')
-rw-r--r--src/compat/compat.h40
-rw-r--r--src/cookie.c6
-rw-r--r--src/device.c2
-rw-r--r--src/noise.c8
-rw-r--r--src/noise.h1
-rw-r--r--src/peer.c2
-rw-r--r--src/ratelimiter.c6
-rw-r--r--src/receive.c2
-rw-r--r--src/send.c8
-rw-r--r--src/tests/qemu/Makefile2
-rw-r--r--src/timers.h2
11 files changed, 43 insertions, 36 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h
index acf18e7..19f51a9 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -388,25 +388,38 @@ static inline int get_random_bytes_wait(void *buf, int nbytes)
#define system_power_efficient_wq system_unbound_wq
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) && !defined(ISRHEL7)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0)
+#include <linux/ktime.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
#include <linux/hrtimer.h>
-static inline u64 ktime_get_boot_ns(void)
+#ifndef ktime_get_real_ts64
+#define timespec64 timespec
+#define ktime_get_real_ts64 ktime_get_real_ts
+#endif
+#else
+#include <linux/timekeeping.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
+static inline u64 __compat_jiffies64_to_nsecs(u64 j)
{
- return ktime_to_ns(ktime_get_boottime());
+#if !(NSEC_PER_SEC % HZ)
+ return (NSEC_PER_SEC / HZ) * j;
+# else
+ return div_u64(j * HZ_TO_USEC_NUM, HZ_TO_USEC_DEN) * 1000;
+#endif
}
+#define jiffies64_to_nsecs __compat_jiffies64_to_nsecs
#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
+static inline u64 ktime_get_coarse_boottime_ns(void)
+{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
-#include <linux/hrtimer.h>
+ return ktime_to_ns(ktime_get_boottime());
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 12) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) || LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 53)
+ return ktime_to_ns(ktime_mono_to_any(ns_to_ktime(jiffies64_to_nsecs(get_jiffies_64())), TK_OFFS_BOOT));
#else
-#include <linux/timekeeping.h>
+ return ktime_to_ns(ktime_get_coarse_boottime());
#endif
-static inline u64 __compat_ktime_get_boot_fast_ns(void)
-{
- return ktime_get_boot_ns();
}
-#define ktime_get_boot_fast_ns __compat_ktime_get_boot_fast_ns
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
@@ -646,11 +659,6 @@ struct __compat_dummy_container { char dev; };
#define COMPAT_CANNOT_USE_AVX512
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
-#define timespec64 timespec
-#define ktime_get_real_ts64 ktime_get_real_ts
-#endif
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
#include <net/genetlink.h>
#define genl_dump_check_consistent(a, b) genl_dump_check_consistent(a, b, &genl_family)
diff --git a/src/cookie.c b/src/cookie.c
index a2ddbcd..8b7d1fe 100644
--- a/src/cookie.c
+++ b/src/cookie.c
@@ -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;
}
@@ -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);
}
@@ -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);
diff --git a/src/device.c b/src/device.c
index 8735935..d17dbf7 100644
--- a/src/device.c
+++ b/src/device.c
@@ -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);
diff --git a/src/noise.c b/src/noise.c
index 5b073bd..a8f86df 100644
--- a/src/noise.c
+++ b/src/noise.c
@@ -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;
}
@@ -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;
@@ -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;
diff --git a/src/noise.h b/src/noise.h
index 9c2cc62..2533237 100644
--- a/src/noise.h
+++ b/src/noise.h
@@ -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 {
diff --git a/src/peer.c b/src/peer.c
index 508f1d5..71325bb 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -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,
diff --git a/src/ratelimiter.c b/src/ratelimiter.c
index fd09190..e33ec72 100644
--- a/src/ratelimiter.c
+++ b/src/ratelimiter.c
@@ -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;
@@ -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);
@@ -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);
diff --git a/src/receive.c b/src/receive.c
index 51d06d3..6a3980b 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -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,
diff --git a/src/send.c b/src/send.c
index b0df5c7..62f1a97 100644
--- a/src/send.c
+++ b/src/send.c
@@ -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);
@@ -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);
@@ -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);
@@ -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);
diff --git a/src/tests/qemu/Makefile b/src/tests/qemu/Makefile
index acba80d..acae128 100644
--- a/src/tests/qemu/Makefile
+++ b/src/tests/qemu/Makefile
@@ -14,7 +14,7 @@ endif
ARCH := $(firstword $(subst -, ,$(CBUILD)))
# Set these from the environment to override
-KERNEL_VERSION ?= 5.1.3
+KERNEL_VERSION ?= 5.1.15
KERNEL_VERSION := $(KERNEL_VERSION)$(if $(DEBUG_KERNEL),$(if $(findstring -debug,$(KERNEL_VERSION)),,-debug),)
BUILD_PATH ?= $(PWD)/../../../qemu-build/$(ARCH)
DISTFILES_PATH ?= $(PWD)/distfiles
diff --git a/src/timers.h b/src/timers.h
index f9d11fe..f0653dc 100644
--- a/src/timers.h
+++ b/src/timers.h
@@ -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 */