]> Git Repo - J-linux.git/blob - tools/testing/selftests/timens/vfork_exec.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / tools / testing / selftests / timens / vfork_exec.c
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 #include <pthread.h>
16
17 #include "log.h"
18 #include "timens.h"
19
20 #define OFFSET (36000)
21
22 struct thread_args {
23         char *tst_name;
24         struct timespec *now;
25 };
26
27 static void *tcheck(void *_args)
28 {
29         struct thread_args *args = _args;
30         struct timespec *now = args->now, tst;
31         int i;
32
33         for (i = 0; i < 2; i++) {
34                 _gettime(CLOCK_MONOTONIC, &tst, i);
35                 if (abs(tst.tv_sec - now->tv_sec) > 5) {
36                         pr_fail("%s: in-thread: unexpected value: %ld (%ld)\n",
37                                 args->tst_name, tst.tv_sec, now->tv_sec);
38                         return (void *)1UL;
39                 }
40         }
41         return NULL;
42 }
43
44 static int check_in_thread(char *tst_name, struct timespec *now)
45 {
46         struct thread_args args = {
47                 .tst_name = tst_name,
48                 .now = now,
49         };
50         pthread_t th;
51         void *retval;
52
53         if (pthread_create(&th, NULL, tcheck, &args))
54                 return pr_perror("thread");
55         if (pthread_join(th, &retval))
56                 return pr_perror("pthread_join");
57         return !(retval == NULL);
58 }
59
60 static int check(char *tst_name, struct timespec *now)
61 {
62         struct timespec tst;
63         int i;
64
65         for (i = 0; i < 2; i++) {
66                 _gettime(CLOCK_MONOTONIC, &tst, i);
67                 if (abs(tst.tv_sec - now->tv_sec) > 5)
68                         return pr_fail("%s: unexpected value: %ld (%ld)\n",
69                                         tst_name, tst.tv_sec, now->tv_sec);
70         }
71         if (check_in_thread(tst_name, now))
72                 return 1;
73         ksft_test_result_pass("%s\n", tst_name);
74         return 0;
75 }
76
77 int main(int argc, char *argv[])
78 {
79         struct timespec now;
80         int status;
81         pid_t pid;
82
83         if (argc > 1) {
84                 char *endptr;
85
86                 ksft_cnt.ksft_pass = 1;
87                 now.tv_sec = strtoul(argv[1], &endptr, 0);
88                 if (*endptr != 0)
89                         return pr_perror("strtoul");
90
91                 return check("child after exec", &now);
92         }
93
94         nscheck();
95
96         ksft_set_plan(4);
97
98         clock_gettime(CLOCK_MONOTONIC, &now);
99
100         if (unshare_timens())
101                 return 1;
102
103         if (_settime(CLOCK_MONOTONIC, OFFSET))
104                 return 1;
105
106         if (check("parent before vfork", &now))
107                 return 1;
108
109         pid = vfork();
110         if (pid < 0)
111                 return pr_perror("fork");
112
113         if (pid == 0) {
114                 char now_str[64];
115                 char *cargv[] = {"exec", now_str, NULL};
116                 char *cenv[] = {NULL};
117
118                 /* Check for proper vvar offsets after execve. */
119                 snprintf(now_str, sizeof(now_str), "%ld", now.tv_sec + OFFSET);
120                 execve("/proc/self/exe", cargv, cenv);
121                 pr_perror("execve");
122                 _exit(1);
123         }
124
125         if (waitpid(pid, &status, 0) != pid)
126                 return pr_perror("waitpid");
127
128         if (status)
129                 ksft_exit_fail();
130         ksft_inc_pass_cnt();
131         ksft_test_result_pass("wait for child\n");
132
133         /* Check that we are still in the source timens. */
134         if (check("parent after vfork", &now))
135                 return 1;
136
137         ksft_exit_pass();
138         return 0;
139 }
This page took 0.036973 seconds and 4 git commands to generate.