Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
0004  */
0005 
0006 #ifdef DEBUG
0007 
0008 #include <linux/jiffies.h>
0009 
0010 static const struct {
0011     bool result;
0012     unsigned int msec_to_sleep_before;
0013 } expected_results[] __initconst = {
0014     [0 ... PACKETS_BURSTABLE - 1] = { true, 0 },
0015     [PACKETS_BURSTABLE] = { false, 0 },
0016     [PACKETS_BURSTABLE + 1] = { true, MSEC_PER_SEC / PACKETS_PER_SECOND },
0017     [PACKETS_BURSTABLE + 2] = { false, 0 },
0018     [PACKETS_BURSTABLE + 3] = { true, (MSEC_PER_SEC / PACKETS_PER_SECOND) * 2 },
0019     [PACKETS_BURSTABLE + 4] = { true, 0 },
0020     [PACKETS_BURSTABLE + 5] = { false, 0 }
0021 };
0022 
0023 static __init unsigned int maximum_jiffies_at_index(int index)
0024 {
0025     unsigned int total_msecs = 2 * MSEC_PER_SEC / PACKETS_PER_SECOND / 3;
0026     int i;
0027 
0028     for (i = 0; i <= index; ++i)
0029         total_msecs += expected_results[i].msec_to_sleep_before;
0030     return msecs_to_jiffies(total_msecs);
0031 }
0032 
0033 static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4,
0034                    struct sk_buff *skb6, struct ipv6hdr *hdr6,
0035                    int *test)
0036 {
0037     unsigned long loop_start_time;
0038     int i;
0039 
0040     wg_ratelimiter_gc_entries(NULL);
0041     rcu_barrier();
0042     loop_start_time = jiffies;
0043 
0044     for (i = 0; i < ARRAY_SIZE(expected_results); ++i) {
0045         if (expected_results[i].msec_to_sleep_before)
0046             msleep(expected_results[i].msec_to_sleep_before);
0047 
0048         if (time_is_before_jiffies(loop_start_time +
0049                        maximum_jiffies_at_index(i)))
0050             return -ETIMEDOUT;
0051         if (wg_ratelimiter_allow(skb4, &init_net) !=
0052                     expected_results[i].result)
0053             return -EXFULL;
0054         ++(*test);
0055 
0056         hdr4->saddr = htonl(ntohl(hdr4->saddr) + i + 1);
0057         if (time_is_before_jiffies(loop_start_time +
0058                        maximum_jiffies_at_index(i)))
0059             return -ETIMEDOUT;
0060         if (!wg_ratelimiter_allow(skb4, &init_net))
0061             return -EXFULL;
0062         ++(*test);
0063 
0064         hdr4->saddr = htonl(ntohl(hdr4->saddr) - i - 1);
0065 
0066 #if IS_ENABLED(CONFIG_IPV6)
0067         hdr6->saddr.in6_u.u6_addr32[2] = htonl(i);
0068         hdr6->saddr.in6_u.u6_addr32[3] = htonl(i);
0069         if (time_is_before_jiffies(loop_start_time +
0070                        maximum_jiffies_at_index(i)))
0071             return -ETIMEDOUT;
0072         if (wg_ratelimiter_allow(skb6, &init_net) !=
0073                     expected_results[i].result)
0074             return -EXFULL;
0075         ++(*test);
0076 
0077         hdr6->saddr.in6_u.u6_addr32[0] =
0078             htonl(ntohl(hdr6->saddr.in6_u.u6_addr32[0]) + i + 1);
0079         if (time_is_before_jiffies(loop_start_time +
0080                        maximum_jiffies_at_index(i)))
0081             return -ETIMEDOUT;
0082         if (!wg_ratelimiter_allow(skb6, &init_net))
0083             return -EXFULL;
0084         ++(*test);
0085 
0086         hdr6->saddr.in6_u.u6_addr32[0] =
0087             htonl(ntohl(hdr6->saddr.in6_u.u6_addr32[0]) - i - 1);
0088 
0089         if (time_is_before_jiffies(loop_start_time +
0090                        maximum_jiffies_at_index(i)))
0091             return -ETIMEDOUT;
0092 #endif
0093     }
0094     return 0;
0095 }
0096 
0097 static __init int capacity_test(struct sk_buff *skb4, struct iphdr *hdr4,
0098                 int *test)
0099 {
0100     int i;
0101 
0102     wg_ratelimiter_gc_entries(NULL);
0103     rcu_barrier();
0104 
0105     if (atomic_read(&total_entries))
0106         return -EXFULL;
0107     ++(*test);
0108 
0109     for (i = 0; i <= max_entries; ++i) {
0110         hdr4->saddr = htonl(i);
0111         if (wg_ratelimiter_allow(skb4, &init_net) != (i != max_entries))
0112             return -EXFULL;
0113         ++(*test);
0114     }
0115     return 0;
0116 }
0117 
0118 bool __init wg_ratelimiter_selftest(void)
0119 {
0120     enum { TRIALS_BEFORE_GIVING_UP = 5000 };
0121     bool success = false;
0122     int test = 0, trials;
0123     struct sk_buff *skb4, *skb6 = NULL;
0124     struct iphdr *hdr4;
0125     struct ipv6hdr *hdr6 = NULL;
0126 
0127     if (IS_ENABLED(CONFIG_KASAN) || IS_ENABLED(CONFIG_UBSAN))
0128         return true;
0129 
0130     BUILD_BUG_ON(MSEC_PER_SEC % PACKETS_PER_SECOND != 0);
0131 
0132     if (wg_ratelimiter_init())
0133         goto out;
0134     ++test;
0135     if (wg_ratelimiter_init()) {
0136         wg_ratelimiter_uninit();
0137         goto out;
0138     }
0139     ++test;
0140     if (wg_ratelimiter_init()) {
0141         wg_ratelimiter_uninit();
0142         wg_ratelimiter_uninit();
0143         goto out;
0144     }
0145     ++test;
0146 
0147     skb4 = alloc_skb(sizeof(struct iphdr), GFP_KERNEL);
0148     if (unlikely(!skb4))
0149         goto err_nofree;
0150     skb4->protocol = htons(ETH_P_IP);
0151     hdr4 = (struct iphdr *)skb_put(skb4, sizeof(*hdr4));
0152     hdr4->saddr = htonl(8182);
0153     skb_reset_network_header(skb4);
0154     ++test;
0155 
0156 #if IS_ENABLED(CONFIG_IPV6)
0157     skb6 = alloc_skb(sizeof(struct ipv6hdr), GFP_KERNEL);
0158     if (unlikely(!skb6)) {
0159         kfree_skb(skb4);
0160         goto err_nofree;
0161     }
0162     skb6->protocol = htons(ETH_P_IPV6);
0163     hdr6 = (struct ipv6hdr *)skb_put(skb6, sizeof(*hdr6));
0164     hdr6->saddr.in6_u.u6_addr32[0] = htonl(1212);
0165     hdr6->saddr.in6_u.u6_addr32[1] = htonl(289188);
0166     skb_reset_network_header(skb6);
0167     ++test;
0168 #endif
0169 
0170     for (trials = TRIALS_BEFORE_GIVING_UP; IS_ENABLED(DEBUG_RATELIMITER_TIMINGS);) {
0171         int test_count = 0, ret;
0172 
0173         ret = timings_test(skb4, hdr4, skb6, hdr6, &test_count);
0174         if (ret == -ETIMEDOUT) {
0175             if (!trials--) {
0176                 test += test_count;
0177                 goto err;
0178             }
0179             continue;
0180         } else if (ret < 0) {
0181             test += test_count;
0182             goto err;
0183         } else {
0184             test += test_count;
0185             break;
0186         }
0187     }
0188 
0189     for (trials = TRIALS_BEFORE_GIVING_UP;;) {
0190         int test_count = 0;
0191 
0192         if (capacity_test(skb4, hdr4, &test_count) < 0) {
0193             if (!trials--) {
0194                 test += test_count;
0195                 goto err;
0196             }
0197             continue;
0198         }
0199         test += test_count;
0200         break;
0201     }
0202 
0203     success = true;
0204 
0205 err:
0206     kfree_skb(skb4);
0207 #if IS_ENABLED(CONFIG_IPV6)
0208     kfree_skb(skb6);
0209 #endif
0210 err_nofree:
0211     wg_ratelimiter_uninit();
0212     wg_ratelimiter_uninit();
0213     wg_ratelimiter_uninit();
0214     /* Uninit one extra time to check underflow detection. */
0215     wg_ratelimiter_uninit();
0216 out:
0217     if (success)
0218         pr_info("ratelimiter self-tests: pass\n");
0219     else
0220         pr_err("ratelimiter self-test %d: FAIL\n", test);
0221 
0222     return success;
0223 }
0224 #endif