xref: /freebsd/tools/test/stress2/misc/sigreturn3.sh (revision 4d846d26)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org>
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# Fatal trap -4186856: UNKNOWN while in kernel mode
31# cpuid = 1; apic id = 01
32# error code              = 0xfbafcf8c
33# instruction pointer     = 0x79e4:0x4
34# stack pointer           = 0x28:0xffc0aff0
35# frame pointer           = 0x28:0x204620d4
36# code segment            = base 0x0, limit 0x0, type 0x0
37#                         = DPL 0, pres 0, def32 0, gran 0
38# processor eflags        = trace trap,  at 0x3b/frame 0xffc0340c
39# KDB: enter: panic
40# [ thread pid 15631 tid 114622 ]
41# Stopped at      kdb_enter+0x34: movl    $0,kdb_why
42# db>
43
44[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
45prog=sigreturn3
46
47cat > /tmp/$prog.c <<EOF
48#include <sys/types.h>
49#include <sys/resource.h>
50#include <sys/stat.h>
51#include <sys/syscall.h>
52#include <sys/wait.h>
53
54#include <err.h>
55#include <errno.h>
56#include <fcntl.h>
57#include <libutil.h>
58#include <pthread.h>
59#include <pwd.h>
60#include <signal.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65
66#define N 4096
67#define RUNTIME 120
68#define THREADS 1
69
70static uint32_t r[N];
71
72static void
73hand(int i __unused) {	/* handler */
74	exit(1);
75}
76
77static void *
78churn(void *arg __unused)
79{
80	time_t start;
81
82	pthread_set_name_np(pthread_self(), __func__);
83	start = time(NULL);
84	while (time(NULL) - start < 10) {
85		arc4random_buf(r, sizeof(r));
86		usleep(100);
87	}
88	return(NULL);
89}
90
91static void *
92calls(void *arg __unused)
93{
94	time_t start;
95	int i;
96
97	start = time(NULL);
98	for (i = 0; time(NULL) - start < 10; i++) {
99		arc4random_buf(r, sizeof(r));
100		alarm(1);
101		syscall(SYS_sigreturn, r);
102	}
103
104	return (NULL);
105}
106
107int
108main(int argc, char **argv)
109{
110	struct passwd *pw;
111	struct rlimit limit;
112	pid_t pid;
113	pthread_t rp, cp[THREADS];
114	time_t start;
115	int e, j;
116
117	if ((pw = getpwnam("nobody")) == NULL)
118		err(1, "failed to resolve nobody");
119
120	if (getenv("USE_ROOT") && argc == 2)
121		fprintf(stderr, "Running syscall4 as root for %s.\n",
122				argv[1]);
123	else {
124		if (setgroups(1, &pw->pw_gid) ||
125		    setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
126		    seteuid(pw->pw_uid) || setuid(pw->pw_uid))
127			err(1, "Can't drop privileges to \"nobody\"");
128		endpwent();
129	}
130
131	limit.rlim_cur = limit.rlim_max = 1000;
132#if defined(RLIMIT_NPTS)
133	if (setrlimit(RLIMIT_NPTS, &limit) < 0)
134		err(1, "setrlimit");
135#endif
136
137	signal(SIGALRM, hand);
138	signal(SIGILL,  hand);
139	signal(SIGFPE,  hand);
140	signal(SIGSEGV, hand);
141	signal(SIGBUS,  hand);
142	signal(SIGURG,  hand);
143	signal(SIGSYS,  hand);
144	signal(SIGTRAP, hand);
145
146	if (daemon(1, 1) == -1)
147		err(1, "daemon()");
148
149	start = time(NULL);
150	while ((time(NULL) - start) < RUNTIME) {
151		if ((pid = fork()) == 0) {
152			if ((e = pthread_create(&rp, NULL, churn, NULL)) != 0)
153			errc(1, e, "pthread_create");
154			for (j = 0; j < THREADS; j++)
155				if ((e = pthread_create(&cp[j], NULL, calls,
156				    NULL)) != 0)
157					errc(1, e, "pthread_create");
158			for (j = 0; j < THREADS; j++)
159				pthread_join(cp[j], NULL);
160
161			if ((e = pthread_kill(rp, SIGINT)) != 0)
162				errc(1, e, "pthread_kill");
163			if ((e = pthread_join(rp, NULL)) != 0)
164				errc(1, e, "pthread_join");
165			_exit(0);
166		}
167		waitpid(pid, NULL, 0);
168	}
169
170	return (0);
171}
172EOF
173
174cd /tmp
175cc -o $prog -Wall -Wextra -O0 $prog.c -lpthread || exit 1
176start=`date +%s`
177while [ $((`date +%s` - start)) -lt 300 ]; do
178	./$prog > /dev/null 2>&1
179	date +%T
180done
181rm -f /tmp/$prog /tmp/$ptog.c /tmp/$prog.core
182exit 0
183