1 /*
2 * Check decoding of threads when a non-leader thread invokes execve.
3 *
4 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2023 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #ifdef __NR_nanosleep
15
16 # include <errno.h>
17 # include <pthread.h>
18 # include <signal.h>
19 # include <stdio.h>
20 # include <stdlib.h>
21 # include <time.h>
22 # include <unistd.h>
23
24 # include "kernel_old_timespec.h"
25
26 # ifndef PRINT_EXITED
27 # define PRINT_EXITED 1
28 # endif
29 # ifndef PRINT_SUPERSEDED
30 # define PRINT_SUPERSEDED 1
31 # endif
32
33 static pid_t leader;
34 static pid_t tid;
35
36 static void
37 handler(int signo)
38 {
39 }
40
41 static unsigned int sigsetsize;
42 static long
43 k_sigsuspend(const sigset_t *const set)
44 {
45 return syscall(__NR_rt_sigsuspend, set, sigsetsize);
46 }
47
48 static pid_t
49 k_gettid(void)
50 {
51 return syscall(__NR_gettid);
52 }
53
54 static void
55 get_sigsetsize(void)
56 {
57 static const struct sigaction sa = { .sa_handler = handler };
58 if (sigaction(SIGUSR1, &sa, NULL))
59 perror_msg_and_fail("sigaction");
60
61 sigset_t mask;
62 sigemptyset(&mask);
63 sigaddset(&mask, SIGUSR1);
64 if (sigprocmask(SIG_BLOCK, &mask, NULL))
65 perror_msg_and_fail("sigprocmask");
66
67 raise(SIGUSR1);
68
69 sigemptyset(&mask);
70 for (sigsetsize = sizeof(mask) / sizeof(long);
71 sigsetsize; sigsetsize >>= 1) {
72 long rc = k_sigsuspend(&mask);
73 if (!rc)
74 error_msg_and_fail("rt_sigsuspend");
75 if (EINTR == errno)
76 break;
77 printf("%-5d rt_sigsuspend(%p, %u) = %s\n",
78 leader, &mask, sigsetsize, sprintrc(rc));
79 }
80 if (!sigsetsize)
81 perror_msg_and_fail("rt_sigsuspend");
82 printf("%-5d rt_sigsuspend([], %u) = ? ERESTARTNOHAND"
83 " (To be restarted if no handler)\n", leader, sigsetsize);
84 }
85
86 enum {
87 ACTION_exit = 0,
88 ACTION_rt_sigsuspend,
89 ACTION_nanosleep,
90 NUMBER_OF_ACTIONS
91 };
92
93 static const unsigned int NUMBER_OF_ITERATIONS = 1;
94 static unsigned int action;
95 static int fds[2];
96
97 static unsigned int
98 arglen(char **args)
99 {
100 char **p;
101
102 for (p = args; *p; ++p)
103 ;
104
105 return p - args;
106 }
107
108 static void *
109 thread(void *arg)
110 {
111 tid = k_gettid();
112
113 static char buf[sizeof(action) * 3];
114 sprintf(buf, "%u", action + 1);
115
116 char **argv = arg;
117 argv[2] = buf;
118
119 if (read(fds[0], fds, sizeof(fds[0])))
120 perror_msg_and_fail("execve");
121
122 kernel_old_timespec_t ts = { .tv_nsec = 100000000 };
123 (void) syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0, &ts, NULL);
124
125 kernel_old_timespec_t ots = { .tv_nsec = 12345 };
126 printf("%-5d nanosleep({tv_sec=0, tv_nsec=%u}, NULL) = 0\n",
127 tid, (unsigned int) ots.tv_nsec);
128
129 switch (action % NUMBER_OF_ACTIONS) {
130 case ACTION_exit:
131 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]"
132 ", %p /* %u vars */ <pid changed to %u ...>\n",
133 tid, argv[0], argv[0], argv[1], argv[2],
134 environ, arglen(environ), leader);
135 break;
136 case ACTION_rt_sigsuspend:
137 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]"
138 ", %p /* %u vars */ <unfinished ...>\n"
139 "%-5d <... rt_sigsuspend resumed>) = ?\n",
140 tid, argv[0], argv[0], argv[1], argv[2],
141 environ, arglen(environ),
142 leader);
143 break;
144 case ACTION_nanosleep:
145 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]"
146 ", %p /* %u vars */ <unfinished ...>\n"
147 "%-5d <... nanosleep resumed> <unfinished ...>)"
148 " = ?\n",
149 tid, argv[0], argv[0], argv[1], argv[2],
150 environ, arglen(environ),
151 leader);
152 break;
153 }
154
155 # if PRINT_SUPERSEDED
156 printf("%-5d +++ superseded by execve in pid %u +++\n", leader, tid);
157 # endif
158 printf("%-5d <... execve resumed>) = 0\n", leader);
159
160 (void) syscall(__NR_nanosleep, (unsigned long) &ots, 0UL);
161 execve(argv[0], argv, environ);
162 perror_msg_and_fail("execve");
163 }
164
165 int
166 main(int ac, char **av)
167 {
168 setvbuf(stdout, NULL, _IONBF, 0);
169 leader = getpid();
170
171 if (ac < 3) {
172 kernel_old_timespec_t ts = { .tv_nsec = 1 };
173 if (syscall(__NR_clock_nanosleep, CLOCK_REALTIME, 0, &ts, NULL))
174 perror_msg_and_skip("clock_nanosleep CLOCK_REALTIME");
175
176 get_sigsetsize();
177 static char buf[sizeof(sigsetsize) * 3];
178 sprintf(buf, "%u", sigsetsize);
179
180 char *argv[] = { av[0], buf, (char *) "0", NULL };
181 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]"
182 ", %p /* %u vars */) = 0\n",
183 leader, argv[0], argv[0], argv[1], argv[2],
184 environ, arglen(environ));
185 execve(argv[0], argv, environ);
186 perror_msg_and_fail("execve");
187 }
188
189 sigsetsize = atoi(av[1]);
190 action = atoi(av[2]);
191
192 if (action >= NUMBER_OF_ACTIONS * NUMBER_OF_ITERATIONS) {
193 # if PRINT_EXITED
194 printf("%-5d +++ exited with 0 +++\n", leader);
195 # endif
196 return 0;
197 }
198
199 if (pipe(fds))
200 perror_msg_and_fail("pipe");
201
202 pthread_t t;
203 errno = pthread_create(&t, NULL, thread, av);
204 if (errno)
205 perror_msg_and_fail("pthread_create");
206
207 kernel_old_timespec_t ots = { .tv_sec = 123 };
208 sigset_t mask;
209 sigemptyset(&mask);
210
211 static char leader_str[sizeof(leader) * 3];
212 int leader_str_len =
213 snprintf(leader_str, sizeof(leader_str), "%-5d", leader);
214
215 switch (action % NUMBER_OF_ACTIONS) {
216 case ACTION_exit:
217 printf("%s exit(42)%*s= ?\n", leader_str,
218 (int) sizeof(leader_str) - leader_str_len, " ");
219 close(fds[1]);
220 (void) syscall(__NR_exit, 42);
221 break;
222 case ACTION_rt_sigsuspend:
223 printf("%s rt_sigsuspend([], %u <unfinished ...>\n",
224 leader_str, sigsetsize);
225 close(fds[1]);
226 (void) k_sigsuspend(&mask);
227 break;
228 case ACTION_nanosleep:
229 printf("%s nanosleep({tv_sec=%u, tv_nsec=0}"
230 ", <unfinished ...>\n",
231 leader_str, (unsigned int) ots.tv_sec);
232 close(fds[1]);
233 (void) syscall(__NR_nanosleep,
234 (unsigned long) &ots, 0UL);
235 break;
236 }
237
238 return 1;
239 }
240
241 #else
242
243 SKIP_MAIN_UNDEFINED("__NR_nanosleep")
244
245 #endif