1 /* 2 * Check handling of CLONE_PTRACE'ed processes. 3 * 4 * Copyright (c) 2015-2017 The strace developers. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 32 #include <errno.h> 33 #include <sched.h> 34 #include <signal.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <sys/wait.h> 39 #include <unistd.h> 40 41 static siginfo_t sinfo; 42 43 static void 44 handler(const int no, siginfo_t *const si, void *const uc) 45 { 46 memcpy(&sinfo, si, sizeof(sinfo)); 47 } 48 49 static int 50 child(void *const arg) 51 { 52 for(;;) 53 pause(); 54 return 0; 55 } 56 57 #define child_stack_size (get_page_size() / 2) 58 59 #ifdef IA64 60 extern int __clone2(int (*)(void *), void *, size_t, int, void *, ...); 61 # define clone(fn, child_stack, flags, arg) \ 62 __clone2(fn, child_stack, child_stack_size, flags, arg) 63 #endif 64 65 int 66 main(void) 67 { 68 const int sig = SIGUSR1; 69 sigset_t mask; 70 sigemptyset(&mask); 71 sigaddset(&mask, sig); 72 if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) 73 perror_msg_and_fail("sigprocmask"); 74 75 const pid_t pid = clone(child, tail_alloc(child_stack_size), 76 CLONE_PTRACE | SIGCHLD, 0); 77 if (pid < 0) 78 perror_msg_and_fail("clone"); 79 80 static const struct sigaction sa = { 81 .sa_sigaction = handler, 82 .sa_flags = SA_SIGINFO 83 }; 84 if (sigaction(SIGCHLD, &sa, NULL)) 85 perror_msg_and_fail("sigaction"); 86 87 kill(pid, sig); 88 89 FILE *const fp = fdopen(3, "a"); 90 if (!fp) 91 perror_msg_and_fail("fdopen"); 92 if (fprintf(fp, "%s: Detached unknown pid %d\n", 93 getenv("STRACE_EXE") ?: "strace", pid) < 0) 94 perror_msg_and_fail("fprintf"); 95 96 int status; 97 while (wait(&status) != pid) { 98 if (errno != EINTR) 99 perror_msg_and_fail("wait"); 100 } 101 if (!WIFSIGNALED(status) || WTERMSIG(status) != sig) 102 error_msg_and_fail("unexpected child exit status %d", status); 103 104 printf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=%d" 105 ", si_uid=%u, si_status=%s, si_utime=%u, si_stime=%u} ---\n" 106 "+++ exited with 0 +++\n", pid, geteuid(), "SIGUSR1", 107 (unsigned int) sinfo.si_utime, (unsigned int) sinfo.si_stime); 108 109 return 0; 110 } 111