|
1 | | -// SPDX-License-Identifier: GPL-2.0 |
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
2 | 2 | /* |
3 | | - * Test cases for compiler-based stack variable zeroing via future |
4 | | - * compiler flags or CONFIG_GCC_PLUGIN_STRUCTLEAK*. |
| 3 | + * Test cases for compiler-based stack variable zeroing via |
| 4 | + * -ftrivial-auto-var-init={zero,pattern} or CONFIG_GCC_PLUGIN_STRUCTLEAK*. |
| 5 | + * |
| 6 | + * External build example: |
| 7 | + * clang -O2 -Wall -ftrivial-auto-var-init=pattern \ |
| 8 | + * -o test_stackinit test_stackinit.c |
5 | 9 | */ |
| 10 | +#ifdef __KERNEL__ |
6 | 11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
7 | 12 |
|
8 | 13 | #include <linux/init.h> |
9 | 14 | #include <linux/kernel.h> |
10 | 15 | #include <linux/module.h> |
11 | 16 | #include <linux/string.h> |
12 | 17 |
|
| 18 | +#else |
| 19 | + |
| 20 | +/* Userspace headers. */ |
| 21 | +#include <stdio.h> |
| 22 | +#include <stdint.h> |
| 23 | +#include <string.h> |
| 24 | +#include <stdbool.h> |
| 25 | +#include <errno.h> |
| 26 | +#include <sys/types.h> |
| 27 | + |
| 28 | +/* Linux kernel-ism stubs for stand-alone userspace build. */ |
| 29 | +#define KBUILD_MODNAME "stackinit" |
| 30 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 31 | +#define pr_err(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__) |
| 32 | +#define pr_warn(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__) |
| 33 | +#define pr_info(fmt, ...) fprintf(stdout, pr_fmt(fmt), ##__VA_ARGS__) |
| 34 | +#define __init /**/ |
| 35 | +#define __exit /**/ |
| 36 | +#define __user /**/ |
| 37 | +#define noinline __attribute__((__noinline__)) |
| 38 | +#define __aligned(x) __attribute__((__aligned__(x))) |
| 39 | +#ifdef __clang__ |
| 40 | +# define __compiletime_error(message) /**/ |
| 41 | +#else |
| 42 | +# define __compiletime_error(message) __attribute__((__error__(message))) |
| 43 | +#endif |
| 44 | +#define __compiletime_assert(condition, msg, prefix, suffix) \ |
| 45 | + do { \ |
| 46 | + extern void prefix ## suffix(void) __compiletime_error(msg); \ |
| 47 | + if (!(condition)) \ |
| 48 | + prefix ## suffix(); \ |
| 49 | + } while (0) |
| 50 | +#define _compiletime_assert(condition, msg, prefix, suffix) \ |
| 51 | + __compiletime_assert(condition, msg, prefix, suffix) |
| 52 | +#define compiletime_assert(condition, msg) \ |
| 53 | + _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) |
| 54 | +#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) |
| 55 | +#define BUILD_BUG_ON(condition) \ |
| 56 | + BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) |
| 57 | +typedef uint8_t u8; |
| 58 | +typedef uint16_t u16; |
| 59 | +typedef uint32_t u32; |
| 60 | +typedef uint64_t u64; |
| 61 | + |
| 62 | +#define module_init(func) static int (*do_init)(void) = func |
| 63 | +#define module_exit(func) static void (*do_exit)(void) = func |
| 64 | +#define MODULE_LICENSE(str) int main(void) { \ |
| 65 | + int rc; \ |
| 66 | + /* License: str */ \ |
| 67 | + rc = do_init(); \ |
| 68 | + if (rc == 0) \ |
| 69 | + do_exit(); \ |
| 70 | + return rc; \ |
| 71 | + } |
| 72 | + |
| 73 | +#endif /* __KERNEL__ */ |
| 74 | + |
13 | 75 | /* Exfiltration buffer. */ |
14 | 76 | #define MAX_VAR_SIZE 128 |
15 | 77 | static u8 check_buf[MAX_VAR_SIZE]; |
@@ -279,6 +341,10 @@ DEFINE_TEST(user, struct test_user, STRUCT, none); |
279 | 341 | static int noinline __leaf_switch_none(int path, bool fill) |
280 | 342 | { |
281 | 343 | switch (path) { |
| 344 | + /* |
| 345 | + * This is intentionally unreachable. To silence the |
| 346 | + * warning, build with -Wno-switch-unreachable |
| 347 | + */ |
282 | 348 | uint64_t var; |
283 | 349 |
|
284 | 350 | case 1: |
|
0 commit comments