1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5# 6# Copyright (c) 2021 Mark Johnston <markj@FreeBSD.org> 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# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# ptrace(2) test scenario by Mark Johnston 31# https://people.freebsd.org/~markj/ptrace_stop_mt.c 32# Fixed by r303423. 33 34# stopped on signal 17 after detach 35# UID PID PPID CPU PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND 36# 1001 47125 62778 0 52 0 6568 2456 wait S+ 2 0:00.01 /bin/sh ./ptrace10.sh 37# 1001 47146 47125 0 23 0 6108 1928 nanslp S+ 2 0:00.00 ./ptrace10 38# 1001 47148 47146 0 24 0 6240 1932 - T+ 2 0:00.00 ./ptrace10 39# 1001 47148 47146 0 24 0 6240 1932 - T+ 2 0:00.00 ./ptrace10 40 41. ../default.cfg 42 43cd /tmp 44cat > ptrace10.c <<EOF 45#include <sys/types.h> 46#include <sys/ptrace.h> 47#include <sys/wait.h> 48 49#include <err.h> 50#include <pthread.h> 51#include <signal.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <unistd.h> 55 56static void 57sighup(int sig __unused) 58{ 59} 60 61static void 62sleep_forever(void) 63{ 64 65 while (1) 66 sleep(1); 67} 68 69static void * 70thread(void *arg __unused) 71{ 72 73 sleep_forever(); 74 return (NULL); 75} 76 77int 78main(void) 79{ 80 struct sigaction act; 81 sigset_t set; 82 pthread_t t; 83 pid_t pid, ret; 84 int e, try, limit, r, status; 85 86 e = 0; 87 pid = fork(); 88 if (pid < 0) 89 err(1, "fork"); 90 if (pid == 0) { 91 act.sa_handler = sighup; 92 act.sa_flags = 0; 93 sigemptyset(&act.sa_mask); 94 if (sigaction(SIGHUP, &act, NULL) != 0) 95 err(1, "sigaction"); 96 97 r = pthread_create(&t, NULL, thread, NULL); 98 if (r != 0) 99 errc(1, r, "pthread_create"); 100 101 /* Force SIGHUP to be delivered to the new thread. */ 102 sigemptyset(&set); 103 sigaddset(&set, SIGHUP); 104 r = pthread_sigmask(SIG_BLOCK, &set, NULL); 105 if (r != 0) 106 errc(1, r, "pthread_sigmask"); 107 108 sleep_forever(); 109 } else { 110 sleep(1); /* give the child a chance to set itself up */ 111 112 limit = 100; 113 for (try = 1; try <= limit; try++) { 114 if (kill(pid, SIGHUP) != 0) 115 err(1, "kill(SIGHUP)"); 116 if (ptrace(PT_ATTACH, pid, NULL, 0) != 0) 117 err(1, "ptrace(PT_ATTACH)"); 118 if (waitpid(pid, &status, WUNTRACED) != pid) 119 err(1, "waitpid 1"); 120 if (!WIFSTOPPED(status)) 121 errx(1, "unexpected status %d after PT_ATTACH", 122 status); 123 if (ptrace(PT_DETACH, pid, NULL, 0) != 0) 124 err(1, "ptrace(PT_DETACH)"); 125 126 sleep(1); 127 ret = waitpid(pid, &status, WUNTRACED | WNOHANG); 128 if (ret < 0) 129 err(1, "waitpid"); 130 if (ret == 0) 131 continue; 132 if (!WIFSTOPPED(status)) 133 errx(1, "unexpected status %d after PT_DETACH", 134 status); 135 printf("stopped on signal %d after detach\n", 136 WSTOPSIG(status)); 137 e = 1; 138 break; 139 } 140 } 141 kill(pid, SIGINT); 142 143 return (e); 144} 145EOF 146 147mycc -o ptrace10 -Wall -Wextra -O2 -g ptrace10.c -lpthread || exit 1 148rm ptrace10.c 149 150./ptrace10 151s=$? 152if [ $s -ne 0 ]; then 153 ps -lxH | grep -v grep | egrep "UID|ptrace10" 154 while pgrep -q ptrace10; do 155 pkill -9 ptrace10 156 done 157fi 158wait 159 160rm -f ptrace10 161exit $s 162