^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define pr_fmt(fmt) "kcsan: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/random.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "encoding.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define ITERS_PER_TEST 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* Test requirements. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static bool test_requires(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* random should be initialized for the below tests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) return prandom_u32() + prandom_u32() != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Test watchpoint encode and decode: check that encoding some access's info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * and then subsequent decode preserves the access's info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static bool test_encode_decode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) for (i = 0; i < ITERS_PER_TEST; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) size_t size = prandom_u32_max(MAX_ENCODABLE_SIZE) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) bool is_write = !!prandom_u32_max(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) prandom_bytes(&addr, sizeof(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (WARN_ON(!check_encodable(addr, size)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Encode and decode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const long encoded_watchpoint =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) encode_watchpoint(addr, size, is_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned long verif_masked_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) size_t verif_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) bool verif_is_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Check special watchpoints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (WARN_ON(decode_watchpoint(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) INVALID_WATCHPOINT, &verif_masked_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) &verif_size, &verif_is_write)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (WARN_ON(decode_watchpoint(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) CONSUMED_WATCHPOINT, &verif_masked_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) &verif_size, &verif_is_write)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Check decoding watchpoint returns same data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (WARN_ON(!decode_watchpoint(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) encoded_watchpoint, &verif_masked_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) &verif_size, &verif_is_write)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (WARN_ON(verif_masked_addr !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) (addr & WATCHPOINT_ADDR_MASK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (WARN_ON(verif_size != size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (WARN_ON(is_write != verif_is_write))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) pr_err("%s fail: %s %zu bytes @ %lx -> encoded: %lx -> %s %zu bytes @ %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) __func__, is_write ? "write" : "read", size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) addr, encoded_watchpoint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) verif_is_write ? "write" : "read", verif_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) verif_masked_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* Test access matching function. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static bool test_matching_access(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (WARN_ON(!matching_access(10, 1, 10, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (WARN_ON(!matching_access(10, 2, 11, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (WARN_ON(!matching_access(10, 1, 9, 2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (WARN_ON(matching_access(10, 1, 11, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (WARN_ON(matching_access(9, 1, 10, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * An access of size 0 could match another access, as demonstrated here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Rather than add more comparisons to 'matching_access()', which would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * end up in the fast-path for *all* checks, check_access() simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * returns for all accesses of size 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (WARN_ON(!matching_access(8, 8, 12, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int __init kcsan_selftest(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int passed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define RUN_TEST(do_test) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ++total; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (do_test()) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ++passed; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) pr_err("selftest: " #do_test " failed"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) RUN_TEST(test_requires);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) RUN_TEST(test_encode_decode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) RUN_TEST(test_matching_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) pr_info("selftest: %d/%d tests passed\n", passed, total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (passed != total)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) panic("selftests failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) postcore_initcall(kcsan_selftest);