From owner-svn-src-user@freebsd.org Tue Apr 24 07:40:52 2018 Return-Path: Delivered-To: svn-src-user@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 86E23FBEDF9 for ; Tue, 24 Apr 2018 07:40:52 +0000 (UTC) (envelope-from pho@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 3C3DD75B93; Tue, 24 Apr 2018 07:40:52 +0000 (UTC) (envelope-from pho@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 1D1B410436; Tue, 24 Apr 2018 07:40:52 +0000 (UTC) (envelope-from pho@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w3O7eqOM041832; Tue, 24 Apr 2018 07:40:52 GMT (envelope-from pho@FreeBSD.org) Received: (from pho@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w3O7epeR041829; Tue, 24 Apr 2018 07:40:51 GMT (envelope-from pho@FreeBSD.org) Message-Id: <201804240740.w3O7epeR041829@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: pho set sender to pho@FreeBSD.org using -f From: Peter Holm Date: Tue, 24 Apr 2018 07:40:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r332915 - user/pho/stress2/misc X-SVN-Group: user X-SVN-Commit-Author: pho X-SVN-Commit-Paths: user/pho/stress2/misc X-SVN-Commit-Revision: 332915 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Apr 2018 07:40:52 -0000 Author: pho Date: Tue Apr 24 07:40:51 2018 New Revision: 332915 URL: https://svnweb.freebsd.org/changeset/base/332915 Log: Added some old test which have not yet caught any problems. Sponsored by: Dell EMC Isilon Added: user/pho/stress2/misc/exlock.sh (contents, props changed) user/pho/stress2/misc/jumbo.sh (contents, props changed) user/pho/stress2/misc/lstat.sh (contents, props changed) user/pho/stress2/misc/maxproc.sh (contents, props changed) Added: user/pho/stress2/misc/exlock.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/pho/stress2/misc/exlock.sh Tue Apr 24 07:40:51 2018 (r332915) @@ -0,0 +1,124 @@ +#!/bin/sh + +# +# Copyright (c) 2014 EMC Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +# Simple O_EXLOCK test scenario. + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > exlock.c +mycc -o exlock -Wall -Wextra exlock.c || exit 1 +rm -f exlock.c +cd $here + +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 2g -u $mdstart || exit 1 +bsdlabel -w md$mdstart auto +newfs $newfs_flags md${mdstart}$part > /dev/null +mount /dev/md${mdstart}$part $mntpoint +chmod 777 $mntpoint + +su $testuser -c "cd $mntpoint; /tmp/exlock" + +while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 +done +mdconfig -d -u $mdstart +rm -f /tmp/exlock +exit +EOF +#include +#include + +#include +#include +#include +#include + +char buf[128]; + +#define PARALLEL 3 + +static void +tst(char *file, int n) +{ + int fd, i; + + for (i = 0; i < (int)sizeof(buf); i++) + buf[i] = '0' + n; + + for (i = 0; i < 1024 * 1024; i++) { + if ((fd = open(file, O_RDWR | O_CREAT | O_APPEND | O_EXLOCK, + 0644)) == -1) + err(1, "open(%s)", file); + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "write"); + close(fd); + } + + _exit(0); +} +static void +test(void) +{ + int i; + char file[80]; + + snprintf(file, sizeof(file), "f06%d", getpid()); + + for (i = 0; i < 3; i++) + if (fork() == 0) + tst(file, i); + for (i = 0; i < 3; i++) + wait(NULL); + + unlink(file); + + _exit(0); +} + +int +main(void) +{ + int i; + + for (i = 0; i < PARALLEL; i++) + if (fork() == 0) + test(); + for (i = 0; i < PARALLEL; i++) + wait(NULL); + + return (0); +} Added: user/pho/stress2/misc/jumbo.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/pho/stress2/misc/jumbo.sh Tue Apr 24 07:40:51 2018 (r332915) @@ -0,0 +1,224 @@ +#!/bin/sh + +# +# Copyright (c) 2014 EMC Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# Stress the jumbo mbuf allocation +# vmstat -z | sed -n '1p;/jumbo/p' + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > jumbo.c +mycc -o jumbo -Wall -Wextra -O2 jumbo.c || exit 1 +rm -f jumbo.c + +log=/tmp/mbuf.log +nb=80 +host=localhost +[ $# -eq 1 ] && host=$1 +( + for i in `jot $nb 0`; do + /tmp/jumbo $((12345 + $i)) & + done + sleep 30 + for i in `jot $nb 0`; do + /tmp/jumbo $host $((12345 + $i)) & + done + for i in `jot $nb 0`; do + wait + done +) > $log 2>&1 + +rm -f /tmp/jumbo +grep -q FAIL $log && { cat $log 1>&2; exit 1; } +rm -f $log +exit 0 +EOF +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MX (1024 * 1024) +#define RETRIES 5 +#define TIMEOUT 1200 + +char *host; +int loops, port, server; + +void +ahandler(int s __unused) +{ + if (server) + fprintf(stderr, "FAIL Server timed out after %d loops.\n", + loops); + else + fprintf(stderr, "FAIL Client timed out after %d loops.\n", + loops); + _exit(0); +} + + +static void +reader(void) { + socklen_t len; + struct sockaddr_in inetaddr, inetpeer; + int *buf, i, n, msgsock, on, tcpsock; + + setproctitle("reader - init"); + on = 1; + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + signal(SIGALRM, ahandler); + alarm(TIMEOUT); + if (bind(tcpsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) + err(1, "bind(), %s:%d", __FILE__, __LINE__); + + if (listen(tcpsock, 5) < 0) + err(1, "listen(), %s:%d", __FILE__, __LINE__); + + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) + err(1, "accept(), %s:%d", __FILE__, __LINE__); + + if ((buf = malloc(MX)) == NULL) + err(1, "malloc(%d), %s:%d", MX, __FILE__, __LINE__); + setproctitle("reader"); + for (i = 4096; i < MX; i += 1024) { + alarm(TIMEOUT); + if ((n = recvfrom(msgsock, buf, i, MSG_WAITALL, NULL, + NULL)) < 0) { + if (errno == EAGAIN) + continue; + err(1, "read(), %s:%d", __FILE__, __LINE__); + } + if (n == 0) + break; + + loops++; + } + close(msgsock); + _exit(0); +} + +static void +writer(void) { + struct sockaddr_in inetaddr; + struct hostent *hostent; + int i, on, r, tcpsock; + char *line; + + setproctitle("writer - init"); + signal(SIGALRM, ahandler); + alarm(TIMEOUT); + on = 1; + for (i = 0; i < RETRIES; i++) { + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + if ((hostent = gethostbyname (host)) == NULL) + err(1, "gethostbyname(%s)", host); + bzero((char *) &inetaddr, sizeof(inetaddr)); + memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + r = connect(tcpsock, (struct sockaddr *) &inetaddr, + sizeof(inetaddr)); + if (r == 0) + break; + sleep(1); + close(tcpsock); + } + if (r < 0) + err(1, "connect(%s, %d), %s:%d", host, port, __FILE__, + __LINE__); + + setproctitle("writer"); + if ((line = malloc(MX)) == NULL) + err(1, "malloc(%d), %s:%d", MX, __FILE__, __LINE__); + alarm(TIMEOUT); + for (i = sysconf(_SC_PAGESIZE); i < MX; i += 1024) { + if (write(tcpsock, line, i) < 0) + err(1, "socket write(). %s:%d", __FILE__, __LINE__); + loops++; + } + close(tcpsock); + + return; +} + +int +main(int argc, char **argv) +{ + + if (argc == 2) { + server = 1; + port = atoi(argv[1]); + reader(); + } else if (argc == 3) { + host = argv[1]; + port = atoi(argv[2]); + writer(); + } else + errx(1, "Usage: %s {} \n", argv[0]); + + return (0); +} Added: user/pho/stress2/misc/lstat.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/pho/stress2/misc/lstat.sh Tue Apr 24 07:40:51 2018 (r332915) @@ -0,0 +1,238 @@ +#!/bin/sh + +# +# Copyright (c) 2016 EMC Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# Hunt for; +# Bug 204764 - Filesystem deadlock, process in vodead state +# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=204764 +# No problem seen. + +. ../default.cfg + +dir=/tmp +odir=`pwd` +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/lstat.c +mycc -o lstat -Wall -Wextra -O0 -g lstat.c || exit 1 +rm -f lstat.c +cd $odir + +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 1g -u $mdstart || exit 1 +bsdlabel -w md$mdstart auto +newfs -n -b 4096 -f 512 -i 1024 md${mdstart}$part > /dev/null +mount -o async /dev/md${mdstart}$part $mntpoint || exit 1 + +path=$mntpoint/a/b/c +mkdir -p $path + +$dir/lstat $path + +while mount | grep "on $mntpoint " | grep -q /dev/md; do + umount $mntpoint || sleep 1 +done +mdconfig -d -u $mdstart +rm -rf $dir/lstat $wdir/lstat.tmp.* +exit + +EOF +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile u_int *dirs, *share; +static char *arg; + +#define R1 0 +#define R2 1 + +#define MXDIRS 3000 +#define PARALLEL 2 +#define RUNTIME 600 +#define SLPTIME 400 + +static void +tfts(int idx) +{ + FTS *fts; + FTSENT *p; + struct stat sb; + int ftsoptions; + char *args[2]; + + if (idx != 0) + _exit(0); + + ftsoptions = FTS_PHYSICAL; + args[0] = arg, + args[1] = 0; + + setproctitle("fts"); + while (share[R2] == 0) { + if ((fts = fts_open(args, ftsoptions, NULL)) == NULL) + err(1, "fts_open"); + + while ((p = fts_read(fts)) != NULL) { + lstat(fts->fts_path, &sb); + if (share[R2] == 1) + break; + } + + if (fts_close(fts) == -1) + err(1, "fts_close()"); + } + + _exit(0); +} + +static int +test(int idx) +{ + struct stat sb; + pid_t fpid, pd, pid; + size_t len; + int i, n, r; + char dir[128], path[128]; + + atomic_add_int(&share[R1], 1); + while (share[R1] != PARALLEL) + ; + + len = PAGE_SIZE; + if ((dirs = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + if ((fpid = fork()) == 0) + tfts(idx); + + pid = getpid(); + snprintf(dir, sizeof(dir), "%s/dir.%d", arg, pid); + if (mkdir(dir, 0777) == -1) + err(1, "mkdir(%s)", dir); + if (chdir(dir) == -1) + err(1, "chdir(%s)", dir); + if ((pd = fork()) == 0) { + setproctitle("mkdir"); + i = 0; + while (share[R2] == 0) { + snprintf(path, sizeof(path), "%s/d.%d.%d", arg, pid, + i); + n = 0; + while (dirs[0] > MXDIRS && share[R2] == 0) + usleep(SLPTIME); + while ((r = mkdir(path, 0777)) == -1) { + if (errno != EMLINK) + err(1, "mkdir(%s) @ %d", path, + __LINE__); + usleep(SLPTIME); + if (share[2] == 1) + break; + } + if (r == 0) { + atomic_add_int(&dirs[0], 1); + i++; + } + } + + _exit(0); + } + + i = 0; + setproctitle("rmdir"); + while (dirs[0] > 0 || share[R2] == 0) { + n = 0; + if (dirs[0] < MXDIRS / 2) + usleep(SLPTIME); + snprintf(path, sizeof(path), "%s/d.%d.%d", arg, pid, i); + while (lstat(path, &sb) == -1 && share[R2] == 0) { + usleep(SLPTIME); + } + if (rmdir(path) == -1) { + if (errno != ENOENT) + err(1, "rmdir(%s)", path); + } else { + atomic_add_int(&dirs[0], -1); + i++; + } + } + waitpid(pd, NULL, 0); + waitpid(fpid, NULL, 0); + + chdir(".."); + if ((rmdir(dir)) == -1) + err(1, "unlink(%s)", dir); + + _exit(0); +} + +int +main(int argc, char *argv[]) +{ + size_t len; + int e, i, pids[PARALLEL], status; + + if (argc != 2) + errx(1, "Usage: %s ", argv[0]); + arg = argv[1]; + + e = 0; + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + share[R1] = 0; + for (i = 0; i < PARALLEL; i++) { + if ((pids[i] = fork()) == 0) + test(i); + } + sleep(RUNTIME); + share[R2] = 1; + for (i = 0; i < PARALLEL; i++) { + waitpid(pids[i], &status, 0); + e += status == 0 ? 0 : 1; + } + + return (e); +} Added: user/pho/stress2/misc/maxproc.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/pho/stress2/misc/maxproc.sh Tue Apr 24 07:40:51 2018 (r332915) @@ -0,0 +1,169 @@ +#!/bin/sh + +# +# Copyright (c) 2014 EMC Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +# Test that a non root user can at most have maxproc - 10 processes. + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/$0 > maxproc.c +mycc -o maxproc -Wall -Wextra maxproc.c -lkvm || exit 1 +rm -f maxproc.c +[ `sysctl -n kern.maxproc` -gt 37028 ] && exit 0 # Excessive run time +cd $here + +/tmp/maxproc + +rm -f /tmp/maxproc +exit +EOF +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + NL_NPROCS, + NL_MAXPROC, + NL_MARKER +}; + +static struct { + int order; + const char *name; +} namelist[] = { + { NL_NPROCS, "_nprocs" }, + { NL_MAXPROC, "_maxproc" }, + { NL_MARKER, "" }, +}; + +#define NNAMES (sizeof(namelist) / sizeof(*namelist)) +#define MULTIUSERFUZZ 5 + +static struct nlist nl[NNAMES]; + +static void +t2(void) +{ + pid_t p; + + for (;;) { + if ((p = fork()) == 0) { + sleep(2); + _exit(0); + } + if (p == -1) + break; + } +} + +static void +t1(int priv) +{ + pid_t p; + struct passwd *pw; + + if ((p = fork()) == 0) { + if ((pw = getpwnam("nobody")) == NULL) + err(1, "no such user: nobody"); + + if (priv == 0) { + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"nobody\""); + } + endpwent(); + + t2(); + _exit(0); + } + waitpid(p, NULL, 0); +} + +int +getprocs(void) +{ + kvm_t *kd; + int i, nprocs, maxproc; + char buf[_POSIX2_LINE_MAX]; + char *nlistf, *memf; + + nlistf = memf = NULL; + for (i = 0; i < (int)NNAMES; i++) + nl[namelist[i].order].n_name = strdup(namelist[i].name); + + if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) + errx(1, "kvm_openfile(%s, %s): %s", nlistf, memf, buf); + if (kvm_nlist(kd, nl) == -1) + errx(1, "kvm_nlist: %s", kvm_geterr(kd)); + if (kvm_read(kd, nl[NL_NPROCS].n_value, &nprocs, + sizeof(nprocs)) != sizeof(nprocs)) + errx(1, "kvm_read(): %s", kvm_geterr(kd)); + if (kvm_read(kd, nl[NL_MAXPROC].n_value, &maxproc, + sizeof(maxproc)) != sizeof(maxproc)) + errx(1, "kvm_read(): %s", kvm_geterr(kd)); + kvm_close(kd); + + return (maxproc - nprocs - 1); +} + +int +main(void) +{ + int i, n; + + alarm(1200); + n = getprocs(); + for (i = 0; i < n / 10 * 8; i++) { + if (fork() == 0) { + sleep(2); + _exit(0); + } + } + + t1(0); + + n = getprocs(); + if (n < 10 - MULTIUSERFUZZ) + errx(1, "FAIL: nprocs = %d\n", n); + + return (0); +}