Pull Kselftest updates from Shuah Khan: - fixes to seccomp test, and kselftest framework - cleanups to remove duplicate header defines - fixes to efivarfs "make clean" target - cgroup cleanup path - Moving the IMA kexec_load selftest to selftests/kexec work from Mimi Johar and Petr Vorel - A framework to kselftest for writing kernel test modules addition from Tobin C. Harding * tag 'linux-kselftest-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (29 commits) selftests: build and run gpio when output directory is the src dir selftests/ipc: Fix msgque compiler warnings selftests/efivarfs: clean up test files from test_create*() selftests: fix headers_install circular dependency selftests/kexec: update get_secureboot_mode selftests/kexec: make kexec_load test independent of IMA being enabled selftests/kexec: check kexec_load and kexec_file_load are enabled selftests/kexec: Add missing '=y' to config options selftests/kexec: kexec_file_load syscall test selftests/kexec: define "require_root_privileges" selftests/kexec: define common logging functions selftests/kexec: define a set of common functions selftests/kexec: cleanup the kexec selftest selftests/kexec: move the IMA kexec_load selftest to selftests/kexec selftests/harness: Add 30 second timeout per test selftests/seccomp: Handle namespace failures gracefully selftests: cgroup: fix cleanup path in test_memcg_subtree_control() selftests: efivarfs: remove the test_create_read file if it was exist rseq/selftests: Adapt number of threads to the number of detected cpus lib: Add test module for strscpy_pad ...
Unified · Split
| @@ -14,6 +14,10 @@ in safe mode with a limited scope. In limited mode, cpu-hotplug test is · 13 unmodified lines | ||
| 14 | 14 | run on a single cpu as opposed to all hotplug capable cpus, and memory |
| 15 | 15 | hotplug test is run on 2% of hotplug capable memory instead of 10%. |
| 16 | 16 | |
| 17 | +kselftest runs as a userspace process. Tests that can be written/run in | |
| 18 | +userspace may wish to use the `Test Harness`_. Tests that need to be | |
| 19 | +run in kernel space may wish to use a `Test Module`_. | |
| 20 | + | |
| 17 | 21 | Running the selftests (hotplug tests are run in limited mode) |
| 18 | 22 | ============================================================= |
| 19 | 23 | |
| @@ -161,11 +165,97 @@ Contributing new tests (details) · 141 unmodified lines | ||
| 161 | 165 | |
| 162 | 166 | e.g: tools/testing/selftests/android/config |
| 163 | 167 | |
| 168 | +Test Module | |
| 169 | +=========== | |
| 170 | + | |
| 171 | +Kselftest tests the kernel from userspace. Sometimes things need | |
| 172 | +testing from within the kernel, one method of doing this is to create a | |
| 173 | +test module. We can tie the module into the kselftest framework by | |
| 174 | +using a shell script test runner. ``kselftest_module.sh`` is designed | |
| 175 | +to facilitate this process. There is also a header file provided to | |
| 176 | +assist writing kernel modules that are for use with kselftest: | |
| 177 | + | |
| 178 | +- ``tools/testing/kselftest/kselftest_module.h`` | |
| 179 | +- ``tools/testing/kselftest/kselftest_module.sh`` | |
| 180 | + | |
| 181 | +How to use | |
| 182 | +---------- | |
| 183 | + | |
| 184 | +Here we show the typical steps to create a test module and tie it into | |
| 185 | +kselftest. We use kselftests for lib/ as an example. | |
| 186 | + | |
| 187 | +1. Create the test module | |
| 188 | + | |
| 189 | +2. Create the test script that will run (load/unload) the module | |
| 190 | + e.g. ``tools/testing/selftests/lib/printf.sh`` | |
| 191 | + | |
| 192 | +3. Add line to config file e.g. ``tools/testing/selftests/lib/config`` | |
| 193 | + | |
| 194 | +4. Add test script to makefile e.g. ``tools/testing/selftests/lib/Makefile`` | |
| 195 | + | |
| 196 | +5. Verify it works: | |
| 197 | + | |
| 198 | +.. code-block:: sh | |
| 199 | + | |
| 200 | + # Assumes you have booted a fresh build of this kernel tree | |
| 201 | + cd /path/to/linux/tree | |
| 202 | + make kselftest-merge | |
| 203 | + make modules | |
| 204 | + sudo make modules_install | |
| 205 | + make TARGETS=lib kselftest | |
| 206 | + | |
| 207 | +Example Module | |
| 208 | +-------------- | |
| 209 | + | |
| 210 | +A bare bones test module might look like this: | |
| 211 | + | |
| 212 | +.. code-block:: c | |
| 213 | + | |
| 214 | + // SPDX-License-Identifier: GPL-2.0+ | |
| 215 | + | |
| 216 | + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
| 217 | + | |
| 218 | + #include "../tools/testing/selftests/kselftest_module.h" | |
| 219 | + | |
| 220 | + KSTM_MODULE_GLOBALS(); | |
| 221 | + | |
| 222 | + /* | |
| 223 | + * Kernel module for testing the foobinator | |
| 224 | + */ | |
| 225 | + | |
| 226 | + static int __init test_function() | |
| 227 | + { | |
| 228 | + ... | |
| 229 | + } | |
| 230 | + | |
| 231 | + static void __init selftest(void) | |
| 232 | + { | |
| 233 | + KSTM_CHECK_ZERO(do_test_case("", 0)); | |
| 234 | + } | |
| 235 | + | |
| 236 | + KSTM_MODULE_LOADERS(test_foo); | |
| 237 | + MODULE_AUTHOR("John Developer <jd@fooman.org>"); | |
| 238 | + MODULE_LICENSE("GPL"); | |
| 239 | + | |
| 240 | +Example test script | |
| 241 | +------------------- | |
| 242 | + | |
| 243 | +.. code-block:: sh | |
| 244 | + | |
| 245 | + #!/bin/bash | |
| 246 | + # SPDX-License-Identifier: GPL-2.0+ | |
| 247 | + $(dirname $0)/../kselftest_module.sh "foo" test_foo | |
| 248 | + | |
| 249 | + | |
| 164 | 250 | Test Harness |
| 165 | 251 | ============ |
| 166 | 252 | |
| 167 | −The kselftest_harness.h file contains useful helpers to build tests. The tests | |
| 168 | −from tools/testing/selftests/seccomp/seccomp_bpf.c can be used as example. | |
| 253 | +The kselftest_harness.h file contains useful helpers to build tests. The | |
| 254 | +test harness is for userspace testing, for kernel space testing see `Test | |
| 255 | +Module`_ above. | |
| 256 | + | |
| 257 | +The tests from tools/testing/selftests/seccomp/seccomp_bpf.c can be used as | |
| 258 | +example. | |
| 169 | 259 | |
| 170 | 260 | Example |
| 171 | 261 | ------- |
| @@ -31,6 +31,10 @@ size_t strlcpy(char *, const char *, size_t); · 30 unmodified lines | ||
| 31 | 31 | #ifndef __HAVE_ARCH_STRSCPY |
| 32 | 32 | ssize_t strscpy(char *, const char *, size_t); |
| 33 | 33 | #endif |
| 34 | + | |
| 35 | +/* Wraps calls to strscpy()/memset(), no arch specific code required */ | |
| 36 | +ssize_t strscpy_pad(char *dest, const char *src, size_t count); | |
| 37 | + | |
| 34 | 38 | #ifndef __HAVE_ARCH_STRCAT |
| 35 | 39 | extern char * strcat(char *, const char *); |
| 36 | 40 | #endif |
| @@ -1769,6 +1769,9 @@ config TEST_HEXDUMP · 1768 unmodified lines | ||
| 1769 | 1769 | config TEST_STRING_HELPERS |
| 1770 | 1770 | tristate "Test functions located in the string_helpers module at runtime" |
| 1771 | 1771 | |
| 1772 | +config TEST_STRSCPY | |
| 1773 | + tristate "Test strscpy*() family of functions at runtime" | |
| 1774 | + | |
| 1772 | 1775 | config TEST_KSTRTOX |
| 1773 | 1776 | tristate "Test kstrto*() family of functions at runtime" |
| 1774 | 1777 | |
| @@ -81,6 +81,7 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o · 80 unmodified lines | ||
| 81 | 81 | obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o |
| 82 | 82 | obj-$(CONFIG_TEST_PRINTF) += test_printf.o |
| 83 | 83 | obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o |
| 84 | +obj-$(CONFIG_TEST_STRSCPY) += test_strscpy.o | |
| 84 | 85 | obj-$(CONFIG_TEST_BITFIELD) += test_bitfield.o |
| 85 | 86 | obj-$(CONFIG_TEST_UUID) += test_uuid.o |
| 86 | 87 | obj-$(CONFIG_TEST_XARRAY) += test_xarray.o |
| @@ -159,11 +159,9 @@ EXPORT_SYMBOL(strlcpy); · 158 unmodified lines | ||
| 159 | 159 | * @src: Where to copy the string from |
| 160 | 160 | * @count: Size of destination buffer |
| 161 | 161 | * |
| 162 | − * Copy the string, or as much of it as fits, into the dest buffer. | |
| 163 | − * The routine returns the number of characters copied (not including | |
| 164 | − * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. | |
| 165 | − * The behavior is undefined if the string buffers overlap. | |
| 166 | − * The destination buffer is always NUL terminated, unless it's zero-sized. | |
| 162 | + * Copy the string, or as much of it as fits, into the dest buffer. The | |
| 163 | + * behavior is undefined if the string buffers overlap. The destination | |
| 164 | + * buffer is always NUL terminated, unless it's zero-sized. | |
| 167 | 165 | * |
| 168 | 166 | * Preferred to strlcpy() since the API doesn't require reading memory |
| 169 | 167 | * from the src string beyond the specified "count" bytes, and since |
| @@ -173,8 +171,10 @@ EXPORT_SYMBOL(strlcpy); · 3 unmodified lines | ||
| 173 | 171 | * |
| 174 | 172 | * Preferred to strncpy() since it always returns a valid string, and |
| 175 | 173 | * doesn't unnecessarily force the tail of the destination buffer to be |
| 176 | − * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() | |
| 177 | − * with an overflow test, then just memset() the tail of the dest buffer. | |
| 174 | + * zeroed. If zeroing is desired please use strscpy_pad(). | |
| 175 | + * | |
| 176 | + * Return: The number of characters copied (not including the trailing | |
| 177 | + * %NUL) or -E2BIG if the destination buffer wasn't big enough. | |
| 178 | 178 | */ |
| 179 | 179 | ssize_t strscpy(char *dest, const char *src, size_t count) |
| 180 | 180 | { |
| @@ -237,6 +237,39 @@ ssize_t strscpy(char *dest, const char *src, size_t count) · 56 unmodified lines | ||
| 237 | 237 | EXPORT_SYMBOL(strscpy); |
| 238 | 238 | #endif |
| 239 | 239 | |
| 240 | +/** | |
| 241 | + * strscpy_pad() - Copy a C-string into a sized buffer | |
| 242 | + * @dest: Where to copy the string to | |
| 243 | + * @src: Where to copy the string from | |
| 244 | + * @count: Size of destination buffer | |
| 245 | + * | |
| 246 | + * Copy the string, or as much of it as fits, into the dest buffer. The | |
| 247 | + * behavior is undefined if the string buffers overlap. The destination | |
| 248 | + * buffer is always %NUL terminated, unless it's zero-sized. | |
| 249 | + * | |
| 250 | + * If the source string is shorter than the destination buffer, zeros | |
| 251 | + * the tail of the destination buffer. | |
| 252 | + * | |
| 253 | + * For full explanation of why you may want to consider using the | |
| 254 | + * 'strscpy' functions please see the function docstring for strscpy(). | |
| 255 | + * | |
| 256 | + * Return: The number of characters copied (not including the trailing | |
| 257 | + * %NUL) or -E2BIG if the destination buffer wasn't big enough. | |
| 258 | + */ | |
| 259 | +ssize_t strscpy_pad(char *dest, const char *src, size_t count) | |
| 260 | +{ | |
| 261 | + ssize_t written; | |
| 262 | + | |
| 263 | + written = strscpy(dest, src, count); | |
| 264 | + if (written < 0 || written == count - 1) | |
| 265 | + return written; | |
| 266 | + | |
| 267 | + memset(dest + written + 1, 0, count - written - 1); | |
| 268 | + | |
| 269 | + return written; | |
| 270 | +} | |
| 271 | +EXPORT_SYMBOL(strscpy_pad); | |
| 272 | + | |
| 240 | 273 | #ifndef __HAVE_ARCH_STRCAT |
| 241 | 274 | /** |
| 242 | 275 | * strcat - Append one %NUL-terminated string to another |
| @@ -12,6 +12,8 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/slab.h> |
| 13 | 13 | #include <linux/string.h> |
| 14 | 14 | |
| 15 | +#include "../tools/testing/selftests/kselftest_module.h" | |
| 16 | + | |
| 15 | 17 | static unsigned total_tests __initdata; |
| 16 | 18 | static unsigned failed_tests __initdata; |
| 17 | 19 | |
| @@ -361,7 +363,7 @@ static void noinline __init test_mem_optimisations(void) · 343 unmodified lines | ||
| 361 | 363 | } |
| 362 | 364 | } |
| 363 | 365 | |
| 364 | −static int __init test_bitmap_init(void) | |
| 366 | +static void __init selftest(void) | |
| 365 | 367 | { |
| 366 | 368 | test_zero_clear(); |
| 367 | 369 | test_fill_set(); |
| @@ -369,22 +371,8 @@ static int __init test_bitmap_init(void) · 1 unmodified line | ||
| 369 | 371 | test_bitmap_arr32(); |
| 370 | 372 | test_bitmap_parselist(); |
| 371 | 373 | test_mem_optimisations(); |
| 372 | − | |
| 373 | − if (failed_tests == 0) | |
| 374 | − pr_info("all %u tests passed\n", total_tests); | |
| 375 | − else | |
| 376 | − pr_warn("failed %u out of %u tests\n", | |
| 377 | − failed_tests, total_tests); | |
| 378 | − | |
| 379 | − return failed_tests ? -EINVAL : 0; | |
| 380 | 374 | } |
| 381 | 375 | |
| 382 | −static void __exit test_bitmap_cleanup(void) | |
| 383 | −{ | |
| 384 | −} | |
| 385 | − | |
| 386 | −module_init(test_bitmap_init); | |
| 387 | −module_exit(test_bitmap_cleanup); | |
| 388 | − | |
| 376 | +KSTM_MODULE_LOADERS(test_bitmap); | |
| 389 | 377 | MODULE_AUTHOR("david decotigny <david.decotigny@googlers.com>"); |
| 390 | 378 | MODULE_LICENSE("GPL"); |
| @@ -21,6 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/gfp.h> |
| 22 | 22 | #include <linux/mm.h> |
| 23 | 23 | |
| 24 | +#include "../tools/testing/selftests/kselftest_module.h" | |
| 25 | + | |
| 24 | 26 | #define BUF_SIZE 256 |
| 25 | 27 | #define PAD_SIZE 16 |
| 26 | 28 | #define FILL_CHAR '$' |
| @@ -590,12 +592,11 @@ test_pointer(void) · 563 unmodified lines | ||
| 590 | 592 | flags(); |
| 591 | 593 | } |
| 592 | 594 | |
| 593 | −static int __init | |
| 594 | −test_printf_init(void) | |
| 595 | +static void __init selftest(void) | |
| 595 | 596 | { |
| 596 | 597 | alloced_buffer = kmalloc(BUF_SIZE + 2*PAD_SIZE, GFP_KERNEL); |
| 597 | 598 | if (!alloced_buffer) |
| 598 | − return -ENOMEM; | |
| 599 | + return; | |
| 599 | 600 | test_buffer = alloced_buffer + PAD_SIZE; |
| 600 | 601 | |
| 601 | 602 | test_basic(); |
| @@ -604,16 +605,8 @@ test_printf_init(void) · 2 unmodified lines | ||
| 604 | 605 | test_pointer(); |
| 605 | 606 | |
| 606 | 607 | kfree(alloced_buffer); |
| 607 | − | |
| 608 | − if (failed_tests == 0) | |
| 609 | − pr_info("all %u tests passed\n", total_tests); | |
| 610 | − else | |
| 611 | − pr_warn("failed %u out of %u tests\n", failed_tests, total_tests); | |
| 612 | − | |
| 613 | − return failed_tests ? -EINVAL : 0; | |
| 614 | 608 | } |
| 615 | 609 | |
| 616 | −module_init(test_printf_init); | |
| 617 | − | |
| 610 | +KSTM_MODULE_LOADERS(test_printf); | |
| 618 | 611 | MODULE_AUTHOR("Rasmus Villemoes <linux@rasmusvillemoes.dk>"); |
| 619 | 612 | MODULE_LICENSE("GPL"); |
| @@ -0,0 +1,150 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0+ | |
| 2 | + | |
| 3 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
| 4 | + | |
| 5 | +#include <linux/string.h> | |
| 6 | + | |
| 7 | +#include "../tools/testing/selftests/kselftest_module.h" | |
| 8 | + | |
| 9 | +/* | |
| 10 | + * Kernel module for testing 'strscpy' family of functions. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +KSTM_MODULE_GLOBALS(); | |
| 14 | + | |
| 15 | +/* | |
| 16 | + * tc() - Run a specific test case. | |
| 17 | + * @src: Source string, argument to strscpy_pad() | |
| 18 | + * @count: Size of destination buffer, argument to strscpy_pad() | |
| 19 | + * @expected: Expected return value from call to strscpy_pad() | |
| 20 | + * @terminator: 1 if there should be a terminating null byte 0 otherwise. | |
| 21 | + * @chars: Number of characters from the src string expected to be | |
| 22 | + * written to the dst buffer. | |
| 23 | + * @pad: Number of pad characters expected (in the tail of dst buffer). | |
| 24 | + * (@pad does not include the null terminator byte.) | |
| 25 | + * | |
| 26 | + * Calls strscpy_pad() and verifies the return value and state of the | |
| 27 | + * destination buffer after the call returns. | |
| 28 | + */ | |
| 29 | +static int __init tc(char *src, int count, int expected, | |
| 30 | + int chars, int terminator, int pad) | |
| 31 | +{ | |
| 32 | + int nr_bytes_poison; | |
| 33 | + int max_expected; | |
| 34 | + int max_count; | |
| 35 | + int written; | |
| 36 | + char buf[6]; | |
| 37 | + int index, i; | |
| 38 | + const char POISON = 'z'; | |
| 39 | + | |
| 40 | + total_tests++; | |
| 41 | + | |
| 42 | + if (!src) { | |
| 43 | + pr_err("null source string not supported\n"); | |
| 44 | + return -1; | |
| 45 | + } | |
| 46 | + | |
| 47 | + memset(buf, POISON, sizeof(buf)); | |
| 48 | + /* Future proofing test suite, validate args */ | |
| 49 | + max_count = sizeof(buf) - 2; /* Space for null and to verify overflow */ | |
| 50 | + max_expected = count - 1; /* Space for the null */ | |
| 51 | + if (count > max_count) { | |
| 52 | + pr_err("count (%d) is too big (%d) ... aborting", count, max_count); | |
| 53 | + return -1; | |
| 54 | + } | |
| 55 | + if (expected > max_expected) { | |
| 56 | + pr_warn("expected (%d) is bigger than can possibly be returned (%d)", | |
| 57 | + expected, max_expected); | |
| 58 | + } | |
| 59 | + | |
| 60 | + written = strscpy_pad(buf, src, count); | |
| 61 | + if ((written) != (expected)) { | |
| 62 | + pr_err("%d != %d (written, expected)\n", written, expected); | |
| 63 | + goto fail; | |
| 64 | + } | |
| 65 | + | |
| 66 | + if (count && written == -E2BIG) { | |
| 67 | + if (strncmp(buf, src, count - 1) != 0) { | |
| 68 | + pr_err("buffer state invalid for -E2BIG\n"); | |
| 69 | + goto fail; | |
| 70 | + } | |
| 71 | + if (buf[count - 1] != '\0') { | |
| 72 | + pr_err("too big string is not null terminated correctly\n"); | |
| 73 | + goto fail; | |
| 74 | + } | |
| 75 | + } | |
| 76 | + | |
| 77 | + for (i = 0; i < chars; i++) { | |
| 78 | + if (buf[i] != src[i]) { | |
| 79 | + pr_err("buf[i]==%c != src[i]==%c\n", buf[i], src[i]); | |
| 80 | + goto fail; | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + if (terminator) { | |
| 85 | + if (buf[count - 1] != '\0') { | |
| 86 | + pr_err("string is not null terminated correctly\n"); | |
| 87 | + goto fail; | |
| 88 | + } | |
| 89 | + } | |
| 90 | + | |
| 91 | + for (i = 0; i < pad; i++) { | |
| 92 | + index = chars + terminator + i; | |
| 93 | + if (buf[index] != '\0') { | |
| 94 | + pr_err("padding missing at index: %d\n", i); | |
| 95 | + goto fail; | |
| 96 | + } | |
| 97 | + } | |
| 98 | + | |
| 99 | + nr_bytes_poison = sizeof(buf) - chars - terminator - pad; | |
| 100 | + for (i = 0; i < nr_bytes_poison; i++) { | |
| 101 | + index = sizeof(buf) - 1 - i; /* Check from the end back */ | |
| 102 | + if (buf[index] != POISON) { | |
| 103 | + pr_err("poison value missing at index: %d\n", i); | |
| 104 | + goto fail; | |
| 105 | + } | |
| 106 | + } | |
| 107 | + | |
| 108 | + return 0; | |
| 109 | +fail: | |
| 110 | + failed_tests++; | |
| 111 | + return -1; | |
| 112 | +} | |
| 113 | + | |
| 114 | +static void __init selftest(void) | |
| 115 | +{ | |
| 116 | + /* | |
| 117 | + * tc() uses a destination buffer of size 6 and needs at | |
| 118 | + * least 2 characters spare (one for null and one to check for | |
| 119 | + * overflow). This means we should only call tc() with | |
| 120 | + * strings up to a maximum of 4 characters long and 'count' | |
| 121 | + * should not exceed 4. To test with longer strings increase | |
| 122 | + * the buffer size in tc(). | |
| 123 | + */ | |
| 124 | + | |
| 125 | + /* tc(src, count, expected, chars, terminator, pad) */ | |
| 126 | + KSTM_CHECK_ZERO(tc("a", 0, -E2BIG, 0, 0, 0)); | |
| 127 | + KSTM_CHECK_ZERO(tc("", 0, -E2BIG, 0, 0, 0)); | |
| 128 | + | |
| 129 | + KSTM_CHECK_ZERO(tc("a", 1, -E2BIG, 0, 1, 0)); | |
| 130 | + KSTM_CHECK_ZERO(tc("", 1, 0, 0, 1, 0)); | |
| 131 | + | |
| 132 | + KSTM_CHECK_ZERO(tc("ab", 2, -E2BIG, 1, 1, 0)); | |
| 133 | + KSTM_CHECK_ZERO(tc("a", 2, 1, 1, 1, 0)); | |
| 134 | + KSTM_CHECK_ZERO(tc("", 2, 0, 0, 1, 1)); | |
| 135 | + | |
| 136 | + KSTM_CHECK_ZERO(tc("abc", 3, -E2BIG, 2, 1, 0)); | |
| 137 | + KSTM_CHECK_ZERO(tc("ab", 3, 2, 2, 1, 0)); | |
| 138 | + KSTM_CHECK_ZERO(tc("a", 3, 1, 1, 1, 1)); | |
| 139 | + KSTM_CHECK_ZERO(tc("", 3, 0, 0, 1, 2)); | |
| 140 | + | |
| 141 | + KSTM_CHECK_ZERO(tc("abcd", 4, -E2BIG, 3, 1, 0)); | |
| 142 | + KSTM_CHECK_ZERO(tc("abc", 4, 3, 3, 1, 0)); | |
| 143 | + KSTM_CHECK_ZERO(tc("ab", 4, 2, 2, 1, 1)); | |
| 144 | + KSTM_CHECK_ZERO(tc("a", 4, 1, 1, 1, 2)); | |
| 145 | + KSTM_CHECK_ZERO(tc("", 4, 0, 0, 1, 3)); | |
| 146 | +} | |
| 147 | + | |
| 148 | +KSTM_MODULE_LOADERS(test_strscpy); | |
| 149 | +MODULE_AUTHOR("Tobin C. Harding <tobin@kernel.org>"); | |
| 150 | +MODULE_LICENSE("GPL"); | |
| @@ -15,11 +15,11 @@ TARGETS += firmware · 14 unmodified lines | ||
| 15 | 15 | TARGETS += ftrace |
| 16 | 16 | TARGETS += futex |
| 17 | 17 | TARGETS += gpio |
| 18 | −TARGETS += ima | |
| 19 | 18 | TARGETS += intel_pstate |
| 20 | 19 | TARGETS += ipc |
| 21 | 20 | TARGETS += ir |
| 22 | 21 | TARGETS += kcmp |
| 22 | +TARGETS += kexec | |
| 23 | 23 | TARGETS += kvm |
| 24 | 24 | TARGETS += lib |
| 25 | 25 | TARGETS += livepatch |
| @@ -75,12 +75,15 @@ ifneq ($(KBUILD_SRC),) · 49 unmodified lines | ||
| 75 | 75 | override LDFLAGS = |
| 76 | 76 | endif |
| 77 | 77 | |
| 78 | −BUILD := $(O) | |
| 79 | −ifndef BUILD | |
| 80 | − BUILD := $(KBUILD_OUTPUT) | |
| 81 | −endif | |
| 82 | −ifndef BUILD | |
| 83 | − BUILD := $(shell pwd) | |
| 78 | +ifneq ($(O),) | |
| 79 | + BUILD := $(O) | |
| 80 | +else | |
| 81 | + ifneq ($(KBUILD_OUTPUT),) | |
| 82 | + BUILD := $(KBUILD_OUTPUT) | |
| 83 | + else | |
| 84 | + BUILD := $(shell pwd) | |
| 85 | + DEFAULT_INSTALL_HDR_PATH := 1 | |
| 86 | + endif | |
| 84 | 87 | endif |
| 85 | 88 | |
| 86 | 89 | # KSFT_TAP_LEVEL is used from KSFT framework to prevent nested TAP header |
| @@ -89,8 +92,50 @@ endif · 2 unmodified lines | ||
| 89 | 92 | # with system() call. Export it here to cover override RUN_TESTS defines. |
| 90 | 93 | export KSFT_TAP_LEVEL=`echo 1` |
| 91 | 94 | |
| 95 | +# Prepare for headers install | |
| 96 | +top_srcdir ?= ../../.. | |
| 97 | +include $(top_srcdir)/scripts/subarch.include | |
| 98 | +ARCH ?= $(SUBARCH) | |
| 99 | +export KSFT_KHDR_INSTALL_DONE := 1 | |
| 92 | 100 | export BUILD |
| 93 | −all: | |
| 101 | + | |
| 102 | +# build and run gpio when output directory is the src dir. | |
| 103 | +# gpio has dependency on tools/gpio and builds tools/gpio | |
| 104 | +# objects in the src directory in all cases making the src | |
| 105 | +# repo dirty even when objects are relocated. | |
| 106 | +ifneq (1,$(DEFAULT_INSTALL_HDR_PATH)) | |
| 107 | + TMP := $(filter-out gpio, $(TARGETS)) | |
| 108 | + TARGETS := $(TMP) | |
| 109 | +endif | |
| 110 | + | |
| 111 | +# set default goal to all, so make without a target runs all, even when | |
| 112 | +# all isn't the first target in the file. | |
| 113 | +.DEFAULT_GOAL := all | |
| 114 | + | |
| 115 | +# Install headers here once for all tests. KSFT_KHDR_INSTALL_DONE | |
| 116 | +# is used to avoid running headers_install from lib.mk. | |
| 117 | +# Invoke headers install with --no-builtin-rules to avoid circular | |
| 118 | +# dependency in "make kselftest" case. In this case, second level | |
| 119 | +# make inherits builtin-rules which will use the rule generate | |
| 120 | +# Makefile.o and runs into | |
| 121 | +# "Circular Makefile.o <- prepare dependency dropped." | |
| 122 | +# and headers_install fails and test compile fails. | |
| 123 | +# | |
| 124 | +# O= KBUILD_OUTPUT cases don't run into this error, since main Makefile | |
| 125 | +# invokes them as sub-makes and --no-builtin-rules is not necessary, | |
| 126 | +# but doesn't cause any failures. Keep it simple and use the same | |
| 127 | +# flags in both cases. | |
| 128 | +# Local build cases: "make kselftest", "make -C" - headers are installed | |
| 129 | +# in the default INSTALL_HDR_PATH usr/include. | |
| 130 | +khdr: | |
| 131 | +ifeq (1,$(DEFAULT_INSTALL_HDR_PATH)) | |
| 132 | + make --no-builtin-rules ARCH=$(ARCH) -C $(top_srcdir) headers_install | |
| 133 | +else | |
| 134 | + make --no-builtin-rules INSTALL_HDR_PATH=$$BUILD/usr \ | |
| 135 | + ARCH=$(ARCH) -C $(top_srcdir) headers_install | |
| 136 | +endif | |
| 137 | + | |
| 138 | +all: khdr | |
| 94 | 139 | @for TARGET in $(TARGETS); do \ |
| 95 | 140 | BUILD_TARGET=$$BUILD/$$TARGET; \ |
| 96 | 141 | mkdir $$BUILD_TARGET -p; \ |
| @@ -173,4 +218,4 @@ clean: · 76 unmodified lines | ||
| 173 | 218 | make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\ |
| 174 | 219 | done; |
| 175 | 220 | |
| 176 | −.PHONY: all run_tests hotplug run_hotplug clean_hotplug run_pstore_crash install clean | |
| 221 | +.PHONY: khdr all run_tests hotplug run_hotplug clean_hotplug run_pstore_crash install clean | |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | */ |
| 27 | 27 | static int test_memcg_subtree_control(const char *root) |
| 28 | 28 | { |
| 29 | − char *parent, *child, *parent2, *child2; | |
| 29 | + char *parent, *child, *parent2 = NULL, *child2 = NULL; | |
| 30 | 30 | int ret = KSFT_FAIL; |
| 31 | 31 | char buf[PAGE_SIZE]; |
| 32 | 32 | |
| @@ -34,50 +34,54 @@ static int test_memcg_subtree_control(const char *root) · 1 unmodified line | ||
| 34 | 34 | parent = cg_name(root, "memcg_test_0"); |
| 35 | 35 | child = cg_name(root, "memcg_test_0/memcg_test_1"); |
| 36 | 36 | if (!parent || !child) |
| 37 | − goto cleanup; | |
| 37 | + goto cleanup_free; | |
| 38 | 38 | |
| 39 | 39 | if (cg_create(parent)) |
| 40 | − goto cleanup; | |
| 40 | + goto cleanup_free; | |
| 41 | 41 | |
| 42 | 42 | if (cg_write(parent, "cgroup.subtree_control", "+memory")) |
| 43 | − goto cleanup; | |
| 43 | + goto cleanup_parent; | |
| 44 | 44 | |
| 45 | 45 | if (cg_create(child)) |
| 46 | − goto cleanup; | |
| 46 | + goto cleanup_parent; | |
| 47 | 47 | |
| 48 | 48 | if (cg_read_strstr(child, "cgroup.controllers", "memory")) |
| 49 | − goto cleanup; | |
| 49 | + goto cleanup_child; | |
| 50 | 50 | |
| 51 | 51 | /* Create two nested cgroups without enabling memory controller */ |
| 52 | 52 | parent2 = cg_name(root, "memcg_test_1"); |
| 53 | 53 | child2 = cg_name(root, "memcg_test_1/memcg_test_1"); |
| 54 | 54 | if (!parent2 || !child2) |
| 55 | − goto cleanup; | |
| 55 | + goto cleanup_free2; | |
| 56 | 56 | |
| 57 | 57 | if (cg_create(parent2)) |
| 58 | − goto cleanup; | |
| 58 | + goto cleanup_free2; | |
| 59 | 59 | |
| 60 | 60 | if (cg_create(child2)) |
| 61 | − goto cleanup; | |
| 61 | + goto cleanup_parent2; | |
| 62 | 62 | |
| 63 | 63 | if (cg_read(child2, "cgroup.controllers", buf, sizeof(buf))) |
| 64 | − goto cleanup; | |
| 64 | + goto cleanup_all; | |
| 65 | 65 | |
| 66 | 66 | if (!cg_read_strstr(child2, "cgroup.controllers", "memory")) |
| 67 | − goto cleanup; | |
| 67 | + goto cleanup_all; | |
| 68 | 68 | |
| 69 | 69 | ret = KSFT_PASS; |
| 70 | 70 | |
| 71 | −cleanup: | |
| 72 | − cg_destroy(child); | |
| 73 | − cg_destroy(parent); | |
| 74 | − free(parent); | |
| 75 | − free(child); | |
| 76 | − | |
| 71 | +cleanup_all: | |
| 77 | 72 | cg_destroy(child2); |
| 73 | +cleanup_parent2: | |
| 78 | 74 | cg_destroy(parent2); |
| 75 | +cleanup_free2: | |
| 79 | 76 | free(parent2); |
| 80 | 77 | free(child2); |
| 78 | +cleanup_child: | |
| 79 | + cg_destroy(child); | |
| 80 | +cleanup_parent: | |
| 81 | + cg_destroy(parent); | |
| 82 | +cleanup_free: | |
| 83 | + free(parent); | |
| 84 | + free(child); | |
| 81 | 85 | |
| 82 | 86 | return ret; |
| 83 | 87 | } |
| @@ -7,6 +7,12 @@ test_guid=210be57c-9849-4fc7-a635-e6382d1aec27 · 6 unmodified lines | ||
| 7 | 7 | # Kselftest framework requirement - SKIP code is 4. |
| 8 | 8 | ksft_skip=4 |
| 9 | 9 | |
| 10 | +file_cleanup() | |
| 11 | +{ | |
| 12 | + chattr -i $1 | |
| 13 | + rm -f $1 | |
| 14 | +} | |
| 15 | + | |
| 10 | 16 | check_prereqs() |
| 11 | 17 | { |
| 12 | 18 | local msg="skip all tests:" |
| @@ -58,8 +64,10 @@ test_create() · 45 unmodified lines | ||
| 58 | 64 | |
| 59 | 65 | if [ $(stat -c %s $file) -ne 5 ]; then |
| 60 | 66 | echo "$file has invalid size" >&2 |
| 67 | + file_cleanup $file | |
| 61 | 68 | exit 1 |
| 62 | 69 | fi |
| 70 | + file_cleanup $file | |
| 63 | 71 | } |
| 64 | 72 | |
| 65 | 73 | test_create_empty() |
| @@ -72,12 +80,14 @@ test_create_empty() · 6 unmodified lines | ||
| 72 | 80 | echo "$file can not be created without writing" >&2 |
| 73 | 81 | exit 1 |
| 74 | 82 | fi |
| 83 | + file_cleanup $file | |
| 75 | 84 | } |
| 76 | 85 | |
| 77 | 86 | test_create_read() |
| 78 | 87 | { |
| 79 | 88 | local file=$efivarfs_mount/$FUNCNAME-$test_guid |
| 80 | 89 | ./create-read $file |
| 90 | + file_cleanup $file | |
| 81 | 91 | } |
| 82 | 92 | |
| 83 | 93 | test_delete() |
| @@ -92,11 +102,7 @@ test_delete() · 8 unmodified lines | ||
| 92 | 102 | exit 1 |
| 93 | 103 | fi |
| 94 | 104 | |
| 95 | − rm $file 2>/dev/null | |
| 96 | − if [ $? -ne 0 ]; then | |
| 97 | − chattr -i $file | |
| 98 | − rm $file | |
| 99 | − fi | |
| 105 | + file_cleanup $file | |
| 100 | 106 | |
| 101 | 107 | if [ -e $file ]; then |
| 102 | 108 | echo "$file couldn't be deleted" >&2 |
| @@ -150,11 +156,7 @@ test_valid_filenames() · 47 unmodified lines | ||
| 150 | 156 | echo "$file could not be created" >&2 |
| 151 | 157 | ret=1 |
| 152 | 158 | else |
| 153 | − rm $file 2>/dev/null | |
| 154 | − if [ $? -ne 0 ]; then | |
| 155 | − chattr -i $file | |
| 156 | − rm $file | |
| 157 | − fi | |
| 159 | + file_cleanup $file | |
| 158 | 160 | fi |
| 159 | 161 | done |
| 160 | 162 | |
| @@ -187,11 +189,7 @@ test_invalid_filenames() · 26 unmodified lines | ||
| 187 | 189 | |
| 188 | 190 | if [ -e $file ]; then |
| 189 | 191 | echo "Creating $file should have failed" >&2 |
| 190 | − rm $file 2>/dev/null | |
| 191 | − if [ $? -ne 0 ]; then | |
| 192 | − chattr -i $file | |
| 193 | − rm $file | |
| 194 | − fi | |
| 192 | + file_cleanup $file | |
| 195 | 193 | ret=1 |
| 196 | 194 | fi |
| 197 | 195 | done |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <unistd.h> |
| 13 | 13 | #include <stdio.h> |
| 14 | 14 | #include <stdlib.h> |
| 15 | −#include <stdio.h> | |
| 16 | 15 | #include <errno.h> |
| 17 | 16 | #include <string.h> |
| 18 | 17 | #include <fcntl.h> |
| @@ -1,4 +0,0 @@ | ||
| 1 | −CONFIG_IMA_APPRAISE | |
| 2 | −CONFIG_IMA_ARCH_POLICY | |
| 3 | −CONFIG_SECURITYFS | |
| 4 | −CONFIG_KEXEC_VERIFY_SIG | |
| @@ -1,54 +0,0 @@ | ||
| 1 | −#!/bin/sh | |
| 2 | −# SPDX-License-Identifier: GPL-2.0+ | |
| 3 | −# Loading a kernel image via the kexec_load syscall should fail | |
| 4 | −# when the kerne is CONFIG_KEXEC_VERIFY_SIG enabled and the system | |
| 5 | −# is booted in secureboot mode. | |
| 6 | − | |
| 7 | −TEST="$0" | |
| 8 | −EFIVARFS="/sys/firmware/efi/efivars" | |
| 9 | −rc=0 | |
| 10 | − | |
| 11 | −# Kselftest framework requirement - SKIP code is 4. | |
| 12 | −ksft_skip=4 | |
| 13 | − | |
| 14 | −# kexec requires root privileges | |
| 15 | −if [ $UID != 0 ]; then | |
| 16 | − echo "$TEST: must be run as root" >&2 | |
| 17 | − exit $ksft_skip | |
| 18 | −fi | |
| 19 | − | |
| 20 | −# Make sure that efivars is mounted in the normal location | |
| 21 | −if ! grep -q "^\S\+ $EFIVARFS efivarfs" /proc/mounts; then | |
| 22 | − echo "$TEST: efivars is not mounted on $EFIVARFS" >&2 | |
| 23 | − exit $ksft_skip | |
| 24 | −fi | |
| 25 | − | |
| 26 | −# Get secureboot mode | |
| 27 | −file="$EFIVARFS/SecureBoot-*" | |
| 28 | −if [ ! -e $file ]; then | |
| 29 | − echo "$TEST: unknown secureboot mode" >&2 | |
| 30 | − exit $ksft_skip | |
| 31 | −fi | |
| 32 | −secureboot=`hexdump $file | awk '{print substr($4,length($4),1)}'` | |
| 33 | − | |
| 34 | −# kexec_load should fail in secure boot mode | |
| 35 | −KERNEL_IMAGE="/boot/vmlinuz-`uname -r`" | |
| 36 | −kexec -l $KERNEL_IMAGE &>> /dev/null | |
| 37 | −if [ $? == 0 ]; then | |
| 38 | − kexec -u | |
| 39 | − if [ "$secureboot" == "1" ]; then | |
| 40 | − echo "$TEST: kexec_load succeeded [FAIL]" | |
| 41 | − rc=1 | |
| 42 | − else | |
| 43 | − echo "$TEST: kexec_load succeeded [PASS]" | |
| 44 | − fi | |
| 45 | −else | |
| 46 | − if [ "$secureboot" == "1" ]; then | |
| 47 | − echo "$TEST: kexec_load failed [PASS]" | |
| 48 | − else | |
| 49 | − echo "$TEST: kexec_load failed [FAIL]" | |
| 50 | − rc=1 | |
| 51 | − fi | |
| 52 | −fi | |
| 53 | − | |
| 54 | −exit $rc | |
| @@ -1,9 +1,10 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | +#define _GNU_SOURCE | |
| 2 | 3 | #include <stdlib.h> |
| 3 | 4 | #include <stdio.h> |
| 4 | 5 | #include <string.h> |
| 5 | 6 | #include <errno.h> |
| 6 | −#include <linux/msg.h> | |
| 7 | +#include <sys/msg.h> | |
| 7 | 8 | #include <fcntl.h> |
| 8 | 9 | |
| 9 | 10 | #include "../kselftest.h" |
| @@ -73,7 +74,7 @@ int restore_queue(struct msgque_data *msgque) · 63 unmodified lines | ||
| 73 | 74 | return 0; |
| 74 | 75 | |
| 75 | 76 | destroy: |
| 76 | − if (msgctl(id, IPC_RMID, 0)) | |
| 77 | + if (msgctl(id, IPC_RMID, NULL)) | |
| 77 | 78 | printf("Failed to destroy queue: %d\n", -errno); |
| 78 | 79 | return ret; |
| 79 | 80 | } |
| @@ -120,7 +121,7 @@ int check_and_destroy_queue(struct msgque_data *msgque) · 40 unmodified lines | ||
| 120 | 121 | |
| 121 | 122 | ret = 0; |
| 122 | 123 | err: |
| 123 | − if (msgctl(msgque->msq_id, IPC_RMID, 0)) { | |
| 124 | + if (msgctl(msgque->msq_id, IPC_RMID, NULL)) { | |
| 124 | 125 | printf("Failed to destroy queue: %d\n", -errno); |
| 125 | 126 | return -errno; |
| 126 | 127 | } |
| @@ -129,7 +130,7 @@ err: · 2 unmodified lines | ||
| 129 | 130 | |
| 130 | 131 | int dump_queue(struct msgque_data *msgque) |
| 131 | 132 | { |
| 132 | − struct msqid64_ds ds; | |
| 133 | + struct msqid_ds ds; | |
| 133 | 134 | int kern_id; |
| 134 | 135 | int i, ret; |
| 135 | 136 | |
| @@ -245,7 +246,7 @@ int main(int argc, char **argv) · 109 unmodified lines | ||
| 245 | 246 | return ksft_exit_pass(); |
| 246 | 247 | |
| 247 | 248 | err_destroy: |
| 248 | − if (msgctl(msgque.msq_id, IPC_RMID, 0)) { | |
| 249 | + if (msgctl(msgque.msq_id, IPC_RMID, NULL)) { | |
| 249 | 250 | printf("Failed to destroy queue: %d\n", -errno); |
| 250 | 251 | return ksft_exit_fail(); |
| 251 | 252 | } |
| @@ -1,10 +1,11 @@ | ||
| 1 | −# Makefile for kexec_load | |
| 1 | +# Makefile for kexec tests | |
| 2 | 2 | |
| 3 | 3 | uname_M := $(shell uname -m 2>/dev/null || echo not) |
| 4 | 4 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) |
| 5 | 5 | |
| 6 | 6 | ifeq ($(ARCH),x86) |
| 7 | −TEST_PROGS := test_kexec_load.sh | |
| 7 | +TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh | |
| 8 | +TEST_FILES := kexec_common_lib.sh | |
| 8 | 9 | |
| 9 | 10 | include ../lib.mk |
| 10 | 11 | |
| @@ -0,0 +1,3 @@ | ||
| 1 | +CONFIG_IMA_APPRAISE=y | |
| 2 | +CONFIG_IMA_ARCH_POLICY=y | |
| 3 | +CONFIG_SECURITYFS=y | |
| @@ -0,0 +1,220 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | +# | |
| 4 | +# Kselftest framework defines: ksft_pass=0, ksft_fail=1, ksft_skip=4 | |
| 5 | + | |
| 6 | +VERBOSE="${VERBOSE:-1}" | |
| 7 | +IKCONFIG="/tmp/config-`uname -r`" | |
| 8 | +KERNEL_IMAGE="/boot/vmlinuz-`uname -r`" | |
| 9 | +SECURITYFS=$(grep "securityfs" /proc/mounts | awk '{print $2}') | |
| 10 | + | |
| 11 | +log_info() | |
| 12 | +{ | |
| 13 | + [ $VERBOSE -ne 0 ] && echo "[INFO] $1" | |
| 14 | +} | |
| 15 | + | |
| 16 | +# The ksefltest framework requirement returns 0 for PASS. | |
| 17 | +log_pass() | |
| 18 | +{ | |
| 19 | + [ $VERBOSE -ne 0 ] && echo "$1 [PASS]" | |
| 20 | + exit 0 | |
| 21 | +} | |
| 22 | + | |
| 23 | +# The ksefltest framework requirement returns 1 for FAIL. | |
| 24 | +log_fail() | |
| 25 | +{ | |
| 26 | + [ $VERBOSE -ne 0 ] && echo "$1 [FAIL]" | |
| 27 | + exit 1 | |
| 28 | +} | |
| 29 | + | |
| 30 | +# The ksefltest framework requirement returns 4 for SKIP. | |
| 31 | +log_skip() | |
| 32 | +{ | |
| 33 | + [ $VERBOSE -ne 0 ] && echo "$1" | |
| 34 | + exit 4 | |
| 35 | +} | |
| 36 | + | |
| 37 | +# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID). | |
| 38 | +# (Based on kdump-lib.sh) | |
| 39 | +get_efivarfs_secureboot_mode() | |
| 40 | +{ | |
| 41 | + local efivarfs="/sys/firmware/efi/efivars" | |
| 42 | + local secure_boot_file="" | |
| 43 | + local setup_mode_file="" | |
| 44 | + local secureboot_mode=0 | |
| 45 | + local setup_mode=0 | |
| 46 | + | |
| 47 | + # Make sure that efivar_fs is mounted in the normal location | |
| 48 | + if ! grep -q "^\S\+ $efivarfs efivarfs" /proc/mounts; then | |
| 49 | + log_info "efivars is not mounted on $efivarfs" | |
| 50 | + return 0; | |
| 51 | + fi | |
| 52 | + secure_boot_file=$(find "$efivarfs" -name SecureBoot-* 2>/dev/null) | |
| 53 | + setup_mode_file=$(find "$efivarfs" -name SetupMode-* 2>/dev/null) | |
| 54 | + if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then | |
| 55 | + secureboot_mode=$(hexdump -v -e '/1 "%d\ "' \ | |
| 56 | + "$secure_boot_file"|cut -d' ' -f 5) | |
| 57 | + setup_mode=$(hexdump -v -e '/1 "%d\ "' \ | |
| 58 | + "$setup_mode_file"|cut -d' ' -f 5) | |
| 59 | + | |
| 60 | + if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then | |
| 61 | + log_info "secure boot mode enabled (CONFIG_EFIVAR_FS)" | |
| 62 | + return 1; | |
| 63 | + fi | |
| 64 | + fi | |
| 65 | + return 0; | |
| 66 | +} | |
| 67 | + | |
| 68 | +get_efi_var_secureboot_mode() | |
| 69 | +{ | |
| 70 | + local efi_vars | |
| 71 | + local secure_boot_file | |
| 72 | + local setup_mode_file | |
| 73 | + local secureboot_mode | |
| 74 | + local setup_mode | |
| 75 | + | |
| 76 | + if [ ! -d "$efi_vars" ]; then | |
| 77 | + log_skip "efi_vars is not enabled\n" | |
| 78 | + fi | |
| 79 | + secure_boot_file=$(find "$efi_vars" -name SecureBoot-* 2>/dev/null) | |
| 80 | + setup_mode_file=$(find "$efi_vars" -name SetupMode-* 2>/dev/null) | |
| 81 | + if [ -f "$secure_boot_file/data" ] && \ | |
| 82 | + [ -f "$setup_mode_file/data" ]; then | |
| 83 | + secureboot_mode=`od -An -t u1 "$secure_boot_file/data"` | |
| 84 | + setup_mode=`od -An -t u1 "$setup_mode_file/data"` | |
| 85 | + | |
| 86 | + if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then | |
| 87 | + log_info "secure boot mode enabled (CONFIG_EFI_VARS)" | |
| 88 | + return 1; | |
| 89 | + fi | |
| 90 | + fi | |
| 91 | + return 0; | |
| 92 | +} | |
| 93 | + | |
| 94 | +# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID). | |
| 95 | +# The secure boot mode can be accessed either as the last integer | |
| 96 | +# of "od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-*" or from | |
| 97 | +# "od -An -t u1 /sys/firmware/efi/vars/SecureBoot-*/data". The efi | |
| 98 | +# SetupMode can be similarly accessed. | |
| 99 | +# Return 1 for SecureBoot mode enabled and SetupMode mode disabled. | |
| 100 | +get_secureboot_mode() | |
| 101 | +{ | |
| 102 | + local secureboot_mode=0 | |
| 103 | + | |
| 104 | + get_efivarfs_secureboot_mode | |
| 105 | + secureboot_mode=$? | |
| 106 | + | |
| 107 | + # fallback to using the efi_var files | |
| 108 | + if [ $secureboot_mode -eq 0 ]; then | |
| 109 | + get_efi_var_secureboot_mode | |
| 110 | + secureboot_mode=$? | |
| 111 | + fi | |
| 112 | + | |
| 113 | + if [ $secureboot_mode -eq 0 ]; then | |
| 114 | + log_info "secure boot mode not enabled" | |
| 115 | + fi | |
| 116 | + return $secureboot_mode; | |
| 117 | +} | |
| 118 | + | |
| 119 | +require_root_privileges() | |
| 120 | +{ | |
| 121 | + if [ $(id -ru) -ne 0 ]; then | |
| 122 | + log_skip "requires root privileges" | |
| 123 | + fi | |
| 124 | +} | |
| 125 | + | |
| 126 | +# Look for config option in Kconfig file. | |
| 127 | +# Return 1 for found and 0 for not found. | |
| 128 | +kconfig_enabled() | |
| 129 | +{ | |
| 130 | + local config="$1" | |
| 131 | + local msg="$2" | |
| 132 | + | |
| 133 | + grep -E -q $config $IKCONFIG | |
| 134 | + if [ $? -eq 0 ]; then | |
| 135 | + log_info "$msg" | |
| 136 | + return 1 | |
| 137 | + fi | |
| 138 | + return 0 | |
| 139 | +} | |
| 140 | + | |
| 141 | +# Attempt to get the kernel config first via proc, and then by | |
| 142 | +# extracting it from the kernel image or the configs.ko using | |
| 143 | +# scripts/extract-ikconfig. | |
| 144 | +# Return 1 for found. | |
| 145 | +get_kconfig() | |
| 146 | +{ | |
| 147 | + local proc_config="/proc/config.gz" | |
| 148 | + local module_dir="/lib/modules/`uname -r`" | |
| 149 | + local configs_module="$module_dir/kernel/kernel/configs.ko" | |
| 150 | + | |
| 151 | + if [ ! -f $proc_config ]; then | |
| 152 | + modprobe configs > /dev/null 2>&1 | |
| 153 | + fi | |
| 154 | + if [ -f $proc_config ]; then | |
| 155 | + cat $proc_config | gunzip > $IKCONFIG 2>/dev/null | |
| 156 | + if [ $? -eq 0 ]; then | |
| 157 | + return 1 | |
| 158 | + fi | |
| 159 | + fi | |
| 160 | + | |
| 161 | + local extract_ikconfig="$module_dir/source/scripts/extract-ikconfig" | |
| 162 | + if [ ! -f $extract_ikconfig ]; then | |
| 163 | + log_skip "extract-ikconfig not found" | |
| 164 | + fi | |
| 165 | + | |
| 166 | + $extract_ikconfig $KERNEL_IMAGE > $IKCONFIG 2>/dev/null | |
| 167 | + if [ $? -eq 1 ]; then | |
| 168 | + if [ ! -f $configs_module ]; then | |
| 169 | + log_skip "CONFIG_IKCONFIG not enabled" | |
| 170 | + fi | |
| 171 | + $extract_ikconfig $configs_module > $IKCONFIG | |
| 172 | + if [ $? -eq 1 ]; then | |
| 173 | + log_skip "CONFIG_IKCONFIG not enabled" | |
| 174 | + fi | |
| 175 | + fi | |
| 176 | + return 1 | |
| 177 | +} | |
| 178 | + | |
| 179 | +# Make sure that securityfs is mounted | |
| 180 | +mount_securityfs() | |
| 181 | +{ | |
| 182 | + if [ -z $SECURITYFS ]; then | |
| 183 | + SECURITYFS=/sys/kernel/security | |
| 184 | + mount -t securityfs security $SECURITYFS | |
| 185 | + fi | |
| 186 | + | |
| 187 | + if [ ! -d "$SECURITYFS" ]; then | |
| 188 | + log_fail "$SECURITYFS :securityfs is not mounted" | |
| 189 | + fi | |
| 190 | +} | |
| 191 | + | |
| 192 | +# The policy rule format is an "action" followed by key-value pairs. This | |
| 193 | +# function supports up to two key-value pairs, in any order. | |
| 194 | +# For example: action func=<keyword> [appraise_type=<type>] | |
| 195 | +# Return 1 for found and 0 for not found. | |
| 196 | +check_ima_policy() | |
| 197 | +{ | |
| 198 | + local action="$1" | |
| 199 | + local keypair1="$2" | |
| 200 | + local keypair2="$3" | |
| 201 | + local ret=0 | |
| 202 | + | |
| 203 | + mount_securityfs | |
| 204 | + | |
| 205 | + local ima_policy=$SECURITYFS/ima/policy | |
| 206 | + if [ ! -e $ima_policy ]; then | |
| 207 | + log_fail "$ima_policy not found" | |
| 208 | + fi | |
| 209 | + | |
| 210 | + if [ -n $keypair2 ]; then | |
| 211 | + grep -e "^$action.*$keypair1" "$ima_policy" | \ | |
| 212 | + grep -q -e "$keypair2" | |
| 213 | + else | |
| 214 | + grep -q -e "^$action.*$keypair1" "$ima_policy" | |
| 215 | + fi | |
| 216 | + | |
| 217 | + # invert "grep -q" result, returning 1 for found. | |
| 218 | + [ $? -eq 0 ] && ret=1 | |
| 219 | + return $ret | |
| 220 | +} | |
| @@ -0,0 +1,208 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | +# | |
| 4 | +# Loading a kernel image via the kexec_file_load syscall can verify either | |
| 5 | +# the IMA signature stored in the security.ima xattr or the PE signature, | |
| 6 | +# both signatures depending on the IMA policy, or none. | |
| 7 | +# | |
| 8 | +# To determine whether the kernel image is signed, this test depends | |
| 9 | +# on pesign and getfattr. This test also requires the kernel to be | |
| 10 | +# built with CONFIG_IKCONFIG enabled and either CONFIG_IKCONFIG_PROC | |
| 11 | +# enabled or access to the extract-ikconfig script. | |
| 12 | + | |
| 13 | +TEST="KEXEC_FILE_LOAD" | |
| 14 | +. ./kexec_common_lib.sh | |
| 15 | + | |
| 16 | +trap "{ rm -f $IKCONFIG ; }" EXIT | |
| 17 | + | |
| 18 | +# Some of the IMA builtin policies may require the kexec kernel image to | |
| 19 | +# be signed, but these policy rules may be replaced with a custom | |
| 20 | +# policy. Only CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS persists after | |
| 21 | +# loading a custom policy. Check if it is enabled, before reading the | |
| 22 | +# IMA runtime sysfs policy file. | |
| 23 | +# Return 1 for IMA signature required and 0 for not required. | |
| 24 | +is_ima_sig_required() | |
| 25 | +{ | |
| 26 | + local ret=0 | |
| 27 | + | |
| 28 | + kconfig_enabled "CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS=y" \ | |
| 29 | + "IMA kernel image signature required" | |
| 30 | + if [ $? -eq 1 ]; then | |
| 31 | + log_info "IMA signature required" | |
| 32 | + return 1 | |
| 33 | + fi | |
| 34 | + | |
| 35 | + # The architecture specific or a custom policy may require the | |
| 36 | + # kexec kernel image be signed. Policy rules are walked | |
| 37 | + # sequentially. As a result, a policy rule may be defined, but | |
| 38 | + # might not necessarily be used. This test assumes if a policy | |
| 39 | + # rule is specified, that is the intent. | |
| 40 | + if [ $ima_read_policy -eq 1 ]; then | |
| 41 | + check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ | |
| 42 | + "appraise_type=imasig" | |
| 43 | + ret=$? | |
| 44 | + [ $ret -eq 1 ] && log_info "IMA signature required"; | |
| 45 | + fi | |
| 46 | + return $ret | |
| 47 | +} | |
| 48 | + | |
| 49 | +# The kexec_file_load_test() is complicated enough, require pesign. | |
| 50 | +# Return 1 for PE signature found and 0 for not found. | |
| 51 | +check_for_pesig() | |
| 52 | +{ | |
| 53 | + which pesign > /dev/null 2>&1 || log_skip "pesign not found" | |
| 54 | + | |
| 55 | + pesign -i $KERNEL_IMAGE --show-signature | grep -q "No signatures" | |
| 56 | + local ret=$? | |
| 57 | + if [ $ret -eq 1 ]; then | |
| 58 | + log_info "kexec kernel image PE signed" | |
| 59 | + else | |
| 60 | + log_info "kexec kernel image not PE signed" | |
| 61 | + fi | |
| 62 | + return $ret | |
| 63 | +} | |
| 64 | + | |
| 65 | +# The kexec_file_load_test() is complicated enough, require getfattr. | |
| 66 | +# Return 1 for IMA signature found and 0 for not found. | |
| 67 | +check_for_imasig() | |
| 68 | +{ | |
| 69 | + local ret=0 | |
| 70 | + | |
| 71 | + which getfattr > /dev/null 2>&1 | |
| 72 | + if [ $? -eq 1 ]; then | |
| 73 | + log_skip "getfattr not found" | |
| 74 | + fi | |
| 75 | + | |
| 76 | + line=$(getfattr -n security.ima -e hex --absolute-names $KERNEL_IMAGE 2>&1) | |
| 77 | + echo $line | grep -q "security.ima=0x03" | |
| 78 | + if [ $? -eq 0 ]; then | |
| 79 | + ret=1 | |
| 80 | + log_info "kexec kernel image IMA signed" | |
| 81 | + else | |
| 82 | + log_info "kexec kernel image not IMA signed" | |
| 83 | + fi | |
| 84 | + return $ret | |
| 85 | +} | |
| 86 | + | |
| 87 | +kexec_file_load_test() | |
| 88 | +{ | |
| 89 | + local succeed_msg="kexec_file_load succeeded" | |
| 90 | + local failed_msg="kexec_file_load failed" | |
| 91 | + local key_msg="try enabling the CONFIG_INTEGRITY_PLATFORM_KEYRING" | |
| 92 | + | |
| 93 | + line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1) | |
| 94 | + | |
| 95 | + if [ $? -eq 0 ]; then | |
| 96 | + kexec --unload --kexec-file-syscall | |
| 97 | + | |
| 98 | + # In secureboot mode with an architecture specific | |
| 99 | + # policy, make sure either an IMA or PE signature exists. | |
| 100 | + if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \ | |
| 101 | + [ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ]; then | |
| 102 | + log_fail "$succeed_msg (missing sig)" | |
| 103 | + fi | |
| 104 | + | |
| 105 | + if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \ | |
| 106 | + && [ $pe_signed -eq 0 ]; then | |
| 107 | + log_fail "$succeed_msg (missing PE sig)" | |
| 108 | + fi | |
| 109 | + | |
| 110 | + if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then | |
| 111 | + log_fail "$succeed_msg (missing IMA sig)" | |
| 112 | + fi | |
| 113 | + | |
| 114 | + if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ | |
| 115 | + && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \ | |
| 116 | + && [ $ima_read_policy -eq 0 ]; then | |
| 117 | + log_fail "$succeed_msg (possibly missing IMA sig)" | |
| 118 | + fi | |
| 119 | + | |
| 120 | + if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 0 ]; then | |
| 121 | + log_info "No signature verification required" | |
| 122 | + elif [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ | |
| 123 | + && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \ | |
| 124 | + && [ $ima_read_policy -eq 1 ]; then | |
| 125 | + log_info "No signature verification required" | |
| 126 | + fi | |
| 127 | + | |
| 128 | + log_pass "$succeed_msg" | |
| 129 | + fi | |
| 130 | + | |
| 131 | + # Check the reason for the kexec_file_load failure | |
| 132 | + echo $line | grep -q "Required key not available" | |
| 133 | + if [ $? -eq 0 ]; then | |
| 134 | + if [ $platform_keyring -eq 0 ]; then | |
| 135 | + log_pass "$failed_msg (-ENOKEY), $key_msg" | |
| 136 | + else | |
| 137 | + log_pass "$failed_msg (-ENOKEY)" | |
| 138 | + fi | |
| 139 | + fi | |
| 140 | + | |
| 141 | + if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \ | |
| 142 | + && [ $pe_signed -eq 0 ]; then | |
| 143 | + log_pass "$failed_msg (missing PE sig)" | |
| 144 | + fi | |
| 145 | + | |
| 146 | + if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then | |
| 147 | + log_pass "$failed_msg (missing IMA sig)" | |
| 148 | + fi | |
| 149 | + | |
| 150 | + if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ | |
| 151 | + && [ $ima_sig_required -eq 0 ] && [ $ima_read_policy -eq 0 ] \ | |
| 152 | + && [ $ima_signed -eq 0 ]; then | |
| 153 | + log_pass "$failed_msg (possibly missing IMA sig)" | |
| 154 | + fi | |
| 155 | + | |
| 156 | + log_pass "$failed_msg" | |
| 157 | + return 0 | |
| 158 | +} | |
| 159 | + | |
| 160 | +# kexec requires root privileges | |
| 161 | +require_root_privileges | |
| 162 | + | |
| 163 | +# get the kernel config | |
| 164 | +get_kconfig | |
| 165 | + | |
| 166 | +kconfig_enabled "CONFIG_KEXEC_FILE=y" "kexec_file_load is enabled" | |
| 167 | +if [ $? -eq 0 ]; then | |
| 168 | + log_skip "kexec_file_load is not enabled" | |
| 169 | +fi | |
| 170 | + | |
| 171 | +# Determine which kernel config options are enabled | |
| 172 | +kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled" | |
| 173 | +ima_appraise=$? | |
| 174 | + | |
| 175 | +kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \ | |
| 176 | + "architecture specific policy enabled" | |
| 177 | +arch_policy=$? | |
| 178 | + | |
| 179 | +kconfig_enabled "CONFIG_INTEGRITY_PLATFORM_KEYRING=y" \ | |
| 180 | + "platform keyring enabled" | |
| 181 | +platform_keyring=$? | |
| 182 | + | |
| 183 | +kconfig_enabled "CONFIG_IMA_READ_POLICY=y" "reading IMA policy permitted" | |
| 184 | +ima_read_policy=$? | |
| 185 | + | |
| 186 | +kconfig_enabled "CONFIG_KEXEC_SIG_FORCE=y" \ | |
| 187 | + "kexec signed kernel image required" | |
| 188 | +kexec_sig_required=$? | |
| 189 | + | |
| 190 | +kconfig_enabled "CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y" \ | |
| 191 | + "PE signed kernel image required" | |
| 192 | +pe_sig_required=$? | |
| 193 | + | |
| 194 | +is_ima_sig_required | |
| 195 | +ima_sig_required=$? | |
| 196 | + | |
| 197 | +get_secureboot_mode | |
| 198 | +secureboot=$? | |
| 199 | + | |
| 200 | +# Are there pe and ima signatures | |
| 201 | +check_for_pesig | |
| 202 | +pe_signed=$? | |
| 203 | + | |
| 204 | +check_for_imasig | |
| 205 | +ima_signed=$? | |
| 206 | + | |
| 207 | +# Test loading the kernel image via kexec_file_load syscall | |
| 208 | +kexec_file_load_test | |
| @@ -0,0 +1,47 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | +# | |
| 4 | +# Prevent loading a kernel image via the kexec_load syscall when | |
| 5 | +# signatures are required. (Dependent on CONFIG_IMA_ARCH_POLICY.) | |
| 6 | + | |
| 7 | +TEST="$0" | |
| 8 | +. ./kexec_common_lib.sh | |
| 9 | + | |
| 10 | +# kexec requires root privileges | |
| 11 | +require_root_privileges | |
| 12 | + | |
| 13 | +# get the kernel config | |
| 14 | +get_kconfig | |
| 15 | + | |
| 16 | +kconfig_enabled "CONFIG_KEXEC=y" "kexec_load is enabled" | |
| 17 | +if [ $? -eq 0 ]; then | |
| 18 | + log_skip "kexec_load is not enabled" | |
| 19 | +fi | |
| 20 | + | |
| 21 | +kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled" | |
| 22 | +ima_appraise=$? | |
| 23 | + | |
| 24 | +kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \ | |
| 25 | + "IMA architecture specific policy enabled" | |
| 26 | +arch_policy=$? | |
| 27 | + | |
| 28 | +get_secureboot_mode | |
| 29 | +secureboot=$? | |
| 30 | + | |
| 31 | +# kexec_load should fail in secure boot mode and CONFIG_IMA_ARCH_POLICY enabled | |
| 32 | +kexec --load $KERNEL_IMAGE > /dev/null 2>&1 | |
| 33 | +if [ $? -eq 0 ]; then | |
| 34 | + kexec --unload | |
| 35 | + if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ]; then | |
| 36 | + log_fail "kexec_load succeeded" | |
| 37 | + elif [ $ima_appraise -eq 0 -o $arch_policy -eq 0 ]; then | |
| 38 | + log_info "Either IMA or the IMA arch policy is not enabled" | |
| 39 | + fi | |
| 40 | + log_pass "kexec_load succeeded" | |
| 41 | +else | |
| 42 | + if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] ; then | |
| 43 | + log_pass "kexec_load failed" | |
| 44 | + else | |
| 45 | + log_fail "kexec_load failed" | |
| 46 | + fi | |
| 47 | +fi | |
| @@ -696,6 +696,7 @@ void __run_test(struct __test_metadata *t) · 695 unmodified lines | ||
| 696 | 696 | t->passed = 1; |
| 697 | 697 | t->trigger = 0; |
| 698 | 698 | printf("[ RUN ] %s\n", t->name); |
| 699 | + alarm(30); | |
| 699 | 700 | child_pid = fork(); |
| 700 | 701 | if (child_pid < 0) { |
| 701 | 702 | printf("ERROR SPAWNING TEST CHILD\n"); |
| @@ -744,6 +745,7 @@ void __run_test(struct __test_metadata *t) · 42 unmodified lines | ||
| 744 | 745 | } |
| 745 | 746 | } |
| 746 | 747 | printf("[ %4s ] %s\n", (t->passed ? "OK" : "FAIL"), t->name); |
| 748 | + alarm(0); | |
| 747 | 749 | } |
| 748 | 750 | |
| 749 | 751 | static int test_harness_run(int __attribute__((unused)) argc, |
| @@ -0,0 +1,48 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0+ */ | |
| 2 | +#ifndef __KSELFTEST_MODULE_H | |
| 3 | +#define __KSELFTEST_MODULE_H | |
| 4 | + | |
| 5 | +#include <linux/module.h> | |
| 6 | + | |
| 7 | +/* | |
| 8 | + * Test framework for writing test modules to be loaded by kselftest. | |
| 9 | + * See Documentation/dev-tools/kselftest.rst for an example test module. | |
| 10 | + */ | |
| 11 | + | |
| 12 | +#define KSTM_MODULE_GLOBALS() \ | |
| 13 | +static unsigned int total_tests __initdata; \ | |
| 14 | +static unsigned int failed_tests __initdata | |
| 15 | + | |
| 16 | +#define KSTM_CHECK_ZERO(x) do { \ | |
| 17 | + total_tests++; \ | |
| 18 | + if (x) { \ | |
| 19 | + pr_warn("TC failed at %s:%d\n", __func__, __LINE__); \ | |
| 20 | + failed_tests++; \ | |
| 21 | + } \ | |
| 22 | +} while (0) | |
| 23 | + | |
| 24 | +static inline int kstm_report(unsigned int total_tests, unsigned int failed_tests) | |
| 25 | +{ | |
| 26 | + if (failed_tests == 0) | |
| 27 | + pr_info("all %u tests passed\n", total_tests); | |
| 28 | + else | |
| 29 | + pr_warn("failed %u out of %u tests\n", failed_tests, total_tests); | |
| 30 | + | |
| 31 | + return failed_tests ? -EINVAL : 0; | |
| 32 | +} | |
| 33 | + | |
| 34 | +#define KSTM_MODULE_LOADERS(__module) \ | |
| 35 | +static int __init __module##_init(void) \ | |
| 36 | +{ \ | |
| 37 | + pr_info("loaded.\n"); \ | |
| 38 | + selftest(); \ | |
| 39 | + return kstm_report(total_tests, failed_tests); \ | |
| 40 | +} \ | |
| 41 | +static void __exit __module##_exit(void) \ | |
| 42 | +{ \ | |
| 43 | + pr_info("unloaded.\n"); \ | |
| 44 | +} \ | |
| 45 | +module_init(__module##_init); \ | |
| 46 | +module_exit(__module##_exit) | |
| 47 | + | |
| 48 | +#endif /* __KSELFTEST_MODULE_H */ | |
| @@ -0,0 +1,84 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# SPDX-License-Identifier: GPL-2.0+ | |
| 3 | + | |
| 4 | +# | |
| 5 | +# Runs an individual test module. | |
| 6 | +# | |
| 7 | +# kselftest expects a separate executable for each test, this can be | |
| 8 | +# created by adding a script like this: | |
| 9 | +# | |
| 10 | +# #!/bin/sh | |
| 11 | +# SPDX-License-Identifier: GPL-2.0+ | |
| 12 | +# $(dirname $0)/../kselftest_module.sh "description" module_name | |
| 13 | +# | |
| 14 | +# Example: tools/testing/selftests/lib/printf.sh | |
| 15 | + | |
| 16 | +desc="" # Output prefix. | |
| 17 | +module="" # Filename (without the .ko). | |
| 18 | +args="" # modprobe arguments. | |
| 19 | + | |
| 20 | +modprobe="/sbin/modprobe" | |
| 21 | + | |
| 22 | +main() { | |
| 23 | + parse_args "$@" | |
| 24 | + assert_root | |
| 25 | + assert_have_module | |
| 26 | + run_module | |
| 27 | +} | |
| 28 | + | |
| 29 | +parse_args() { | |
| 30 | + script=${0##*/} | |
| 31 | + | |
| 32 | + if [ $# -lt 2 ]; then | |
| 33 | + echo "Usage: $script <description> <module_name> [FAIL]" | |
| 34 | + exit 1 | |
| 35 | + fi | |
| 36 | + | |
| 37 | + desc="$1" | |
| 38 | + shift || true | |
| 39 | + module="$1" | |
| 40 | + shift || true | |
| 41 | + args="$@" | |
| 42 | +} | |
| 43 | + | |
| 44 | +assert_root() { | |
| 45 | + if [ ! -w /dev ]; then | |
| 46 | + skip "please run as root" | |
| 47 | + fi | |
| 48 | +} | |
| 49 | + | |
| 50 | +assert_have_module() { | |
| 51 | + if ! $modprobe -q -n $module; then | |
| 52 | + skip "module $module is not found" | |
| 53 | + fi | |
| 54 | +} | |
| 55 | + | |
| 56 | +run_module() { | |
| 57 | + if $modprobe -q $module $args; then | |
| 58 | + $modprobe -q -r $module | |
| 59 | + say "ok" | |
| 60 | + else | |
| 61 | + fail "" | |
| 62 | + fi | |
| 63 | +} | |
| 64 | + | |
| 65 | +say() { | |
| 66 | + echo "$desc: $1" | |
| 67 | +} | |
| 68 | + | |
| 69 | + | |
| 70 | +fail() { | |
| 71 | + say "$1 [FAIL]" >&2 | |
| 72 | + exit 1 | |
| 73 | +} | |
| 74 | + | |
| 75 | +skip() { | |
| 76 | + say "$1 [SKIP]" >&2 | |
| 77 | + # Kselftest framework requirement - SKIP code is 4. | |
| 78 | + exit 4 | |
| 79 | +} | |
| 80 | + | |
| 81 | +# | |
| 82 | +# Main script | |
| 83 | +# | |
| 84 | +main "$@" | |
| @@ -3,7 +3,16 @@ · 2 unmodified lines | ||
| 3 | 3 | CC := $(CROSS_COMPILE)gcc |
| 4 | 4 | |
| 5 | 5 | ifeq (0,$(MAKELEVEL)) |
| 6 | −OUTPUT := $(shell pwd) | |
| 6 | + ifneq ($(O),) | |
| 7 | + OUTPUT := $(O) | |
| 8 | + else | |
| 9 | + ifneq ($(KBUILD_OUTPUT),) | |
| 10 | + OUTPUT := $(KBUILD_OUTPUT) | |
| 11 | + else | |
| 12 | + OUTPUT := $(shell pwd) | |
| 13 | + DEFAULT_INSTALL_HDR_PATH := 1 | |
| 14 | + endif | |
| 15 | + endif | |
| 7 | 16 | endif |
| 8 | 17 | |
| 9 | 18 | # The following are built by lib.mk common compile rules. |
| @@ -21,9 +30,34 @@ top_srcdir ?= ../../../.. · 11 unmodified lines | ||
| 21 | 30 | include $(top_srcdir)/scripts/subarch.include |
| 22 | 31 | ARCH ?= $(SUBARCH) |
| 23 | 32 | |
| 33 | +# set default goal to all, so make without a target runs all, even when | |
| 34 | +# all isn't the first target in the file. | |
| 35 | +.DEFAULT_GOAL := all | |
| 36 | + | |
| 37 | +# Invoke headers install with --no-builtin-rules to avoid circular | |
| 38 | +# dependency in "make kselftest" case. In this case, second level | |
| 39 | +# make inherits builtin-rules which will use the rule generate | |
| 40 | +# Makefile.o and runs into | |
| 41 | +# "Circular Makefile.o <- prepare dependency dropped." | |
| 42 | +# and headers_install fails and test compile fails. | |
| 43 | +# O= KBUILD_OUTPUT cases don't run into this error, since main Makefile | |
| 44 | +# invokes them as sub-makes and --no-builtin-rules is not necessary, | |
| 45 | +# but doesn't cause any failures. Keep it simple and use the same | |
| 46 | +# flags in both cases. | |
| 47 | +# Note that the support to install headers from lib.mk is necessary | |
| 48 | +# when test Makefile is run directly with "make -C". | |
| 49 | +# When local build is done, headers are installed in the default | |
| 50 | +# INSTALL_HDR_PATH usr/include. | |
| 24 | 51 | .PHONY: khdr |
| 25 | 52 | khdr: |
| 26 | − make ARCH=$(ARCH) -C $(top_srcdir) headers_install | |
| 53 | +ifndef KSFT_KHDR_INSTALL_DONE | |
| 54 | +ifeq (1,$(DEFAULT_INSTALL_HDR_PATH)) | |
| 55 | + make --no-builtin-rules ARCH=$(ARCH) -C $(top_srcdir) headers_install | |
| 56 | +else | |
| 57 | + make --no-builtin-rules INSTALL_HDR_PATH=$$OUTPUT/usr \ | |
| 58 | + ARCH=$(ARCH) -C $(top_srcdir) headers_install | |
| 59 | +endif | |
| 60 | +endif | |
| 27 | 61 | |
| 28 | 62 | all: khdr $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) |
| 29 | 63 | else |
| @@ -3,6 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | # No binaries, but make sure arg-less "make" doesn't trigger "run_tests" |
| 4 | 4 | all: |
| 5 | 5 | |
| 6 | −TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh | |
| 6 | +TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh strscpy.sh | |
| 7 | 7 | |
| 8 | 8 | include ../lib.mk |
| @@ -1,19 +1,3 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | # SPDX-License-Identifier: GPL-2.0 |
| 3 | − | |
| 4 | −# Kselftest framework requirement - SKIP code is 4. | |
| 5 | −ksft_skip=4 | |
| 6 | − | |
| 7 | −# Runs bitmap infrastructure tests using test_bitmap kernel module | |
| 8 | −if ! /sbin/modprobe -q -n test_bitmap; then | |
| 9 | − echo "bitmap: module test_bitmap is not found [SKIP]" | |
| 10 | − exit $ksft_skip | |
| 11 | −fi | |
| 12 | − | |
| 13 | −if /sbin/modprobe -q test_bitmap; then | |
| 14 | − /sbin/modprobe -q -r test_bitmap | |
| 15 | − echo "bitmap: ok" | |
| 16 | −else | |
| 17 | − echo "bitmap: [FAIL]" | |
| 18 | − exit 1 | |
| 19 | −fi | |
| 3 | +$(dirname $0)/../kselftest_module.sh "bitmap" test_bitmap | |
| @@ -1,3 +1,4 @@ | ||
| 1 | 1 | CONFIG_TEST_PRINTF=m |
| 2 | 2 | CONFIG_TEST_BITMAP=m |
| 3 | 3 | CONFIG_PRIME_NUMBERS=m |
| 4 | +CONFIG_TEST_STRSCPY=m | |
| @@ -1,19 +1,4 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | # SPDX-License-Identifier: GPL-2.0 |
| 3 | 3 | # Checks fast/slow prime_number generation for inconsistencies |
| 4 | − | |
| 5 | −# Kselftest framework requirement - SKIP code is 4. | |
| 6 | −ksft_skip=4 | |
| 7 | − | |
| 8 | −if ! /sbin/modprobe -q -n prime_numbers; then | |
| 9 | − echo "prime_numbers: module prime_numbers is not found [SKIP]" | |
| 10 | − exit $ksft_skip | |
| 11 | −fi | |
| 12 | − | |
| 13 | −if /sbin/modprobe -q prime_numbers selftest=65536; then | |
| 14 | − /sbin/modprobe -q -r prime_numbers | |
| 15 | − echo "prime_numbers: ok" | |
| 16 | −else | |
| 17 | − echo "prime_numbers: [FAIL]" | |
| 18 | − exit 1 | |
| 19 | −fi | |
| 4 | +$(dirname $0)/../kselftest_module.sh "prime numbers" prime_numbers selftest=65536 | |
| @@ -1,19 +1,4 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | # SPDX-License-Identifier: GPL-2.0 |
| 3 | −# Runs printf infrastructure using test_printf kernel module | |
| 4 | − | |
| 5 | −# Kselftest framework requirement - SKIP code is 4. | |
| 6 | −ksft_skip=4 | |
| 7 | − | |
| 8 | −if ! /sbin/modprobe -q -n test_printf; then | |
| 9 | − echo "printf: module test_printf is not found [SKIP]" | |
| 10 | − exit $ksft_skip | |
| 11 | −fi | |
| 12 | − | |
| 13 | −if /sbin/modprobe -q test_printf; then | |
| 14 | − /sbin/modprobe -q -r test_printf | |
| 15 | − echo "printf: ok" | |
| 16 | −else | |
| 17 | − echo "printf: [FAIL]" | |
| 18 | − exit 1 | |
| 19 | −fi | |
| 3 | +# Tests the printf infrastructure using test_printf kernel module. | |
| 4 | +$(dirname $0)/../kselftest_module.sh "printf" test_printf | |
| @@ -0,0 +1,3 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# SPDX-License-Identifier: GPL-2.0+ | |
| 3 | +$(dirname $0)/../kselftest_module.sh "strscpy*" test_strscpy | |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <errno.h> |
| 17 | 17 | #include <stdio.h> |
| 18 | 18 | #include <stdlib.h> |
| 19 | −#include <sched.h> | |
| 20 | 19 | #include <linux/rseq.h> |
| 21 | 20 | |
| 22 | 21 | /* |
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | #!/bin/bash |
| 2 | 2 | # SPDX-License-Identifier: GPL-2.0+ or MIT |
| 3 | 3 | |
| 4 | +NR_CPUS=`grep '^processor' /proc/cpuinfo | wc -l` | |
| 5 | + | |
| 4 | 6 | EXTRA_ARGS=${@} |
| 5 | 7 | |
| 6 | 8 | OLDIFS="$IFS" |
| @@ -28,15 +30,16 @@ IFS="$OLDIFS" · 21 unmodified lines | ||
| 28 | 30 | |
| 29 | 31 | REPS=1000 |
| 30 | 32 | SLOW_REPS=100 |
| 33 | +NR_THREADS=$((6*${NR_CPUS})) | |
| 31 | 34 | |
| 32 | 35 | function do_tests() |
| 33 | 36 | { |
| 34 | 37 | local i=0 |
| 35 | 38 | while [ "$i" -lt "${#TEST_LIST[@]}" ]; do |
| 36 | 39 | echo "Running test ${TEST_NAME[$i]}" |
| 37 | − ./param_test ${TEST_LIST[$i]} -r ${REPS} ${@} ${EXTRA_ARGS} || exit 1 | |
| 40 | + ./param_test ${TEST_LIST[$i]} -r ${REPS} -t ${NR_THREADS} ${@} ${EXTRA_ARGS} || exit 1 | |
| 38 | 41 | echo "Running compare-twice test ${TEST_NAME[$i]}" |
| 39 | − ./param_test_compare_twice ${TEST_LIST[$i]} -r ${REPS} ${@} ${EXTRA_ARGS} || exit 1 | |
| 42 | + ./param_test_compare_twice ${TEST_LIST[$i]} -r ${REPS} -t ${NR_THREADS} ${@} ${EXTRA_ARGS} || exit 1 | |
| 40 | 43 | let "i++" |
| 41 | 44 | done |
| 42 | 45 | } |
| @@ -3095,9 +3095,9 @@ TEST(user_notification_basic) · 3094 unmodified lines | ||
| 3095 | 3095 | |
| 3096 | 3096 | /* Check that we get -ENOSYS with no listener attached */ |
| 3097 | 3097 | if (pid == 0) { |
| 3098 | − if (user_trap_syscall(__NR_getpid, 0) < 0) | |
| 3098 | + if (user_trap_syscall(__NR_getppid, 0) < 0) | |
| 3099 | 3099 | exit(1); |
| 3100 | − ret = syscall(__NR_getpid); | |
| 3100 | + ret = syscall(__NR_getppid); | |
| 3101 | 3101 | exit(ret >= 0 || errno != ENOSYS); |
| 3102 | 3102 | } |
| 3103 | 3103 | |
| @@ -3112,12 +3112,12 @@ TEST(user_notification_basic) · 8 unmodified lines | ||
| 3112 | 3112 | EXPECT_EQ(seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog), 0); |
| 3113 | 3113 | |
| 3114 | 3114 | /* Check that the basic notification machinery works */ |
| 3115 | − listener = user_trap_syscall(__NR_getpid, | |
| 3115 | + listener = user_trap_syscall(__NR_getppid, | |
| 3116 | 3116 | SECCOMP_FILTER_FLAG_NEW_LISTENER); |
| 3117 | 3117 | ASSERT_GE(listener, 0); |
| 3118 | 3118 | |
| 3119 | 3119 | /* Installing a second listener in the chain should EBUSY */ |
| 3120 | − EXPECT_EQ(user_trap_syscall(__NR_getpid, | |
| 3120 | + EXPECT_EQ(user_trap_syscall(__NR_getppid, | |
| 3121 | 3121 | SECCOMP_FILTER_FLAG_NEW_LISTENER), |
| 3122 | 3122 | -1); |
| 3123 | 3123 | EXPECT_EQ(errno, EBUSY); |
| @@ -3126,7 +3126,7 @@ TEST(user_notification_basic) · 2 unmodified lines | ||
| 3126 | 3126 | ASSERT_GE(pid, 0); |
| 3127 | 3127 | |
| 3128 | 3128 | if (pid == 0) { |
| 3129 | − ret = syscall(__NR_getpid); | |
| 3129 | + ret = syscall(__NR_getppid); | |
| 3130 | 3130 | exit(ret != USER_NOTIF_MAGIC); |
| 3131 | 3131 | } |
| 3132 | 3132 | |
| @@ -3144,7 +3144,7 @@ TEST(user_notification_basic) · 11 unmodified lines | ||
| 3144 | 3144 | EXPECT_GT(poll(&pollfd, 1, -1), 0); |
| 3145 | 3145 | EXPECT_EQ(pollfd.revents, POLLOUT); |
| 3146 | 3146 | |
| 3147 | − EXPECT_EQ(req.data.nr, __NR_getpid); | |
| 3147 | + EXPECT_EQ(req.data.nr, __NR_getppid); | |
| 3148 | 3148 | |
| 3149 | 3149 | resp.id = req.id; |
| 3150 | 3150 | resp.error = 0; |
| @@ -3176,7 +3176,7 @@ TEST(user_notification_kill_in_middle) · 25 unmodified lines | ||
| 3176 | 3176 | TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); |
| 3177 | 3177 | } |
| 3178 | 3178 | |
| 3179 | − listener = user_trap_syscall(__NR_getpid, | |
| 3179 | + listener = user_trap_syscall(__NR_getppid, | |
| 3180 | 3180 | SECCOMP_FILTER_FLAG_NEW_LISTENER); |
| 3181 | 3181 | ASSERT_GE(listener, 0); |
| 3182 | 3182 | |
| @@ -3188,7 +3188,7 @@ TEST(user_notification_kill_in_middle) · 5 unmodified lines | ||
| 3188 | 3188 | ASSERT_GE(pid, 0); |
| 3189 | 3189 | |
| 3190 | 3190 | if (pid == 0) { |
| 3191 | − ret = syscall(__NR_getpid); | |
| 3191 | + ret = syscall(__NR_getppid); | |
| 3192 | 3192 | exit(ret != USER_NOTIF_MAGIC); |
| 3193 | 3193 | } |
| 3194 | 3194 | |
| @@ -3298,7 +3298,7 @@ TEST(user_notification_closed_listener) · 103 unmodified lines | ||
| 3298 | 3298 | TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); |
| 3299 | 3299 | } |
| 3300 | 3300 | |
| 3301 | − listener = user_trap_syscall(__NR_getpid, | |
| 3301 | + listener = user_trap_syscall(__NR_getppid, | |
| 3302 | 3302 | SECCOMP_FILTER_FLAG_NEW_LISTENER); |
| 3303 | 3303 | ASSERT_GE(listener, 0); |
| 3304 | 3304 | |
| @@ -3309,7 +3309,7 @@ TEST(user_notification_closed_listener) · 4 unmodified lines | ||
| 3309 | 3309 | ASSERT_GE(pid, 0); |
| 3310 | 3310 | if (pid == 0) { |
| 3311 | 3311 | close(listener); |
| 3312 | − ret = syscall(__NR_getpid); | |
| 3312 | + ret = syscall(__NR_getppid); | |
| 3313 | 3313 | exit(ret != -1 && errno != ENOSYS); |
| 3314 | 3314 | } |
| 3315 | 3315 | |
| @@ -3332,14 +3332,15 @@ TEST(user_notification_child_pid_ns) · 16 unmodified lines | ||
| 3332 | 3332 | |
| 3333 | 3333 | ASSERT_EQ(unshare(CLONE_NEWUSER | CLONE_NEWPID), 0); |
| 3334 | 3334 | |
| 3335 | − listener = user_trap_syscall(__NR_getpid, SECCOMP_FILTER_FLAG_NEW_LISTENER); | |
| 3335 | + listener = user_trap_syscall(__NR_getppid, | |
| 3336 | + SECCOMP_FILTER_FLAG_NEW_LISTENER); | |
| 3336 | 3337 | ASSERT_GE(listener, 0); |
| 3337 | 3338 | |
| 3338 | 3339 | pid = fork(); |
| 3339 | 3340 | ASSERT_GE(pid, 0); |
| 3340 | 3341 | |
| 3341 | 3342 | if (pid == 0) |
| 3342 | − exit(syscall(__NR_getpid) != USER_NOTIF_MAGIC); | |
| 3343 | + exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC); | |
| 3343 | 3344 | |
| 3344 | 3345 | EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0); |
| 3345 | 3346 | EXPECT_EQ(req.pid, pid); |
| @@ -3371,7 +3372,8 @@ TEST(user_notification_sibling_pid_ns) · 25 unmodified lines | ||
| 3371 | 3372 | TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!"); |
| 3372 | 3373 | } |
| 3373 | 3374 | |
| 3374 | − listener = user_trap_syscall(__NR_getpid, SECCOMP_FILTER_FLAG_NEW_LISTENER); | |
| 3375 | + listener = user_trap_syscall(__NR_getppid, | |
| 3376 | + SECCOMP_FILTER_FLAG_NEW_LISTENER); | |
| 3375 | 3377 | ASSERT_GE(listener, 0); |
| 3376 | 3378 | |
| 3377 | 3379 | pid = fork(); |
| @@ -3384,7 +3386,7 @@ TEST(user_notification_sibling_pid_ns) · 6 unmodified lines | ||
| 3384 | 3386 | ASSERT_GE(pid2, 0); |
| 3385 | 3387 | |
| 3386 | 3388 | if (pid2 == 0) |
| 3387 | − exit(syscall(__NR_getpid) != USER_NOTIF_MAGIC); | |
| 3389 | + exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC); | |
| 3388 | 3390 | |
| 3389 | 3391 | EXPECT_EQ(waitpid(pid2, &status, 0), pid2); |
| 3390 | 3392 | EXPECT_EQ(true, WIFEXITED(status)); |
| @@ -3393,11 +3395,11 @@ TEST(user_notification_sibling_pid_ns) · 2 unmodified lines | ||
| 3393 | 3395 | } |
| 3394 | 3396 | |
| 3395 | 3397 | /* Create the sibling ns, and sibling in it. */ |
| 3396 | − EXPECT_EQ(unshare(CLONE_NEWPID), 0); | |
| 3397 | − EXPECT_EQ(errno, 0); | |
| 3398 | + ASSERT_EQ(unshare(CLONE_NEWPID), 0); | |
| 3399 | + ASSERT_EQ(errno, 0); | |
| 3398 | 3400 | |
| 3399 | 3401 | pid2 = fork(); |
| 3400 | − EXPECT_GE(pid2, 0); | |
| 3402 | + ASSERT_GE(pid2, 0); | |
| 3401 | 3403 | |
| 3402 | 3404 | if (pid2 == 0) { |
| 3403 | 3405 | ASSERT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0); |
| @@ -3405,7 +3407,7 @@ TEST(user_notification_sibling_pid_ns) · 1 unmodified line | ||
| 3405 | 3407 | * The pid should be 0, i.e. the task is in some namespace that |
| 3406 | 3408 | * we can't "see". |
| 3407 | 3409 | */ |
| 3408 | − ASSERT_EQ(req.pid, 0); | |
| 3410 | + EXPECT_EQ(req.pid, 0); | |
| 3409 | 3411 | |
| 3410 | 3412 | resp.id = req.id; |
| 3411 | 3413 | resp.error = 0; |
| @@ -3435,14 +3437,15 @@ TEST(user_notification_fault_recv) · 23 unmodified lines | ||
| 3435 | 3437 | |
| 3436 | 3438 | ASSERT_EQ(unshare(CLONE_NEWUSER), 0); |
| 3437 | 3439 | |
| 3438 | − listener = user_trap_syscall(__NR_getpid, SECCOMP_FILTER_FLAG_NEW_LISTENER); | |
| 3440 | + listener = user_trap_syscall(__NR_getppid, | |
| 3441 | + SECCOMP_FILTER_FLAG_NEW_LISTENER); | |
| 3439 | 3442 | ASSERT_GE(listener, 0); |
| 3440 | 3443 | |
| 3441 | 3444 | pid = fork(); |
| 3442 | 3445 | ASSERT_GE(pid, 0); |
| 3443 | 3446 | |
| 3444 | 3447 | if (pid == 0) |
| 3445 | − exit(syscall(__NR_getpid) != USER_NOTIF_MAGIC); | |
| 3448 | + exit(syscall(__NR_getppid) != USER_NOTIF_MAGIC); | |
| 3446 | 3449 | |
| 3447 | 3450 | /* Do a bad recv() */ |
| 3448 | 3451 | EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, NULL), -1); |
| @@ -32,7 +32,6 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <sys/types.h> |
| 33 | 33 | #include <sys/stat.h> |
| 34 | 34 | #include <fcntl.h> |
| 35 | −#include <stdlib.h> | |
| 36 | 35 | #include <string.h> |
| 37 | 36 | #include <sys/wait.h> |
| 38 | 37 | #include "../kselftest.h" |
| @@ -8,9 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <unistd.h> |
| 9 | 9 | #include <stdio.h> |
| 10 | 10 | #include <errno.h> |
| 11 | −#include <sys/types.h> | |
| 12 | 11 | #include <sys/stat.h> |
| 13 | −#include <unistd.h> | |
| 14 | 12 | #include <sys/mman.h> |
| 15 | 13 | #include <string.h> |
| 16 | 14 | #include <fcntl.h> |