xref: /freebsd/tools/test/stress2/misc/ptrace11.sh (revision e0c4386e)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6# Copyright (c) 2019 Dell EMC Isilon
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# markj@ wrote:
31# I found a kernel bug that caused init to consume 100% CPU if the
32# following steps occurred:
33# - process A forks and creates process B
34# - process C ptrace attaches to process B
35# - process A exits
36# - process C detaches from process B
37# - process B exits
38#
39# Process B gets reparented to init, and the bug causes wait() to return
40# an error each time init attempts to reap process B.
41
42. ../default.cfg
43cd /tmp
44cat > ptrace11.c <<EOF
45#include <sys/types.h>
46#include <sys/mman.h>
47#include <sys/ptrace.h>
48#include <sys/wait.h>
49
50#include <machine/atomic.h>
51
52#include <err.h>
53#include <pthread.h>
54#include <signal.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <unistd.h>
58
59static volatile u_int *share;
60#define SYNC 0
61
62int
63main(void)
64{
65	pid_t pida, pidb;
66	size_t len;
67	int status;
68
69	setproctitle("A");
70	len = PAGE_SIZE;
71	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
72	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
73		err(1, "mmap");
74
75	pida = fork();
76	if (pida < 0)
77		err(1, "fork");
78	if (pida == 0) {
79		setproctitle("B");
80		while (share[SYNC] != 2)
81			usleep(10);
82		_exit(0);
83	} else {
84		sleep(1);
85		pidb = fork();
86		if (pidb < 0)
87			err(1, "fork");
88		if (pidb == 0) {
89			setproctitle("C");
90			if (ptrace(PT_ATTACH, pida, NULL, 0) != 0)
91				err(1, "ptrace(PT_ATTACH)");
92			wait4(pida, &status, 0, NULL);
93			share[SYNC] = 1; /* A to exit */
94			usleep(1000);
95			if (ptrace(PT_DETACH, pida, NULL, 0) != 0)
96				err(1, "ptrace(PT_DETACH)");
97			share[SYNC] = 2; /* B to exit */
98			_exit(0);
99		} else {
100			while (share[SYNC] != 1)
101				usleep(10);
102			_exit(0);
103		}
104	}
105
106	return (0);
107}
108EOF
109
110mycc -o ptrace11 -Wall -Wextra -O2 -g ptrace11.c || exit 1
111rm ptrace11.c
112old=`ps auxwwl | grep -v grep | grep "<defunct>" | wc -l`
113
114./ptrace11
115
116new=`ps auxwwl | grep -v grep | grep "<defunct>" | wc -l`
117if [ $old -ne $new ]; then
118	ps auxwwl | sed -n '1p;/<defunct>/p'
119	echo FAIL
120	s=1
121fi
122
123rm -f ptrace11
124exit $s
125