1#!/bin/sh 2 3# 4# Copyright (c) 2015 EMC Corp. 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# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Fork bomb memory leak test scenario. 30# https://en.wikipedia.org/wiki/Fork_bomb 31 32# OO memory seen: 33# https://people.freebsd.org/~pho/stress/log/forkbomb.txt 34# Fixed by r289026. 35 36. ../default.cfg 37[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 38 39dir=/tmp 40odir=`pwd` 41cd $dir 42sed '1,/^EOF/d' < $odir/$0 > $dir/forkbomb.c 43mycc -o forkbomb -Wall -Wextra -O0 -g forkbomb.c || exit 1 44rm -f forkbomb.c 45cd $odir 46 47mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 48mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 49mdconfig -a -t swap -s 512m -u $mdstart || exit 1 50newfs $newfs_flags md$mdstart > /dev/null 51mount /dev/md$mdstart $mntpoint 52 53su $testuser -c /tmp/forkbomb 54 55while mount | grep "on $mntpoint " | grep -q /dev/md; do 56 umount $mntpoint || sleep 1 57done 58mdconfig -d -u $mdstart 59rm -rf /tmp/forkbomb 60exit 0 61 62EOF 63#include <sys/param.h> 64#include <sys/mman.h> 65 66#include <machine/atomic.h> 67 68#include <err.h> 69#include <errno.h> 70#include <fcntl.h> 71#include <signal.h> 72#include <stdio.h> 73#include <stdlib.h> 74#include <unistd.h> 75 76volatile u_int *share; 77 78#define R1 1 /* sync start */ 79#define R2 2 /* forks */ 80#define R3 3 /* exits */ 81#define R4 4 /* fork failed */ 82 83//#define DEBUG 84#define MXFAIL 2 85#define MAXPROC 40000 /* Arbitrary cap */ 86#define PARALLEL 200 87 88void 89test(void) 90{ 91 int r; 92 93 alarm(1200); 94 atomic_add_int(&share[R1], 1); 95 while (share[R1] != PARALLEL) 96 usleep(100); 97 atomic_add_int(&share[R2], 1); 98 99 for (;;) { 100 if (share[R2] >= MAXPROC || share[R4] > MXFAIL) 101 break; 102 atomic_add_int(&share[R2], 1); 103 if ((r = fork()) == -1) { 104 atomic_add_int(&share[R4], 1); 105 atomic_add_int(&share[R2], -1); 106 usleep(arc4random() % 100000); 107 break; 108 } 109 } 110 111 atomic_add_int(&share[R3], 1); 112 _exit(0); 113} 114 115int 116main(void) 117{ 118 struct sigaction sa; 119 size_t len; 120 int i; 121 122 alarm(1200); 123 len = PAGE_SIZE; 124 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 125 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 126 err(1, "mmap"); 127 128 sa.sa_handler = SIG_IGN; 129 sigemptyset(&sa.sa_mask); 130 sa.sa_flags = 0; 131 if (sigaction(SIGCHLD, &sa, 0) == -1) 132 err(1, "sigaction"); 133 134 for (i = 0; i < PARALLEL; i++) { 135 if (fork() == 0) 136 test(); 137 } 138 139 while (share[R2] == 0 || share[R3] < share[R2]) 140 sleep(1); 141 142#if defined(DEBUG) 143 fprintf(stderr, "MAXPROC: %d. forks: %u / exits: %u / fails: %u\n", 144 MAXPROC, share[R2], share[R3], share[R4]); 145#endif 146 147 return (0); 148} 149