1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4 */
5
6#ifdef DEBUG
7
8#include <linux/jiffies.h>
9
10static const struct {
11	bool result;
12	unsigned int msec_to_sleep_before;
13} expected_results[] __initconst = {
14	[0 ... PACKETS_BURSTABLE - 1] = { true, 0 },
15	[PACKETS_BURSTABLE] = { false, 0 },
16	[PACKETS_BURSTABLE + 1] = { true, MSEC_PER_SEC / PACKETS_PER_SECOND },
17	[PACKETS_BURSTABLE + 2] = { false, 0 },
18	[PACKETS_BURSTABLE + 3] = { true, (MSEC_PER_SEC / PACKETS_PER_SECOND) * 2 },
19	[PACKETS_BURSTABLE + 4] = { true, 0 },
20	[PACKETS_BURSTABLE + 5] = { false, 0 }
21};
22
23static __init unsigned int maximum_jiffies_at_index(int index)
24{
25	unsigned int total_msecs = 2 * MSEC_PER_SEC / PACKETS_PER_SECOND / 3;
26	int i;
27
28	for (i = 0; i <= index; ++i)
29		total_msecs += expected_results[i].msec_to_sleep_before;
30	return msecs_to_jiffies(total_msecs);
31}
32
33static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4,
34			       struct sk_buff *skb6, struct ipv6hdr *hdr6,
35			       int *test)
36{
37	unsigned long loop_start_time;
38	int i;
39
40	wg_ratelimiter_gc_entries(NULL);
41	rcu_barrier();
42	loop_start_time = jiffies;
43
44	for (i = 0; i < ARRAY_SIZE(expected_results); ++i) {
45		if (expected_results[i].msec_to_sleep_before)
46			msleep(expected_results[i].msec_to_sleep_before);
47
48		if (time_is_before_jiffies(loop_start_time +
49					   maximum_jiffies_at_index(i)))
50			return -ETIMEDOUT;
51		if (wg_ratelimiter_allow(skb4, &init_net) !=
52					expected_results[i].result)
53			return -EXFULL;
54		++(*test);
55
56		hdr4->saddr = htonl(ntohl(hdr4->saddr) + i + 1);
57		if (time_is_before_jiffies(loop_start_time +
58					   maximum_jiffies_at_index(i)))
59			return -ETIMEDOUT;
60		if (!wg_ratelimiter_allow(skb4, &init_net))
61			return -EXFULL;
62		++(*test);
63
64		hdr4->saddr = htonl(ntohl(hdr4->saddr) - i - 1);
65
66#if IS_ENABLED(CONFIG_IPV6)
67		hdr6->saddr.in6_u.u6_addr32[2] = htonl(i);
68		hdr6->saddr.in6_u.u6_addr32[3] = htonl(i);
69		if (time_is_before_jiffies(loop_start_time +
70					   maximum_jiffies_at_index(i)))
71			return -ETIMEDOUT;
72		if (wg_ratelimiter_allow(skb6, &init_net) !=
73					expected_results[i].result)
74			return -EXFULL;
75		++(*test);
76
77		hdr6->saddr.in6_u.u6_addr32[0] =
78			htonl(ntohl(hdr6->saddr.in6_u.u6_addr32[0]) + i + 1);
79		if (time_is_before_jiffies(loop_start_time +
80					   maximum_jiffies_at_index(i)))
81			return -ETIMEDOUT;
82		if (!wg_ratelimiter_allow(skb6, &init_net))
83			return -EXFULL;
84		++(*test);
85
86		hdr6->saddr.in6_u.u6_addr32[0] =
87			htonl(ntohl(hdr6->saddr.in6_u.u6_addr32[0]) - i - 1);
88
89		if (time_is_before_jiffies(loop_start_time +
90					   maximum_jiffies_at_index(i)))
91			return -ETIMEDOUT;
92#endif
93	}
94	return 0;
95}
96
97static __init int capacity_test(struct sk_buff *skb4, struct iphdr *hdr4,
98				int *test)
99{
100	int i;
101
102	wg_ratelimiter_gc_entries(NULL);
103	rcu_barrier();
104
105	if (atomic_read(&total_entries))
106		return -EXFULL;
107	++(*test);
108
109	for (i = 0; i <= max_entries; ++i) {
110		hdr4->saddr = htonl(i);
111		if (wg_ratelimiter_allow(skb4, &init_net) != (i != max_entries))
112			return -EXFULL;
113		++(*test);
114	}
115	return 0;
116}
117
118bool __init wg_ratelimiter_selftest(void)
119{
120	enum { TRIALS_BEFORE_GIVING_UP = 5000 };
121	bool success = false;
122	int test = 0, trials;
123	struct sk_buff *skb4, *skb6 = NULL;
124	struct iphdr *hdr4;
125	struct ipv6hdr *hdr6 = NULL;
126
127	if (IS_ENABLED(CONFIG_KASAN) || IS_ENABLED(CONFIG_UBSAN))
128		return true;
129
130	BUILD_BUG_ON(MSEC_PER_SEC % PACKETS_PER_SECOND != 0);
131
132	if (wg_ratelimiter_init())
133		goto out;
134	++test;
135	if (wg_ratelimiter_init()) {
136		wg_ratelimiter_uninit();
137		goto out;
138	}
139	++test;
140	if (wg_ratelimiter_init()) {
141		wg_ratelimiter_uninit();
142		wg_ratelimiter_uninit();
143		goto out;
144	}
145	++test;
146
147	skb4 = alloc_skb(sizeof(struct iphdr), GFP_KERNEL);
148	if (unlikely(!skb4))
149		goto err_nofree;
150	skb4->protocol = htons(ETH_P_IP);
151	hdr4 = (struct iphdr *)skb_put(skb4, sizeof(*hdr4));
152	hdr4->saddr = htonl(8182);
153	skb_reset_network_header(skb4);
154	++test;
155
156#if IS_ENABLED(CONFIG_IPV6)
157	skb6 = alloc_skb(sizeof(struct ipv6hdr), GFP_KERNEL);
158	if (unlikely(!skb6)) {
159		kfree_skb(skb4);
160		goto err_nofree;
161	}
162	skb6->protocol = htons(ETH_P_IPV6);
163	hdr6 = (struct ipv6hdr *)skb_put(skb6, sizeof(*hdr6));
164	hdr6->saddr.in6_u.u6_addr32[0] = htonl(1212);
165	hdr6->saddr.in6_u.u6_addr32[1] = htonl(289188);
166	skb_reset_network_header(skb6);
167	++test;
168#endif
169
170	for (trials = TRIALS_BEFORE_GIVING_UP; IS_ENABLED(DEBUG_RATELIMITER_TIMINGS);) {
171		int test_count = 0, ret;
172
173		ret = timings_test(skb4, hdr4, skb6, hdr6, &test_count);
174		if (ret == -ETIMEDOUT) {
175			if (!trials--) {
176				test += test_count;
177				goto err;
178			}
179			continue;
180		} else if (ret < 0) {
181			test += test_count;
182			goto err;
183		} else {
184			test += test_count;
185			break;
186		}
187	}
188
189	for (trials = TRIALS_BEFORE_GIVING_UP;;) {
190		int test_count = 0;
191
192		if (capacity_test(skb4, hdr4, &test_count) < 0) {
193			if (!trials--) {
194				test += test_count;
195				goto err;
196			}
197			continue;
198		}
199		test += test_count;
200		break;
201	}
202
203	success = true;
204
205err:
206	kfree_skb(skb4);
207#if IS_ENABLED(CONFIG_IPV6)
208	kfree_skb(skb6);
209#endif
210err_nofree:
211	wg_ratelimiter_uninit();
212	wg_ratelimiter_uninit();
213	wg_ratelimiter_uninit();
214	/* Uninit one extra time to check underflow detection. */
215	wg_ratelimiter_uninit();
216out:
217	if (success)
218		pr_info("ratelimiter self-tests: pass\n");
219	else
220		pr_err("ratelimiter self-test %d: FAIL\n", test);
221
222	return success;
223}
224#endif
225