xref: /freebsd/tools/test/stress2/misc/getrandom2.sh (revision 8a272653d9fbd9fc37691c9aad6a05089b4ecb4d)
1*8a272653SPeter Holm#!/bin/sh
2*8a272653SPeter Holm
3*8a272653SPeter Holm#
4*8a272653SPeter Holm# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5*8a272653SPeter Holm#
6*8a272653SPeter Holm# Copyright (c) 2020 Peter Holm
7*8a272653SPeter Holm#
8*8a272653SPeter Holm# Redistribution and use in source and binary forms, with or without
9*8a272653SPeter Holm# modification, are permitted provided that the following conditions
10*8a272653SPeter Holm# are met:
11*8a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright
12*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer.
13*8a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
14*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer in the
15*8a272653SPeter Holm#    documentation and/or other materials provided with the distribution.
16*8a272653SPeter Holm#
17*8a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*8a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*8a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*8a272653SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*8a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*8a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*8a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*8a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*8a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*8a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*8a272653SPeter Holm# SUCH DAMAGE.
28*8a272653SPeter Holm#
29*8a272653SPeter Holm
30*8a272653SPeter Holm# getrandom(2) DoS scenario.
31*8a272653SPeter Holm
32*8a272653SPeter Holm# panic: pmap_growkernel: no memory to grow kernel
33*8a272653SPeter Holm# cpuid = 8
34*8a272653SPeter Holm# time = 1582102582
35*8a272653SPeter Holm# KDB: stack backtrace:
36*8a272653SPeter Holm# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe03e6992450
37*8a272653SPeter Holm# vpanic() at vpanic+0x185/frame 0xfffffe03e69924b0
38*8a272653SPeter Holm# panic() at panic+0x43/frame 0xfffffe03e6992510
39*8a272653SPeter Holm# pmap_growkernel() at pmap_growkernel+0x2d4/frame 0xfffffe03e6992550
40*8a272653SPeter Holm# vm_map_insert() at vm_map_insert+0x296/frame 0xfffffe03e69925f0
41*8a272653SPeter Holm# vm_map_find() at vm_map_find+0x617/frame 0xfffffe03e69926d0
42*8a272653SPeter Holm# kva_import() at kva_import+0x3c/frame 0xfffffe03e6992710
43*8a272653SPeter Holm# vmem_try_fetch() at vmem_try_fetch+0xde/frame 0xfffffe03e6992760
44*8a272653SPeter Holm# vmem_xalloc() at vmem_xalloc+0x4bb/frame 0xfffffe03e69927e0
45*8a272653SPeter Holm# kva_import_domain() at kva_import_domain+0x36/frame 0xfffffe03e6992810
46*8a272653SPeter Holm# vmem_try_fetch() at vmem_try_fetch+0xde/frame 0xfffffe03e6992860
47*8a272653SPeter Holm# vmem_xalloc() at vmem_xalloc+0x4bb/frame 0xfffffe03e69928e0
48*8a272653SPeter Holm# vmem_alloc() at vmem_alloc+0x8a/frame 0xfffffe03e6992930
49*8a272653SPeter Holm# kmem_malloc_domainset() at kmem_malloc_domainset+0x92/frame 0xfffffe03e69929a0
50*8a272653SPeter Holm# malloc() at malloc+0x162/frame 0xfffffe03e69929f0
51*8a272653SPeter Holm# read_random_uio() at read_random_uio+0xa5/frame 0xfffffe03e6992a40
52*8a272653SPeter Holm# sys_getrandom() at sys_getrandom+0x7b/frame 0xfffffe03e6992ac0
53*8a272653SPeter Holm# amd64_syscall() at amd64_syscall+0x183/frame 0xfffffe03e6992bf0
54*8a272653SPeter Holm# fast_syscall_common() at fast_syscall_common+0x101/frame 0xfffffe03e6992bf0
55*8a272653SPeter Holm# --- syscall (563, FreeBSD ELF64, sys_getrandom), rip = 0x80041899a, rsp = 0x7ffffffc3cb8, rbp = 0x7ffffffc3cd0 ---
56*8a272653SPeter Holm# KDB: enter: panic
57*8a272653SPeter Holm# [ thread pid 12095 tid 186584 ]
58*8a272653SPeter Holm# Stopped at      kdb_enter+0x37: movq    $0,0x1084916(%rip)
59*8a272653SPeter Holm# db> x/s version
60*8a272653SPeter Holm# version:        FreeBSD 13.0-CURRENT #0 r358094: Wed Feb 19 06:25:16 CET 2020\012    pho@t2.osted.lan:/usr/src/sys/amd64/compile/PHO\012
61*8a272653SPeter Holm# db>
62*8a272653SPeter Holm
63*8a272653SPeter Holm. ../default.cfg
64*8a272653SPeter Holm
65*8a272653SPeter Holmdir=/tmp
66*8a272653SPeter Holmodir=`pwd`
67*8a272653SPeter Holmcd $dir
68*8a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/getrandom2.c
69*8a272653SPeter Holmmycc -o getrandom2 -Wall -Wextra -O0 -g getrandom2.c || exit 1
70*8a272653SPeter Holmrm -f getrandom2.c
71*8a272653SPeter Holmcd $odir
72*8a272653SPeter Holm
73*8a272653SPeter Holmcd /tmp
74*8a272653SPeter Holm$dir/getrandom2
75*8a272653SPeter Holms=$?
76*8a272653SPeter Holm[ -f getrandom2.core -a $s -eq 0 ] &&
77*8a272653SPeter Holm    { ls -l getrandom2.core; s=1; }
78*8a272653SPeter Holmcd $odir
79*8a272653SPeter Holm
80*8a272653SPeter Holmrm -rf $dir/getrandom2
81*8a272653SPeter Holmexit $s
82*8a272653SPeter Holm
83*8a272653SPeter HolmEOF
84*8a272653SPeter Holm#include <sys/param.h>
85*8a272653SPeter Holm#include <sys/mman.h>
86*8a272653SPeter Holm#include <sys/random.h>
87*8a272653SPeter Holm#include <sys/resource.h>
88*8a272653SPeter Holm#include <sys/stat.h>
89*8a272653SPeter Holm#include <sys/sysctl.h>
90*8a272653SPeter Holm#include <sys/wait.h>
91*8a272653SPeter Holm
92*8a272653SPeter Holm#include <err.h>
93*8a272653SPeter Holm#include <errno.h>
94*8a272653SPeter Holm#include <fcntl.h>
95*8a272653SPeter Holm#include <stdatomic.h>
96*8a272653SPeter Holm#include <stdio.h>
97*8a272653SPeter Holm#include <stdlib.h>
98*8a272653SPeter Holm#include <time.h>
99*8a272653SPeter Holm#include <unistd.h>
100*8a272653SPeter Holm
101*8a272653SPeter Holmstatic size_t mx;
102*8a272653SPeter Holmstatic _Atomic(int) *share;
103*8a272653SPeter Holmstatic int parallel;
104*8a272653SPeter Holmstatic char *bp;
105*8a272653SPeter Holm
106*8a272653SPeter Holm#define PARALLEL 40000   /* Arbitrary cap */
107*8a272653SPeter Holm#define SYNC 0
108*8a272653SPeter Holm
109*8a272653SPeter Holmstatic void
110*8a272653SPeter Holmtest(void)
111*8a272653SPeter Holm{
112*8a272653SPeter Holm	int i;
113*8a272653SPeter Holm
114*8a272653SPeter Holm	alarm(180);
115*8a272653SPeter Holm	(void)atomic_fetch_add(&share[SYNC], 1);
116*8a272653SPeter Holm	while (atomic_load(&share[SYNC]) != parallel)
117*8a272653SPeter Holm		usleep(200000);
118*8a272653SPeter Holm	for (i = 0; i < 10; i++)
119*8a272653SPeter Holm		getrandom(bp, mx, 0);
120*8a272653SPeter Holm//		close(66);
121*8a272653SPeter Holm
122*8a272653SPeter Holm	_exit(0);
123*8a272653SPeter Holm}
124*8a272653SPeter Holm
125*8a272653SPeter Holmint
126*8a272653SPeter Holmmain(void)
127*8a272653SPeter Holm{
128*8a272653SPeter Holm	pid_t *pids;
129*8a272653SPeter Holm	struct rlimit rlp;
130*8a272653SPeter Holm	size_t len;
131*8a272653SPeter Holm        size_t f, vsz;
132*8a272653SPeter Holm        u_int pages;
133*8a272653SPeter Holm	int e, i, status;
134*8a272653SPeter Holm
135*8a272653SPeter Holm	e = 0;
136*8a272653SPeter Holm	len = PAGE_SIZE;
137*8a272653SPeter Holm	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
138*8a272653SPeter Holm	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
139*8a272653SPeter Holm		err(1, "mmap");
140*8a272653SPeter Holm
141*8a272653SPeter Holm	if (getrlimit(RLIMIT_NPROC, &rlp) < 0)
142*8a272653SPeter Holm		err(1, "getrlimit");
143*8a272653SPeter Holm	parallel = rlp.rlim_cur / 100 * 80;
144*8a272653SPeter Holm	if (parallel > PARALLEL)
145*8a272653SPeter Holm		parallel = PARALLEL;
146*8a272653SPeter Holm	pids = calloc(parallel, sizeof(pid_t));
147*8a272653SPeter Holm
148*8a272653SPeter Holm        vsz = sizeof(pages);
149*8a272653SPeter Holm        if (sysctlbyname("vm.stats.vm.v_free_count", &pages, &vsz, NULL, 0) != 0)
150*8a272653SPeter Holm                err(1, "sysctl(vm.stats.vm.v_free_count)");
151*8a272653SPeter Holm	f = pages;
152*8a272653SPeter Holm	f *= PAGE_SIZE;
153*8a272653SPeter Holm
154*8a272653SPeter Holm	if (getrlimit(RLIMIT_DATA, &rlp) < 0)
155*8a272653SPeter Holm		err(1,"getrlimit");
156*8a272653SPeter Holm	mx = rlp.rlim_cur;
157*8a272653SPeter Holm	if (mx > f / parallel)
158*8a272653SPeter Holm		mx = f / parallel;
159*8a272653SPeter Holm	if ((bp = mmap(NULL, mx, PROT_READ | PROT_WRITE, MAP_ANON, -1,
160*8a272653SPeter Holm	    0)) == MAP_FAILED)
161*8a272653SPeter Holm		err(1, "mmap");
162*8a272653SPeter Holm	for (;;) {
163*8a272653SPeter Holm		if (getrandom(bp, mx, 0) != -1)
164*8a272653SPeter Holm			break;
165*8a272653SPeter Holm		mx = mx / 2;
166*8a272653SPeter Holm	}
167*8a272653SPeter Holm	printf("Max getrandom() buffer size is %zu, %d threads\n", mx,
168*8a272653SPeter Holm	    parallel);
169*8a272653SPeter Holm	for (i = 0; i < parallel; i++) {
170*8a272653SPeter Holm		if ((pids[i] = fork()) == 0)
171*8a272653SPeter Holm			test();
172*8a272653SPeter Holm		if (pids[i] == -1)
173*8a272653SPeter Holm			err(1, "fork()");
174*8a272653SPeter Holm	}
175*8a272653SPeter Holm	for (i = 0; i < parallel; i++) {
176*8a272653SPeter Holm		if (waitpid(pids[i], &status, 0) == -1)
177*8a272653SPeter Holm			err(1, "waitpid(%d)", pids[i]);
178*8a272653SPeter Holm		if (status != 0) {
179*8a272653SPeter Holm			if (WIFSIGNALED(status))
180*8a272653SPeter Holm				fprintf(stderr,
181*8a272653SPeter Holm				    "pid %d exit signal %d\n",
182*8a272653SPeter Holm				    pids[i], WTERMSIG(status));
183*8a272653SPeter Holm		}
184*8a272653SPeter Holm		e += status == 0 ? 0 : 1;
185*8a272653SPeter Holm	}
186*8a272653SPeter Holm
187*8a272653SPeter Holm	return (e);
188*8a272653SPeter Holm}
189