1*4d0adee4SPeter Holm#!/bin/sh 2*4d0adee4SPeter Holm 3*4d0adee4SPeter Holm# 4*4d0adee4SPeter Holm# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5*4d0adee4SPeter Holm# 6*4d0adee4SPeter Holm# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> 7*4d0adee4SPeter Holm# 8*4d0adee4SPeter Holm# Redistribution and use in source and binary forms, with or without 9*4d0adee4SPeter Holm# modification, are permitted provided that the following conditions 10*4d0adee4SPeter Holm# are met: 11*4d0adee4SPeter Holm# 1. Redistributions of source code must retain the above copyright 12*4d0adee4SPeter Holm# notice, this list of conditions and the following disclaimer. 13*4d0adee4SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright 14*4d0adee4SPeter Holm# notice, this list of conditions and the following disclaimer in the 15*4d0adee4SPeter Holm# documentation and/or other materials provided with the distribution. 16*4d0adee4SPeter Holm# 17*4d0adee4SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*4d0adee4SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*4d0adee4SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*4d0adee4SPeter Holm# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*4d0adee4SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*4d0adee4SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*4d0adee4SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*4d0adee4SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*4d0adee4SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*4d0adee4SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*4d0adee4SPeter Holm# SUCH DAMAGE. 28*4d0adee4SPeter Holm# 29*4d0adee4SPeter Holm 30*4d0adee4SPeter Holm# procctl(2) fuzz test 31*4d0adee4SPeter Holm 32*4d0adee4SPeter Holmprog=`basename ${0%.sh}` 33*4d0adee4SPeter Holmcat > /tmp/$prog.c <<EOF 34*4d0adee4SPeter Holm#include <sys/param.h> 35*4d0adee4SPeter Holm#include <sys/mman.h> 36*4d0adee4SPeter Holm#include <sys/procctl.h> 37*4d0adee4SPeter Holm 38*4d0adee4SPeter Holm#include <err.h> 39*4d0adee4SPeter Holm#include <pthread.h> 40*4d0adee4SPeter Holm#include <signal.h> 41*4d0adee4SPeter Holm#include <stdio.h> 42*4d0adee4SPeter Holm#include <stdlib.h> 43*4d0adee4SPeter Holm#include <time.h> 44*4d0adee4SPeter Holm#include <unistd.h> 45*4d0adee4SPeter Holm 46*4d0adee4SPeter Holmstatic volatile u_int *share; 47*4d0adee4SPeter Holm 48*4d0adee4SPeter Holm#define PARALLEL 25 49*4d0adee4SPeter Holm#define RUNTIME 120 50*4d0adee4SPeter Holm 51*4d0adee4SPeter Holmstatic long 52*4d0adee4SPeter Holmrandom_long(long mi, long ma) 53*4d0adee4SPeter Holm{ 54*4d0adee4SPeter Holm return (arc4random() % (ma - mi + 1) + mi); 55*4d0adee4SPeter Holm} 56*4d0adee4SPeter Holm 57*4d0adee4SPeter Holmstatic void 58*4d0adee4SPeter Holmflip(void *ap, size_t len) 59*4d0adee4SPeter Holm{ 60*4d0adee4SPeter Holm unsigned char *cp; 61*4d0adee4SPeter Holm int byte; 62*4d0adee4SPeter Holm unsigned char bit, buf, mask, old __unused; 63*4d0adee4SPeter Holm 64*4d0adee4SPeter Holm cp = (unsigned char *)ap; 65*4d0adee4SPeter Holm byte = random_long(0, len); 66*4d0adee4SPeter Holm bit = random_long(0,7); 67*4d0adee4SPeter Holm mask = ~(1 << bit); 68*4d0adee4SPeter Holm buf = cp[byte]; 69*4d0adee4SPeter Holm old = cp[byte]; 70*4d0adee4SPeter Holm buf = (buf & mask) | (~buf & ~mask); 71*4d0adee4SPeter Holm cp[byte] = buf; 72*4d0adee4SPeter Holm} 73*4d0adee4SPeter Holm 74*4d0adee4SPeter Holmstatic void * 75*4d0adee4SPeter Holmtr(void *arg __unused) 76*4d0adee4SPeter Holm{ 77*4d0adee4SPeter Holm usleep(arc4random() % 400); 78*4d0adee4SPeter Holm 79*4d0adee4SPeter Holm return (NULL); 80*4d0adee4SPeter Holm} 81*4d0adee4SPeter Holm 82*4d0adee4SPeter Holmstatic void 83*4d0adee4SPeter Holmtest(void) { 84*4d0adee4SPeter Holm pthread_t thr; 85*4d0adee4SPeter Holm struct procctl_reaper_kill killemall; 86*4d0adee4SPeter Holm pid_t pid; 87*4d0adee4SPeter Holm time_t start; 88*4d0adee4SPeter Holm int data[20], e, n, m; 89*4d0adee4SPeter Holm 90*4d0adee4SPeter Holm n = m = 0; 91*4d0adee4SPeter Holm if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1) 92*4d0adee4SPeter Holm err(EXIT_FAILURE, "Fail to acquire the reaper"); 93*4d0adee4SPeter Holm start = time(NULL); 94*4d0adee4SPeter Holm while (time(NULL) - start < RUNTIME) { 95*4d0adee4SPeter Holm m++; 96*4d0adee4SPeter Holm share[0] = 0; 97*4d0adee4SPeter Holm if ((pid = fork()) == 0) { 98*4d0adee4SPeter Holm e = pthread_create(&thr, NULL, tr, NULL); 99*4d0adee4SPeter Holm if (e != 0) 100*4d0adee4SPeter Holm errc(1, e, "pthread_create"); 101*4d0adee4SPeter Holm share[0] = 1; 102*4d0adee4SPeter Holm setproctitle("child"); 103*4d0adee4SPeter Holm usleep(arc4random() % 200); 104*4d0adee4SPeter Holm if (arc4random() % 100 < 2) 105*4d0adee4SPeter Holm raise(SIGSEGV); 106*4d0adee4SPeter Holm _exit(0); 107*4d0adee4SPeter Holm } 108*4d0adee4SPeter Holm arc4random_buf(data, sizeof(data)); 109*4d0adee4SPeter Holm while (share[0] == 0) 110*4d0adee4SPeter Holm usleep(10); 111*4d0adee4SPeter Holm killemall.rk_sig = SIGTERM; 112*4d0adee4SPeter Holm killemall.rk_flags = 0; 113*4d0adee4SPeter Holm flip(&killemall, sizeof(killemall)); 114*4d0adee4SPeter Holm if (procctl(P_PID, getpid(), PROC_REAP_KILL, 115*4d0adee4SPeter Holm &killemall) == 0) 116*4d0adee4SPeter Holm n++; 117*4d0adee4SPeter Holm if (waitpid(pid, NULL, 0) != pid) 118*4d0adee4SPeter Holm err(1, "waitpid()"); 119*4d0adee4SPeter Holm } 120*4d0adee4SPeter Holm#if defined(DEBUG) 121*4d0adee4SPeter Holm fprintf(stderr, "n = %d out of %d\n", n, m); 122*4d0adee4SPeter Holm#endif 123*4d0adee4SPeter Holm _exit(0); 124*4d0adee4SPeter Holm} 125*4d0adee4SPeter Holm 126*4d0adee4SPeter Holmint 127*4d0adee4SPeter Holmmain(void) { 128*4d0adee4SPeter Holm pid_t pids[PARALLEL]; 129*4d0adee4SPeter Holm size_t len; 130*4d0adee4SPeter Holm int i; 131*4d0adee4SPeter Holm 132*4d0adee4SPeter Holm len = PAGE_SIZE; 133*4d0adee4SPeter Holm if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 134*4d0adee4SPeter Holm MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 135*4d0adee4SPeter Holm err(1, "mmap"); 136*4d0adee4SPeter Holm for (i = 0; i < PARALLEL; i++) { 137*4d0adee4SPeter Holm if ((pids[i] = fork()) == 0) 138*4d0adee4SPeter Holm test(); 139*4d0adee4SPeter Holm } 140*4d0adee4SPeter Holm for (i = 0; i < PARALLEL; i++) 141*4d0adee4SPeter Holm if (waitpid(pids[i], NULL, 0) != pids[i]) 142*4d0adee4SPeter Holm err(1, "waitpid()"); 143*4d0adee4SPeter Holm} 144*4d0adee4SPeter HolmEOF 145*4d0adee4SPeter Holmcc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 146*4d0adee4SPeter Holmrm /tmp/$prog.c 147*4d0adee4SPeter Holm 148*4d0adee4SPeter Holmhere=`pwd` 149*4d0adee4SPeter Holmcd /tmp 150*4d0adee4SPeter Holm./$prog; s=$? 151*4d0adee4SPeter Holmcd $here 152*4d0adee4SPeter Holm 153*4d0adee4SPeter Holmrm -f /tmp/$prog /tmp/$prog.core 154*4d0adee4SPeter Holmexit $s 155