diff options
Diffstat (limited to 'tools/testing/selftests/clone3')
5 files changed, 201 insertions, 95 deletions
diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c index 1c61e3c022..3c9bf0cd82 100644 --- a/tools/testing/selftests/clone3/clone3.c +++ b/tools/testing/selftests/clone3/clone3.c @@ -7,6 +7,7 @@ #include <inttypes.h> #include <linux/types.h> #include <linux/sched.h> +#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -103,8 +104,8 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) return 0; } -static void test_clone3(uint64_t flags, size_t size, int expected, - enum test_mode test_mode) +static bool test_clone3(uint64_t flags, size_t size, int expected, + enum test_mode test_mode) { int ret; @@ -114,97 +115,223 @@ static void test_clone3(uint64_t flags, size_t size, int expected, ret = call_clone3(flags, size, test_mode); ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n", getpid(), ret, expected); - if (ret != expected) - ksft_test_result_fail( + if (ret != expected) { + ksft_print_msg( "[%d] Result (%d) is different than expected (%d)\n", getpid(), ret, expected); - else - ksft_test_result_pass( - "[%d] Result (%d) matches expectation (%d)\n", - getpid(), ret, expected); -} - -int main(int argc, char *argv[]) -{ - uid_t uid = getuid(); - - ksft_print_header(); - ksft_set_plan(19); - test_clone3_supported(); - - /* Just a simple clone3() should return 0.*/ - test_clone3(0, 0, 0, CLONE3_ARGS_NO_TEST); - - /* Do a clone3() in a new PID NS.*/ - if (uid == 0) - test_clone3(CLONE_NEWPID, 0, 0, CLONE3_ARGS_NO_TEST); - else - ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); + return false; + } - /* Do a clone3() with CLONE_ARGS_SIZE_VER0. */ - test_clone3(0, CLONE_ARGS_SIZE_VER0, 0, CLONE3_ARGS_NO_TEST); + return true; +} - /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 */ - test_clone3(0, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, CLONE3_ARGS_NO_TEST); +typedef bool (*filter_function)(void); +typedef size_t (*size_function)(void); - /* Do a clone3() with sizeof(struct clone_args) + 8 */ - test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_NO_TEST); +static bool not_root(void) +{ + if (getuid() != 0) { + ksft_print_msg("Not running as root\n"); + return true; + } - /* Do a clone3() with exit_signal having highest 32 bits non-zero */ - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG); + return false; +} - /* Do a clone3() with negative 32-bit exit_signal */ - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG); +static bool no_timenamespace(void) +{ + if (not_root()) + return true; - /* Do a clone3() with exit_signal not fitting into CSIGNAL mask */ - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG); + if (!access("/proc/self/ns/time", F_OK)) + return false; - /* Do a clone3() with NSIG < exit_signal < CSIG */ - test_clone3(0, 0, -EINVAL, CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG); + ksft_print_msg("Time namespaces are not supported\n"); + return true; +} - test_clone3(0, sizeof(struct __clone_args) + 8, 0, CLONE3_ARGS_ALL_0); +static size_t page_size_plus_8(void) +{ + return getpagesize() + 8; +} - test_clone3(0, sizeof(struct __clone_args) + 16, -E2BIG, - CLONE3_ARGS_ALL_0); +struct test { + const char *name; + uint64_t flags; + size_t size; + size_function size_function; + int expected; + enum test_mode test_mode; + filter_function filter; +}; - test_clone3(0, sizeof(struct __clone_args) * 2, -E2BIG, - CLONE3_ARGS_ALL_0); +static const struct test tests[] = { + { + .name = "simple clone3()", + .flags = 0, + .size = 0, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "clone3() in a new PID_NS", + .flags = CLONE_NEWPID, + .size = 0, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + .filter = not_root, + }, + { + .name = "CLONE_ARGS_SIZE_VER0", + .flags = 0, + .size = CLONE_ARGS_SIZE_VER0, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "CLONE_ARGS_SIZE_VER0 - 8", + .flags = 0, + .size = CLONE_ARGS_SIZE_VER0 - 8, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "sizeof(struct clone_args) + 8", + .flags = 0, + .size = sizeof(struct __clone_args) + 8, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "exit_signal with highest 32 bits non-zero", + .flags = 0, + .size = 0, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_BIG, + }, + { + .name = "negative 32-bit exit_signal", + .flags = 0, + .size = 0, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG, + }, + { + .name = "exit_signal not fitting into CSIGNAL mask", + .flags = 0, + .size = 0, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG, + }, + { + .name = "NSIG < exit_signal < CSIG", + .flags = 0, + .size = 0, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG, + }, + { + .name = "Arguments sizeof(struct clone_args) + 8", + .flags = 0, + .size = sizeof(struct __clone_args) + 8, + .expected = 0, + .test_mode = CLONE3_ARGS_ALL_0, + }, + { + .name = "Arguments sizeof(struct clone_args) + 16", + .flags = 0, + .size = sizeof(struct __clone_args) + 16, + .expected = -E2BIG, + .test_mode = CLONE3_ARGS_ALL_0, + }, + { + .name = "Arguments sizeof(struct clone_arg) * 2", + .flags = 0, + .size = sizeof(struct __clone_args) + 16, + .expected = -E2BIG, + .test_mode = CLONE3_ARGS_ALL_0, + }, + { + .name = "Arguments > page size", + .flags = 0, + .size_function = page_size_plus_8, + .expected = -E2BIG, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "CLONE_ARGS_SIZE_VER0 in a new PID NS", + .flags = CLONE_NEWPID, + .size = CLONE_ARGS_SIZE_VER0, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + .filter = not_root, + }, + { + .name = "CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS", + .flags = CLONE_NEWPID, + .size = CLONE_ARGS_SIZE_VER0 - 8, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "sizeof(struct clone_args) + 8 in a new PID NS", + .flags = CLONE_NEWPID, + .size = sizeof(struct __clone_args) + 8, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + .filter = not_root, + }, + { + .name = "Arguments > page size in a new PID NS", + .flags = CLONE_NEWPID, + .size_function = page_size_plus_8, + .expected = -E2BIG, + .test_mode = CLONE3_ARGS_NO_TEST, + }, + { + .name = "New time NS", + .flags = CLONE_NEWTIME, + .size = 0, + .expected = 0, + .test_mode = CLONE3_ARGS_NO_TEST, + .filter = no_timenamespace, + }, + { + .name = "exit signal (SIGCHLD) in flags", + .flags = SIGCHLD, + .size = 0, + .expected = -EINVAL, + .test_mode = CLONE3_ARGS_NO_TEST, + }, +}; - /* Do a clone3() with > page size */ - test_clone3(0, getpagesize() + 8, -E2BIG, CLONE3_ARGS_NO_TEST); +int main(int argc, char *argv[]) +{ + size_t size; + int i; - /* Do a clone3() with CLONE_ARGS_SIZE_VER0 in a new PID NS. */ - if (uid == 0) - test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0, 0, - CLONE3_ARGS_NO_TEST); - else - ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); + ksft_print_header(); + ksft_set_plan(ARRAY_SIZE(tests)); + test_clone3_supported(); - /* Do a clone3() with CLONE_ARGS_SIZE_VER0 - 8 in a new PID NS */ - test_clone3(CLONE_NEWPID, CLONE_ARGS_SIZE_VER0 - 8, -EINVAL, - CLONE3_ARGS_NO_TEST); + for (i = 0; i < ARRAY_SIZE(tests); i++) { + if (tests[i].filter && tests[i].filter()) { + ksft_test_result_skip("%s\n", tests[i].name); + continue; + } - /* Do a clone3() with sizeof(struct clone_args) + 8 in a new PID NS */ - if (uid == 0) - test_clone3(CLONE_NEWPID, sizeof(struct __clone_args) + 8, 0, - CLONE3_ARGS_NO_TEST); - else - ksft_test_result_skip("Skipping clone3() with CLONE_NEWPID\n"); + if (tests[i].size_function) + size = tests[i].size_function(); + else + size = tests[i].size; - /* Do a clone3() with > page size in a new PID NS */ - test_clone3(CLONE_NEWPID, getpagesize() + 8, -E2BIG, - CLONE3_ARGS_NO_TEST); + ksft_print_msg("Running test '%s'\n", tests[i].name); - /* Do a clone3() in a new time namespace */ - if (access("/proc/self/ns/time", F_OK) == 0) { - test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST); - } else { - ksft_print_msg("Time namespaces are not supported\n"); - ksft_test_result_skip("Skipping clone3() with CLONE_NEWTIME\n"); + ksft_test_result(test_clone3(tests[i].flags, size, + tests[i].expected, + tests[i].test_mode), + "%s\n", tests[i].name); } - /* Do a clone3() with exit signal (SIGCHLD) in flags */ - test_clone3(SIGCHLD, 0, -EINVAL, CLONE3_ARGS_NO_TEST); - ksft_finished(); } diff --git a/tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c b/tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c index 52d3f0364b..31b56d6256 100644 --- a/tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c +++ b/tools/testing/selftests/clone3/clone3_cap_checkpoint_restore.c @@ -27,9 +27,7 @@ #include "../kselftest_harness.h" #include "clone3_selftests.h" -#ifndef MAX_PID_NS_LEVEL #define MAX_PID_NS_LEVEL 32 -#endif static void child_exit(int ret) { diff --git a/tools/testing/selftests/clone3/clone3_clear_sighand.c b/tools/testing/selftests/clone3/clone3_clear_sighand.c index 47a8c0fc36..54a8b2445b 100644 --- a/tools/testing/selftests/clone3/clone3_clear_sighand.c +++ b/tools/testing/selftests/clone3/clone3_clear_sighand.c @@ -16,10 +16,6 @@ #include "../kselftest.h" #include "clone3_selftests.h" -#ifndef CLONE_CLEAR_SIGHAND -#define CLONE_CLEAR_SIGHAND 0x100000000ULL -#endif - static void nop_handler(int signo) { } diff --git a/tools/testing/selftests/clone3/clone3_selftests.h b/tools/testing/selftests/clone3/clone3_selftests.h index e81ffaaee0..3d2663fe50 100644 --- a/tools/testing/selftests/clone3/clone3_selftests.h +++ b/tools/testing/selftests/clone3/clone3_selftests.h @@ -15,10 +15,6 @@ #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) -#ifndef CLONE_INTO_CGROUP -#define CLONE_INTO_CGROUP 0x200000000ULL /* Clone into a specific cgroup given the right permissions. */ -#endif - #ifndef __NR_clone3 #define __NR_clone3 -1 #endif @@ -32,18 +28,9 @@ struct __clone_args { __aligned_u64 stack; __aligned_u64 stack_size; __aligned_u64 tls; -#ifndef CLONE_ARGS_SIZE_VER0 -#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ -#endif __aligned_u64 set_tid; __aligned_u64 set_tid_size; -#ifndef CLONE_ARGS_SIZE_VER1 -#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */ -#endif __aligned_u64 cgroup; -#ifndef CLONE_ARGS_SIZE_VER2 -#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ -#endif }; static pid_t sys_clone3(struct __clone_args *args, size_t size) diff --git a/tools/testing/selftests/clone3/clone3_set_tid.c b/tools/testing/selftests/clone3/clone3_set_tid.c index 0229e9ebb9..ed785afb60 100644 --- a/tools/testing/selftests/clone3/clone3_set_tid.c +++ b/tools/testing/selftests/clone3/clone3_set_tid.c @@ -23,9 +23,7 @@ #include "../kselftest.h" #include "clone3_selftests.h" -#ifndef MAX_PID_NS_LEVEL #define MAX_PID_NS_LEVEL 32 -#endif static int pipe_1[2]; static int pipe_2[2]; |