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