1 /* 2 * Check decoding of threads when a non-leader thread invokes execve. 3 * 4 * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org> 5 * Copyright (c) 2016-2017 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <asm/unistd.h> 33 #include <errno.h> 34 #include <pthread.h> 35 #include <signal.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <time.h> 39 #include <unistd.h> 40 41 static pid_t leader; 42 static pid_t tid; 43 44 static void 45 handler(int signo) 46 { 47 } 48 49 static unsigned int sigsetsize; 50 static long 51 k_sigsuspend(const sigset_t *const set) 52 { 53 return syscall(__NR_rt_sigsuspend, set, sigsetsize); 54 } 55 56 static pid_t 57 k_gettid(void) 58 { 59 return syscall(__NR_gettid); 60 } 61 62 static void 63 get_sigsetsize(void) 64 { 65 static const struct sigaction sa = { .sa_handler = handler }; 66 if (sigaction(SIGUSR1, &sa, NULL)) 67 perror_msg_and_fail("sigaction"); 68 69 sigset_t mask; 70 sigemptyset(&mask); 71 sigaddset(&mask, SIGUSR1); 72 if (sigprocmask(SIG_BLOCK, &mask, NULL)) 73 perror_msg_and_fail("sigprocmask"); 74 75 raise(SIGUSR1); 76 77 sigemptyset(&mask); 78 for (sigsetsize = sizeof(mask) / sizeof(long); 79 sigsetsize; sigsetsize >>= 1) { 80 long rc = k_sigsuspend(&mask); 81 if (!rc) 82 error_msg_and_fail("rt_sigsuspend"); 83 if (EINTR == errno) 84 break; 85 printf("%-5d rt_sigsuspend(%p, %u) = %s\n", 86 leader, &mask, sigsetsize, sprintrc(rc)); 87 } 88 if (!sigsetsize) 89 perror_msg_and_fail("rt_sigsuspend"); 90 printf("%-5d rt_sigsuspend([], %u) = ? ERESTARTNOHAND" 91 " (To be restarted if no handler)\n", leader, sigsetsize); 92 } 93 94 enum { 95 ACTION_exit = 0, 96 ACTION_rt_sigsuspend, 97 ACTION_nanosleep, 98 NUMBER_OF_ACTIONS 99 }; 100 101 static const unsigned int NUMBER_OF_ITERATIONS = 1; 102 static unsigned int action; 103 static int fds[2]; 104 105 static unsigned int 106 arglen(char **args) 107 { 108 char **p; 109 110 for (p = args; *p; ++p) 111 ; 112 113 return p - args; 114 } 115 116 static void * 117 thread(void *arg) 118 { 119 tid = k_gettid(); 120 121 static char buf[sizeof(action) * 3]; 122 sprintf(buf, "%u", action + 1); 123 124 char **argv = arg; 125 argv[2] = buf; 126 127 if (read(fds[0], fds, sizeof(fds[0]))) 128 perror_msg_and_fail("execve"); 129 130 struct timespec ts = { .tv_nsec = 100000000 }; 131 (void) clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL); 132 133 ts.tv_nsec = 12345; 134 printf("%-5d nanosleep({tv_sec=0, tv_nsec=%u}, NULL) = 0\n", 135 tid, (unsigned int) ts.tv_nsec); 136 137 switch (action % NUMBER_OF_ACTIONS) { 138 case ACTION_exit: 139 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]" 140 ", %p /* %u vars */ <pid changed to %u ...>\n", 141 tid, argv[0], argv[0], argv[1], argv[2], 142 environ, arglen(environ), leader); 143 break; 144 case ACTION_rt_sigsuspend: 145 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]" 146 ", %p /* %u vars */ <unfinished ...>\n" 147 "%-5d <... rt_sigsuspend resumed>) = ?\n", 148 tid, argv[0], argv[0], argv[1], argv[2], 149 environ, arglen(environ), 150 leader); 151 break; 152 case ACTION_nanosleep: 153 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]" 154 ", %p /* %u vars */ <unfinished ...>\n" 155 "%-5d <... nanosleep resumed> <unfinished ...>)" 156 " = ?\n", 157 tid, argv[0], argv[0], argv[1], argv[2], 158 environ, arglen(environ), 159 leader); 160 break; 161 } 162 163 printf("%-5d +++ superseded by execve in pid %u +++\n" 164 "%-5d <... execve resumed> ) = 0\n", 165 leader, tid, 166 leader); 167 168 (void) nanosleep(&ts, NULL); 169 execve(argv[0], argv, environ); 170 perror_msg_and_fail("execve"); 171 } 172 173 int 174 main(int ac, char **av) 175 { 176 setvbuf(stdout, NULL, _IONBF, 0); 177 leader = getpid(); 178 179 if (ac < 3) { 180 struct timespec ts = { .tv_nsec = 1 }; 181 if (clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL)) 182 perror_msg_and_skip("clock_nanosleep CLOCK_REALTIME"); 183 184 get_sigsetsize(); 185 static char buf[sizeof(sigsetsize) * 3]; 186 sprintf(buf, "%u", sigsetsize); 187 188 char *argv[] = { av[0], buf, (char *) "0", NULL }; 189 printf("%-5d execve(\"%s\", [\"%s\", \"%s\", \"%s\"]" 190 ", %p /* %u vars */) = 0\n", 191 leader, argv[0], argv[0], argv[1], argv[2], 192 environ, arglen(environ)); 193 execve(argv[0], argv, environ); 194 perror_msg_and_fail("execve"); 195 } 196 197 sigsetsize = atoi(av[1]); 198 action = atoi(av[2]); 199 200 if (action >= NUMBER_OF_ACTIONS * NUMBER_OF_ITERATIONS) { 201 printf("%-5d +++ exited with 0 +++\n", leader); 202 return 0; 203 } 204 205 if (pipe(fds)) 206 perror_msg_and_fail("pipe"); 207 208 pthread_t t; 209 errno = pthread_create(&t, NULL, thread, av); 210 if (errno) 211 perror_msg_and_fail("pthread_create"); 212 213 struct timespec ts = { .tv_sec = 123 }; 214 sigset_t mask; 215 sigemptyset(&mask); 216 217 static char leader_str[sizeof(leader) * 3]; 218 int leader_str_len = 219 snprintf(leader_str, sizeof(leader_str), "%-5d", leader); 220 221 switch (action % NUMBER_OF_ACTIONS) { 222 case ACTION_exit: 223 printf("%s exit(42)%*s= ?\n", leader_str, 224 (int) sizeof(leader_str) - leader_str_len, " "); 225 close(fds[1]); 226 (void) syscall(__NR_exit, 42); 227 break; 228 case ACTION_rt_sigsuspend: 229 printf("%s rt_sigsuspend([], %u <unfinished ...>\n", 230 leader_str, sigsetsize); 231 close(fds[1]); 232 (void) k_sigsuspend(&mask); 233 break; 234 case ACTION_nanosleep: 235 printf("%s nanosleep({tv_sec=%u, tv_nsec=0}" 236 ", <unfinished ...>\n", 237 leader_str, (unsigned int) ts.tv_sec); 238 close(fds[1]); 239 (void) nanosleep(&ts, 0); 240 break; 241 } 242 243 return 1; 244 } 245