1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #define _GNU_SOURCE |
3 | #include <errno.h> |
4 | #include <fcntl.h> |
5 | #include <sched.h> |
6 | #include <stdio.h> |
7 | #include <stdbool.h> |
8 | #include <sys/stat.h> |
9 | #include <sys/syscall.h> |
10 | #include <sys/types.h> |
11 | #include <sys/wait.h> |
12 | #include <time.h> |
13 | #include <unistd.h> |
14 | #include <string.h> |
15 | |
16 | #include "log.h" |
17 | #include "timens.h" |
18 | |
19 | #define OFFSET (36000) |
20 | |
21 | int main(int argc, char *argv[]) |
22 | { |
23 | struct timespec now, tst; |
24 | int status, i; |
25 | pid_t pid; |
26 | |
27 | if (argc > 1) { |
28 | if (sscanf(argv[1], "%ld" , &now.tv_sec) != 1) |
29 | return pr_perror("sscanf" ); |
30 | |
31 | for (i = 0; i < 2; i++) { |
32 | _gettime(CLOCK_MONOTONIC, &tst, i); |
33 | if (labs(tst.tv_sec - now.tv_sec) > 5) |
34 | return pr_fail("%ld %ld\n" , now.tv_sec, tst.tv_sec); |
35 | } |
36 | return 0; |
37 | } |
38 | |
39 | ksft_print_header(); |
40 | |
41 | nscheck(); |
42 | |
43 | ksft_set_plan(plan: 1); |
44 | |
45 | clock_gettime(CLOCK_MONOTONIC, &now); |
46 | |
47 | if (unshare_timens()) |
48 | return 1; |
49 | |
50 | if (_settime(CLOCK_MONOTONIC, OFFSET)) |
51 | return 1; |
52 | |
53 | for (i = 0; i < 2; i++) { |
54 | _gettime(CLOCK_MONOTONIC, &tst, i); |
55 | if (labs(tst.tv_sec - now.tv_sec) > 5) |
56 | return pr_fail("%ld %ld\n" , |
57 | now.tv_sec, tst.tv_sec); |
58 | } |
59 | |
60 | if (argc > 1) |
61 | return 0; |
62 | |
63 | pid = fork(); |
64 | if (pid < 0) |
65 | return pr_perror("fork" ); |
66 | |
67 | if (pid == 0) { |
68 | char now_str[64]; |
69 | char *cargv[] = {"exec" , now_str, NULL}; |
70 | char *cenv[] = {NULL}; |
71 | |
72 | /* Check that a child process is in the new timens. */ |
73 | for (i = 0; i < 2; i++) { |
74 | _gettime(CLOCK_MONOTONIC, &tst, i); |
75 | if (labs(tst.tv_sec - now.tv_sec - OFFSET) > 5) |
76 | return pr_fail("%ld %ld\n" , |
77 | now.tv_sec + OFFSET, tst.tv_sec); |
78 | } |
79 | |
80 | /* Check for proper vvar offsets after execve. */ |
81 | snprintf(now_str, sizeof(now_str), "%ld" , now.tv_sec + OFFSET); |
82 | execve("/proc/self/exe" , cargv, cenv); |
83 | return pr_perror("execve" ); |
84 | } |
85 | |
86 | if (waitpid(pid, &status, 0) != pid) |
87 | return pr_perror("waitpid" ); |
88 | |
89 | if (status) |
90 | ksft_exit_fail(); |
91 | |
92 | ksft_test_result_pass(msg: "exec\n" ); |
93 | ksft_exit_pass(); |
94 | return 0; |
95 | } |
96 | |