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