Messages in this thread Patch in this message | | | From | Adrian Reber <> | Subject | [PATCH 4/4] selftests: add clone3() in time namespace test | Date | Tue, 17 Mar 2020 09:30:44 +0100 |
| |
This adds a test to use clone3() with CLONE_NEWTIME. The test tries to set CLOCK_BOOTTIME to 1 in the new process in the new time namespace and CLOCK_MONOTONIC to +10000.
Signed-off-by: Adrian Reber <areber@redhat.com> --- tools/testing/selftests/timens/Makefile | 4 +- tools/testing/selftests/timens/clone3.c | 134 ++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/timens/clone3.c
diff --git a/tools/testing/selftests/timens/Makefile b/tools/testing/selftests/timens/Makefile index b4fd9a934654..4a50c326bdab 100644 --- a/tools/testing/selftests/timens/Makefile +++ b/tools/testing/selftests/timens/Makefile @@ -1,7 +1,7 @@ -TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec +TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec clone3 TEST_GEN_PROGS_EXTENDED := gettime_perf -CFLAGS := -Wall -Werror -pthread +CFLAGS := -Wall -Werror -pthread -I../../../../usr/include/ LDLIBS := -lrt -ldl include ../lib.mk diff --git a/tools/testing/selftests/timens/clone3.c b/tools/testing/selftests/timens/clone3.c new file mode 100644 index 000000000000..212b35d43fa5 --- /dev/null +++ b/tools/testing/selftests/timens/clone3.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include <linux/sched.h> +#include <linux/types.h> +#include <sched.h> +#include <stdint.h> +#include <string.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +#include "log.h" +#include "timens.h" + +#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) + +struct set_timens_offset { + int clockid; + struct timespec val; +}; + +static void child_exit(int ret) +{ + fflush(stdout); + fflush(stderr); + _exit(ret); +} + +static pid_t sys_clone3(struct clone_args *args, size_t size) +{ + fflush(stdout); + fflush(stderr); + return syscall(__NR_clone3, args, size); +} + +int main(int argc, char *argv[]) +{ + struct set_timens_offset timens_offset[2]; + struct timespec monotonic; + struct timespec boottime; + pid_t pid = -1; + int ret = 0; + int status; + + struct clone_args args = { + .flags = CLONE_NEWTIME, + .exit_signal = SIGCHLD, + }; + + nscheck(); + + ksft_set_plan(1); + + ret = clock_gettime(CLOCK_MONOTONIC, &monotonic); + if (ret) + goto out; + + ret = clock_gettime(CLOCK_BOOTTIME, &boottime); + if (ret) + goto out; + + /* Set CLOCK_BOOTTIME to be 1 (sec). */ + timens_offset[0].clockid = CLOCK_BOOTTIME; + timens_offset[0].val.tv_sec = -boottime.tv_sec + 1; + timens_offset[0].val.tv_nsec = 42; + /* Set CLOCK_MONOTONIC to be 10000 (sec) larger than current. */ + timens_offset[1].clockid = CLOCK_MONOTONIC; + timens_offset[1].val.tv_sec = 10000; + timens_offset[1].val.tv_nsec = 37; + + args.timens_offset_size = 2; + args.timens_offset = ptr_to_u64(timens_offset); + + pid = sys_clone3(&args, sizeof(struct clone_args)); + if (pid < 0) { + ksft_print_msg("%s - Failed to create new process\n", + strerror(errno)); + ret = -errno; + goto out; + } + + if (pid == 0) { + struct timespec monotonic_in_ns; + struct timespec boottime_in_ns; + + ksft_print_msg("I am the child, my PID is %d\n", getpid()); + if (clock_gettime(CLOCK_MONOTONIC, &monotonic_in_ns)) + return -1; + + if (clock_gettime(CLOCK_BOOTTIME, &boottime_in_ns)) + return -1; + + /* + * CLOCK_BOOTTIME has been set to such an offset to + * be 1 in the time namespace after clone3(). + */ + if (boottime_in_ns.tv_sec > 5) + child_exit(EXIT_FAILURE); + ksft_print_msg("CLOCK_BOOTTIME %ld\n", boottime_in_ns.tv_sec); + if (monotonic_in_ns.tv_sec <= monotonic.tv_sec + 9998) + child_exit(EXIT_FAILURE); + ksft_print_msg("CLOCK_MONOTONIC %ld\n", monotonic_in_ns.tv_sec); + child_exit(EXIT_SUCCESS); + } + + if (waitpid(pid, &status, 0) < 0) { + ksft_print_msg("Child returned %s\n", strerror(errno)); + ret = -errno; + goto out; + } + + if (!WIFEXITED(status)) { + ret = -1; + ksft_test_result_fail("Child clocks in time NS are wrong\n"); + goto out; + } + + if (WEXITSTATUS(status)) { + ret = -1; + ksft_test_result_fail("Child clocks in time NS are wrong\n"); + goto out; + } + + ret = 0; + ksft_test_result_pass("Clocks set successfully with clone3()\n"); +out: + if (ret) + ksft_exit_fail(); + + ksft_exit_pass(); + return !!ret; +} -- 2.24.1
| |