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 (abs(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 | nscheck(); |
40 | |
41 | ksft_set_plan(plan: 1); |
42 | |
43 | clock_gettime(CLOCK_MONOTONIC, &now); |
44 | |
45 | if (unshare_timens()) |
46 | return 1; |
47 | |
48 | if (_settime(CLOCK_MONOTONIC, OFFSET)) |
49 | return 1; |
50 | |
51 | for (i = 0; i < 2; i++) { |
52 | _gettime(CLOCK_MONOTONIC, &tst, i); |
53 | if (abs(tst.tv_sec - now.tv_sec) > 5) |
54 | return pr_fail("%ld %ld\n" , |
55 | now.tv_sec, tst.tv_sec); |
56 | } |
57 | |
58 | if (argc > 1) |
59 | return 0; |
60 | |
61 | pid = fork(); |
62 | if (pid < 0) |
63 | return pr_perror("fork" ); |
64 | |
65 | if (pid == 0) { |
66 | char now_str[64]; |
67 | char *cargv[] = {"exec" , now_str, NULL}; |
68 | char *cenv[] = {NULL}; |
69 | |
70 | /* Check that a child process is in the new timens. */ |
71 | for (i = 0; i < 2; i++) { |
72 | _gettime(CLOCK_MONOTONIC, &tst, i); |
73 | if (abs(tst.tv_sec - now.tv_sec - OFFSET) > 5) |
74 | return pr_fail("%ld %ld\n" , |
75 | now.tv_sec + OFFSET, tst.tv_sec); |
76 | } |
77 | |
78 | /* Check for proper vvar offsets after execve. */ |
79 | snprintf(now_str, sizeof(now_str), "%ld" , now.tv_sec + OFFSET); |
80 | execve("/proc/self/exe" , cargv, cenv); |
81 | return pr_perror("execve" ); |
82 | } |
83 | |
84 | if (waitpid(pid, &status, 0) != pid) |
85 | return pr_perror("waitpid" ); |
86 | |
87 | if (status) |
88 | ksft_exit_fail(); |
89 | |
90 | ksft_test_result_pass(msg: "exec\n" ); |
91 | ksft_exit_pass(); |
92 | return 0; |
93 | } |
94 | |