-# $OpenBSD: Makefile,v 1.10 2020/12/17 00:51:11 bluhm Exp $
+# $OpenBSD: Makefile,v 1.11 2021/09/02 12:40:44 mbuhl Exp $
# Copyright (c) 2019 Moritz Buhl <openbsd@moritzbuhl.de>
# Copyright (c) 2019 Alexander Bluhm <bluhm@openbsd.org>
PROGS += t_access
PROGS += t_bind
PROGS += t_chroot t_clock_gettime
+PROGS += t_connect
PROGS += t_dup
+PROGS += t_fork
PROGS += t_fsync
PROGS += t_getgroups t_getitimer t_getlogin t_getpid t_getrusage
PROGS += t_getsid t_getsockname t_gettimeofday
+PROGS += t_kevent
PROGS += t_kill
PROGS += t_link t_listen
-PROGS += t_mkdir t_mkfifo t_mknod t_mlock t_mmap
-PROGS += t_msgctl t_msgget t_msgrcv t_msgsnd t_msync
-PROGS += t_pipe t_pipe2 t_poll t_ptrace
+PROGS += t_minherit
+PROGS += t_mkdir
+PROGS += t_mkfifo
+PROGS += t_mknod
+PROGS += t_mlock
+PROGS += t_mmap
+PROGS += t_msgctl
+PROGS += t_msgget
+PROGS += t_msgrcv
+PROGS += t_msgsnd
+PROGS += t_msync
+PROGS += t_pipe
+PROGS += t_pipe2
+PROGS += t_poll
+PROGS += t_ppoll
+PROGS += t_ptrace
PROGS += t_revoke
-PROGS += t_select t_sendrecv t_setuid t_socketpair t_sigaction t_stat
+PROGS += t_select
+PROGS += t_sendrecv
+PROGS += t_setrlimit
+PROGS += t_setuid
+PROGS += t_sigaction
+PROGS += t_sigaltstack
+PROGS += t_socketpair
+PROGS += t_stat
PROGS += t_syscall
PROGS += t_truncate
PROGS += t_umask t_unlink
+PROGS += t_wait_noproc
+PROGS += t_wait_noproc_wnohang
PROGS += t_write
# failing tests
Reimplement ATF with many hacks to adjust the tests as little as possible.
Tests passing without source file adjustments:
-t_access t_getpid t_link t_msgsnd t_sigaction
-t_bind t_getsid t_listen t_msync t_socketpair
-t_getgroups t_getsockname t_mkdir t_pipe t_truncate
-t_getitimer t_gettimeofday t_mkfifo t_sendrecv t_umask
-t_getlogin t_kill t_msgctl t_setuid t_write
+t_access t_getsockname t_msgctl t_sigaltstack
+t_bind t_gettimeofday t_msgsnd t_socketpair
+t_conect t_kill t_msync t_truncate
+t_getgroups t_link t_pipe t_umask
+t_getitimer t_listen t_ppoll t_write
+t_getlogin t_minherit t_sendrecv
+t_getpid t_mkdir t_setuid
+t_getsid t_mkfifo t_sigaction
Tests passing after adjustments:
-t_chroot - fchroot is not implemented
-t_clock_gettime - requires sysctlbyname
-t_dup - OpenBSD dup3 is similar to Linux dup3
-t_fsync - replace mkstemp
-t_getrusage - no expected fail, PR kern/30115 is NetBSD, work more
-t_mknod - remove tests for unsupported file types
-t_msgget - remove msgget_limit test
-t_poll - remove pollts_* tests
-t_ptrace - change EPERM -> EINVAL for PT_ATTACH of a parent
-t_revoke - remove basic tests, revoke only on ttys supported
-t_select - remove sigset_t struct as it is int on OpenBSD
+t_chroot - fchroot is not implemented
+t_clock_gettime - requires sysctlbyname
+t_dup - OpenBSD dup3 is similar to Linux dup3
+t_fork - add reallocarr function, remove clone(2) tests
+t_fsync - replace mkstemp
+t_getrusage - no expected fail, PR kern/30115 is NetBSD, work more
+t_kevent - no EVFILT_USER, DRVCTLDEV, passing kqueue forbidden
+t_mknod - remove tests for unsupported file types
+t_msgget - remove msgget_limit test
+t_poll - remove pollts_* tests
+t_ptrace - change EPERM -> EINVAL for PT_ATTACH of a parent
+t_revoke - remove basic tests, revoke only on ttys supported
+t_select - remove sigset_t struct as it is int on OpenBSD
+t_setrlimit - remove unsupported resource parameters and lwp
+t_syscall - add __syscall prototype
+t_wait_noproc - waitid and wait6 are not implemented
+t_wait_noproc_wnohang - waitid and wait6 are not implemented
Failing tests:
t_mlock - wrong errno, succeeds where not expected, POSIX imprecise
t_msgrcv - msgrcv(id, &r, 3 - 1, 0x41, 004000) != -1
t_pipe2 - closefrom(4) == -1, remove F_GETNOSIGPIPE and nosigpipe test
t_stat - invalid GID with doas
-t_syscall - SIGSEGV
t_unlink - wrong errno according to POSIX
+t_vfork - !(((status) & 0177) == 0) evaluated to false, SIGSTOP wrong
Excluded tests:
t_clock_nanosleep - not available
t_clone - not available
-t_connect -
-t_fork -
-t_getcontext -
-t_issetugid -
-t_kevent -
+t_futex_ops - no lwp
+t_futex_robust - no lwp
+t_getcontext - not available, removed in POSIX.1-2008
+t_getrandom - not available
+t_issetugid - works as iplemented
t_lwp_create - not available
t_lwp_ctl - not available
t_mincore - removed
-t_minherit -
-t_mprotect -
+t_mprotect - no exec_prot_support and no return_one in libc
t_nanosleep - not available
-t_posix_fadvise -
-t_posix_fallocate -
+t_pollts - not available
+t_posix_fadvise - optional POSIX Advisory Information
+t_posix_fallocate - optional POSIX Advisory Information
+t_ptrace_sigchld -
t_ptrace_wait -
t_ptrace_wait3 -
t_ptrace_wait4 -
t_ptrace_wait6 - not implemented
t_ptrace_waitid -
t_ptrace_waitpid -
-t_recvmmsg -
-t_sendmmsg -
-t_setrlimit -
-t_sigqueue -
-t_sigtimedwait -
-t_swapcontext -
-t_timer_create -
-t_ucontext -
-t_vfork -
-t_wait -
-t_wait_noproc -
-t_wait_noproc_wnohang -
+t_recvmmsg - not implemented, not POSIX
+t_sendmmsg - not implemented, not POSIX
+t_sigqueue - not implemented, added in POSIX.1-2004
+t_sigtimedwait - not implemented, added in POSIX.1-2004
+t_swapcontext - not available, removed in POSIX.1-2008
+t_timer_create - not implemented, added in POSIX.1-2004
+t_ucontext - not available, removed in POSIX.1-2008
+t_wait - wait6 is not available, not POSIX
-/* $OpenBSD: atf-c.h,v 1.2 2021/06/09 19:42:46 mortimer Exp $ */
+/* $OpenBSD: atf-c.h,v 1.3 2021/09/02 12:40:44 mbuhl Exp $ */
/*
* Copyright (c) 2019 Moritz Buhl <openbsd@moritzbuhl.de>
*
#define ATF_CHECK ATF_REQUIRE
#define ATF_CHECK_MSG ATF_REQUIRE_MSG
#define ATF_CHECK_EQ ATF_REQUIRE_EQ
+#define ATF_CHECK_ERRNO ATF_REQUIRE_ERRNO
#define ATF_CHECK_STREQ ATF_REQUIRE_STREQ
#define atf_req(exp, err, msg, ...) \
+/* $OpenBSD: h_macros.h,v 1.2 2021/09/02 12:40:44 mbuhl Exp $ */
/* $NetBSD: h_macros.h,v 1.13 2016/08/20 15:49:08 christos Exp $ */
/*-
-/* $OpenBSD: macros.h,v 1.2 2020/01/30 08:22:30 mpi Exp $ */
+/* $OpenBSD: macros.h,v 1.3 2021/09/02 12:40:44 mbuhl Exp $ */
/* Public domain - Moritz Buhl */
#include <sys/param.h>
return sysctl(mib, miblen, oldp, oldlenp, newp, newlen);
}
+/* t_connect.c */
+#define IPPORT_RESERVEDMAX 1023
+
+/* t_fork.c */
+#define kinfo_proc2 kinfo_proc
+#define KERN_PROC2 KERN_PROC
+#define reallocarr(pp, n, s) ((*pp = reallocarray(*pp, n, s)), *pp == NULL)
+
/* t_mlock.c */
#define MAP_WIRED __MAP_NOREPLACE
/* t_write.c */
#define _PATH_DEVZERO "/dev/zero"
+
+/* t_wait_noproc.c */
+#define ___STRING(x) #x
+#define __BIT(n) (1 << (n))
+/* $OpenBSD: t_clock_gettime.c,v 1.2 2021/09/02 12:40:44 mbuhl Exp $ */
/* $NetBSD: t_clock_gettime.c,v 1.3 2017/01/13 21:30:41 christos Exp $ */
/*-
--- /dev/null
+/* $OpenBSD: t_connect.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_connect.c,v 1.3 2017/01/13 20:09:48 christos Exp $ */
+/*
+ * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/socket.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "atf-c.h"
+
+ATF_TC(connect_low_port);
+ATF_TC_HEAD(connect_low_port, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that low-port allocation "
+ "works");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(connect_low_port, tc)
+{
+ struct sockaddr_in sin, sinlist;
+ int sd, val, slist;
+ socklen_t slen;
+
+ slist = socket(AF_INET, SOCK_STREAM, 0);
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+
+ ATF_REQUIRE(sd > 0);
+ ATF_REQUIRE(slist > 0);
+
+ /* bind listening socket */
+ memset(&sinlist, 0, sizeof(sinlist));
+ sinlist.sin_family = AF_INET;
+ sinlist.sin_port = htons(31522);
+ sinlist.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ ATF_REQUIRE_EQ(bind(slist,
+ (struct sockaddr *)&sinlist, sizeof(sinlist)), 0);
+ ATF_REQUIRE_EQ(listen(slist, 1), 0);
+
+ val = IP_PORTRANGE_LOW;
+ if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, &val,
+ sizeof(val)) == -1)
+ atf_tc_fail("setsockopt failed: %s", strerror(errno));
+
+ memset(&sin, 0, sizeof(sin));
+
+ sin.sin_port = htons(31522);
+ sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+ sin.sin_family = AF_INET;
+
+ if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ int serrno = errno;
+ atf_tc_fail("connect failed: %s%s",
+ strerror(serrno),
+ serrno != EACCES ? "" :
+ " (see http://mail-index.netbsd.org/"
+ "source-changes/2007/12/16/0011.html)");
+ }
+
+ slen = sizeof(sin);
+ ATF_REQUIRE_EQ(getsockname(sd, (struct sockaddr *)&sin, &slen), 0);
+ ATF_REQUIRE_EQ(slen, sizeof(sin));
+ ATF_REQUIRE(ntohs(sin.sin_port) <= IPPORT_RESERVEDMAX);
+
+ close(sd);
+ close(slist);
+}
+
+ATF_TC(connect_foreign_family);
+ATF_TC_HEAD(connect_foreign_family, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that connecting a socket "
+ "with a different address family fails");
+}
+ATF_TC_BODY(connect_foreign_family, tc)
+{
+ struct sockaddr_in addr;
+
+ /* addr.sin_family = AF_UNSPEC = 0 */
+ memset(&addr, 0, sizeof(addr));
+
+ /*
+ * it is not necessary to initialize sin_{addr,port} since
+ * those structure members shall not be accessed if connect
+ * fails correctly.
+ */
+
+ int sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+ ATF_REQUIRE(sock != -1);
+
+ ATF_REQUIRE(-1 == connect(sock, (struct sockaddr *)&addr, sizeof(addr)));
+ ATF_REQUIRE(EAFNOSUPPORT == errno);
+
+ close(sock);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, connect_low_port);
+ ATF_TP_ADD_TC(tp, connect_foreign_family);
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_fork.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_fork.c,v 1.4 2019/04/06 15:41:54 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2018, 2019 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/cdefs.h>
+__COPYRIGHT("@(#) Copyright (c) 2018, 2019\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_fork.c,v 1.4 2019/04/06 15:41:54 kamil Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "atf-c.h"
+
+#ifdef VFORK
+#define FORK vfork
+#else
+#define FORK fork
+#endif
+
+/*
+ * A child process cannot call atf functions and expect them to magically
+ * work like in the parent.
+ * The printf(3) messaging from a child will not work out of the box as well
+ * without estabilishing a communication protocol with its parent. To not
+ * overcomplicate the tests - do not log from a child and use err(3)/errx(3)
+ * wrapped with ASSERT_EQ()/ASSERT_NEQ() as that is guaranteed to work.
+ */
+#define ASSERT_EQ(x, y) \
+do { \
+ uintmax_t vx = (x); \
+ uintmax_t vy = (y); \
+ int ret = vx == vy; \
+ if (!ret) \
+ errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
+ "%s(%ju) == %s(%ju)", __FILE__, __LINE__, __func__, \
+ #x, vx, #y, vy); \
+} while (/*CONSTCOND*/0)
+
+#define ASSERT_NEQ(x, y) \
+do { \
+ uintmax_t vx = (x); \
+ uintmax_t vy = (y); \
+ int ret = vx != vy; \
+ if (!ret) \
+ errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
+ "%s(%ju) != %s(%ju)", __FILE__, __LINE__, __func__, \
+ #x, vx, #y, vy); \
+} while (/*CONSTCOND*/0)
+
+static pid_t
+await_stopped_child(pid_t process)
+{
+ struct kinfo_proc2 *p = NULL;
+ size_t i, len;
+ pid_t child = -1;
+
+ int name[] = {
+ [0] = CTL_KERN,
+ [1] = KERN_PROC2,
+ [2] = KERN_PROC_ALL,
+ [3] = 0,
+ [4] = sizeof(struct kinfo_proc2),
+ [5] = 0
+ };
+
+ const size_t namelen = __arraycount(name);
+
+ /* Await the process becoming a zombie */
+ while(1) {
+ name[5] = 0;
+
+ ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0);
+
+ ASSERT_EQ(reallocarr(&p, len, sizeof(struct kinfo_proc2)), 0);
+
+ name[5] = len;
+
+ ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0);
+
+ for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) {
+ if (p[i].p_pid == getpid())
+ continue;
+ if (p[i].p_ppid != process)
+ continue;
+#ifndef __OpenBSD__
+ if (p[i].p_stat != LSSTOP)
+ continue;
+#endif
+ child = p[i].p_pid;
+ break;
+ }
+
+ if (child != -1)
+ break;
+
+ ASSERT_EQ(usleep(1000), 0);
+ }
+
+ /* Free the buffer */
+ ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0);
+
+ return child;
+}
+
+static void
+raise_raw(int sig)
+{
+ int rv, status;
+ pid_t child, parent, watcher, wpid;
+ int expect_core = (sig == SIGABRT) ? 1 : 0;
+
+ /*
+ * Spawn a dedicated thread to watch for a stopped child and emit
+ * the SIGKILL signal to it.
+ *
+ * This is required in vfork(2)ing parent and optional in fork(2).
+ *
+ * vfork(2) might clobber watcher, this means that it's safer and
+ * simpler to reparent this process to initproc and forget about it.
+ */
+ if (sig == SIGSTOP
+#ifndef VFORK
+ || (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+#endif
+ ) {
+
+ parent = getpid();
+
+ watcher = fork();
+ ATF_REQUIRE(watcher != 1);
+ if (watcher == 0) {
+ /* Double fork(2) trick to reparent to initproc */
+ watcher = fork();
+ ASSERT_NEQ(watcher, -1);
+ if (watcher != 0)
+ _exit(0);
+
+ child = await_stopped_child(parent);
+
+ errno = 0;
+ rv = kill(child, SIGKILL);
+ ASSERT_EQ(rv, 0);
+ ASSERT_EQ(errno, 0);
+
+ /* This exit value will be collected by initproc */
+ _exit(0);
+ }
+
+ wpid = waitpid(watcher, &status, 0);
+
+ ATF_REQUIRE_EQ(wpid, watcher);
+
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(!WIFCONTINUED(status));
+ ATF_REQUIRE(!WIFSIGNALED(status));
+ ATF_REQUIRE(!WIFSTOPPED(status));
+ ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
+ }
+
+ child = FORK();
+ ATF_REQUIRE(child != 1);
+ if (child == 0) {
+ rv = raise(sig);
+ ASSERT_EQ(rv, 0);
+ _exit(0);
+ }
+ wpid = waitpid(child, &status, 0);
+
+ ATF_REQUIRE_EQ(wpid, child);
+
+ switch (sig) {
+ case SIGKILL:
+ case SIGABRT:
+ case SIGHUP:
+ ATF_REQUIRE(!WIFEXITED(status));
+ ATF_REQUIRE(!WIFCONTINUED(status));
+ ATF_REQUIRE(WIFSIGNALED(status));
+ ATF_REQUIRE(!WIFSTOPPED(status));
+ ATF_REQUIRE_EQ(WTERMSIG(status), sig);
+ ATF_REQUIRE_EQ(!!WCOREDUMP(status), expect_core);
+ break;
+#ifdef VFORK
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+#endif
+ case SIGCONT:
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(!WIFCONTINUED(status));
+ ATF_REQUIRE(!WIFSIGNALED(status));
+ ATF_REQUIRE(!WIFSTOPPED(status));
+ ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
+ break;
+#ifndef VFORK
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+#endif
+ case SIGSTOP:
+ ATF_REQUIRE(!WIFEXITED(status));
+ ATF_REQUIRE(!WIFCONTINUED(status));
+ ATF_REQUIRE(WIFSIGNALED(status));
+ ATF_REQUIRE(!WIFSTOPPED(status));
+ ATF_REQUIRE_EQ(WTERMSIG(status), SIGKILL);
+ ATF_REQUIRE_EQ(!!WCOREDUMP(status), 0);
+ }
+}
+
+#define RAISE(test, sig) \
+ATF_TC(test); \
+ATF_TC_HEAD(test, tc) \
+{ \
+ \
+ atf_tc_set_md_var(tc, "descr", \
+ "raise " #sig " in a child"); \
+} \
+ \
+ATF_TC_BODY(test, tc) \
+{ \
+ \
+ raise_raw(sig); \
+}
+
+RAISE(raise1, SIGKILL) /* non-maskable */
+RAISE(raise2, SIGSTOP) /* non-maskable */
+RAISE(raise3, SIGTSTP) /* ignored in vfork(2) */
+RAISE(raise4, SIGTTIN) /* ignored in vfork(2) */
+RAISE(raise5, SIGTTOU) /* ignored in vfork(2) */
+RAISE(raise6, SIGABRT) /* regular abort trap */
+RAISE(raise7, SIGHUP) /* hangup */
+RAISE(raise8, SIGCONT) /* continued? */
+
+/// ----------------------------------------------------------------------------
+
+static int
+clone_func(void *arg __unused)
+{
+
+ return 0;
+}
+
+static void
+nested_raw(const char *fn, volatile int flags)
+{
+ int status;
+ pid_t child, child2, wpid;
+ const size_t stack_size = 1024 * 1024;
+ void *stack, *stack_base;
+
+ stack = malloc(stack_size);
+ ATF_REQUIRE(stack != NULL);
+
+#ifdef __MACHINE_STACK_GROWS_UP
+ stack_base = stack;
+#else
+ stack_base = (char *)stack + stack_size;
+#endif
+
+ flags |= SIGCHLD;
+
+ child = FORK();
+ ATF_REQUIRE(child != 1);
+ if (child == 0) {
+ if (strcmp(fn, "fork") == 0)
+ child2 = fork();
+ else if (strcmp(fn, "vfork") == 0)
+ child2 = vfork();
+#ifndef __OpenBSD__
+ else if (strcmp(fn, "clone") == 0)
+ child2 = __clone(clone_func, stack_base, flags, NULL);
+#endif
+ else
+ __unreachable();
+
+ ASSERT_NEQ(child2, -1);
+
+ if ((strcmp(fn, "fork") == 0) || (strcmp(fn, "vfork") == 0)) {
+ if (child2 == 0)
+ _exit(0);
+ }
+
+ wpid = waitpid(child2, &status, 0);
+ ASSERT_EQ(child2, wpid);
+ ASSERT_EQ(!!WIFEXITED(status), true);
+ ASSERT_EQ(!!WIFCONTINUED(status), false);
+ ASSERT_EQ(!!WIFSIGNALED(status), false);
+ ASSERT_EQ(!!WIFSTOPPED(status), false);
+ ASSERT_EQ(WEXITSTATUS(status), 0);
+
+ _exit(0);
+ }
+ wpid = waitpid(child, &status, 0);
+
+ ATF_REQUIRE_EQ(wpid, child);
+ ATF_REQUIRE_EQ(!!WIFEXITED(status), true);
+ ATF_REQUIRE_EQ(!!WIFCONTINUED(status), false);
+ ATF_REQUIRE_EQ(!!WIFSIGNALED(status), false);
+ ATF_REQUIRE_EQ(!!WIFSTOPPED(status), false);
+ ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
+}
+
+#define NESTED(test, fn, flags) \
+ATF_TC(test); \
+ATF_TC_HEAD(test, tc) \
+{ \
+ \
+ atf_tc_set_md_var(tc, "descr", \
+ "Test nested " #fn " in a child"); \
+} \
+ \
+ATF_TC_BODY(test, tc) \
+{ \
+ \
+ nested_raw(#fn, flags); \
+}
+
+NESTED(nested_fork, fork, 0)
+NESTED(nested_vfork, vfork, 0)
+#ifndef __OpenBSD__
+NESTED(nested_clone, clone, 0)
+NESTED(nested_clone_vm, clone, CLONE_VM)
+NESTED(nested_clone_fs, clone, CLONE_FS)
+NESTED(nested_clone_files, clone, CLONE_FILES)
+//NESTED(nested_clone_sighand, clone, CLONE_SIGHAND) // XXX
+NESTED(nested_clone_vfork, clone, CLONE_VFORK)
+#endif
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, raise1);
+ ATF_TP_ADD_TC(tp, raise2);
+ ATF_TP_ADD_TC(tp, raise3);
+ ATF_TP_ADD_TC(tp, raise4);
+ ATF_TP_ADD_TC(tp, raise5);
+ ATF_TP_ADD_TC(tp, raise6);
+ ATF_TP_ADD_TC(tp, raise7);
+ ATF_TP_ADD_TC(tp, raise8);
+
+ ATF_TP_ADD_TC(tp, nested_fork);
+ ATF_TP_ADD_TC(tp, nested_vfork);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, nested_clone);
+ ATF_TP_ADD_TC(tp, nested_clone_vm);
+ ATF_TP_ADD_TC(tp, nested_clone_fs);
+ ATF_TP_ADD_TC(tp, nested_clone_files);
+// ATF_TP_ADD_TC(tp, nested_clone_sighand); // XXX
+ ATF_TP_ADD_TC(tp, nested_clone_vfork);
+#endif
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_kevent.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_kevent.c,v 1.9 2020/10/31 01:08:32 christos Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundatiom
+ * by Christos Zoulas.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_kevent.c,v 1.9 2020/10/31 01:08:32 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/event.h>
+
+#include "atf-c.h"
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#ifndef __OpenBSD__
+#include <sys/drvctlio.h>
+#endif
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+ATF_TC(kevent_zerotimer);
+ATF_TC_HEAD(kevent_zerotimer, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that kevent with a 0 timer "
+ "does not crash the system (PR lib/45618)");
+}
+
+ATF_TC_BODY(kevent_zerotimer, tc)
+{
+ struct kevent ev;
+ int kq;
+
+ ATF_REQUIRE((kq = kqueue()) != -1);
+ EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0);
+ ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) != -1);
+ ATF_REQUIRE(kevent(kq, NULL, 0, &ev, 1, NULL) == 1);
+}
+
+ATF_TC(kqueue_desc_passing);
+ATF_TC_HEAD(kqueue_desc_passing, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that passing a kqueue to "
+ "another process does not crash the kernel (PR 46463)");
+}
+
+ATF_TC_BODY(kqueue_desc_passing, tc)
+{
+ pid_t child;
+ int s[2], storage, status, kq;
+ struct cmsghdr *msg;
+ struct iovec iov;
+ struct msghdr m;
+ struct kevent ev;
+
+ ATF_REQUIRE((kq = kqueue()) != -1);
+
+ // atf_tc_skip("crashes kernel (PR kern/46463)");
+
+ ATF_REQUIRE(socketpair(AF_LOCAL, SOCK_STREAM, 0, s) != -1);
+ msg = malloc(CMSG_SPACE(sizeof(int)));
+ m.msg_iov = &iov;
+ m.msg_iovlen = 1;
+ m.msg_name = NULL;
+ m.msg_namelen = 0;
+ m.msg_control = msg;
+ m.msg_controllen = CMSG_SPACE(sizeof(int));
+
+ child = fork();
+ if (child == 0) {
+#ifdef __OpenBSD__
+ sleep(1);
+ exit(0);
+#endif
+ close(s[0]);
+
+ iov.iov_base = &storage;
+ iov.iov_len = sizeof(int);
+ m.msg_iov = &iov;
+ m.msg_iovlen = 1;
+
+ if (recvmsg(s[1], &m, 0) == -1)
+ err(1, "child: could not recvmsg");
+
+ kq = *(int *)CMSG_DATA(msg);
+ printf("child (pid %d): received kq fd %d\n", getpid(), kq);
+ exit(0);
+ }
+
+ close(s[1]);
+
+ iov.iov_base = &storage;
+ iov.iov_len = sizeof(int);
+
+ msg->cmsg_level = SOL_SOCKET;
+ msg->cmsg_type = SCM_RIGHTS;
+ msg->cmsg_len = CMSG_LEN(sizeof(int));
+
+ *(int *)CMSG_DATA(msg) = kq;
+
+ EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0);
+ ATF_CHECK(kevent(kq, &ev, 1, NULL, 0, NULL) != -1);
+
+ printf("parent (pid %d): sending kq fd %d\n", getpid(), kq);
+ if (sendmsg(s[0], &m, 0) == -1) {
+#ifdef __OpenBSD__
+ ATF_REQUIRE_EQ_MSG(errno, EINVAL, "errno is %d", errno);
+#else
+ ATF_REQUIRE_EQ_MSG(errno, EBADF, "errno is %d", errno);
+ atf_tc_skip("PR kern/46523");
+#endif
+ }
+
+ close(kq);
+
+ waitpid(child, &status, 0);
+ ATF_CHECK(WIFEXITED(status) && WEXITSTATUS(status)==0);
+}
+
+#ifndef __OpenBSD__
+ATF_TC(kqueue_unsupported_fd);
+ATF_TC_HEAD(kqueue_unsupported_fd, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that watching an fd whose"
+ " type is not supported does not crash the kernel");
+}
+
+ATF_TC_BODY(kqueue_unsupported_fd, tc)
+{
+ /* mqueue and semaphore use fnullop_kqueue also */
+ int fd, kq;
+ struct kevent ev;
+
+ fd = open(DRVCTLDEV, O_RDONLY);
+ if (fd == -1) {
+ switch (errno) {
+ case ENOENT:
+ case ENXIO:
+ atf_tc_skip("no " DRVCTLDEV " available for testing");
+ break;
+ }
+ }
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE((kq = kqueue()) != -1);
+
+ EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|
+ NOTE_RENAME|NOTE_REVOKE, 0, 0);
+
+ ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == -1);
+ ATF_REQUIRE_ERRNO(EOPNOTSUPP, true);
+
+ (void)close(fd);
+ (void)close(kq);
+}
+
+ATF_TC(kqueue_EVFILT_USER);
+ATF_TC_HEAD(kqueue_EVFILT_USER, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks usability of EVFILT_USER");
+}
+
+ATF_TC_BODY(kqueue_EVFILT_USER, tc)
+{
+ /* mqueue and semaphore use fnullop_kqueue also */
+ int kq;
+ struct kevent ev, rev;
+
+ ATF_REQUIRE((kq = kqueue()) != -1);
+
+ EV_SET(&ev, 666, EVFILT_USER, EV_ADD | EV_ENABLE, 0, 0, 0);
+ ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == 0);
+ EV_SET(&ev, 666, EVFILT_USER, 0, NOTE_FFCOPY | NOTE_TRIGGER | 8, 0, 0);
+ ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == 0);
+ const struct timespec timeout = {
+ .tv_sec = 1,
+ .tv_nsec = 0,
+ };
+
+ ATF_REQUIRE(kevent(kq, NULL, 0, &rev, 1, &timeout) == 1);
+ ATF_REQUIRE(rev.ident == 666);
+ ATF_REQUIRE(rev.filter == EVFILT_USER);
+ ATF_REQUIRE(rev.fflags == 8);
+ (void)close(kq);
+}
+#endif
+
+
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, kevent_zerotimer);
+ ATF_TP_ADD_TC(tp, kqueue_desc_passing);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, kqueue_unsupported_fd);
+ ATF_TP_ADD_TC(tp, kqueue_EVFILT_USER);
+#endif
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_minherit.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "atf-c.h"
+
+static long page;
+
+static void *
+makemap(int v, int f) {
+ void *map = mmap(NULL, page, PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_ANON, -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+ memset(map, v, page);
+ if (f != 666)
+ ATF_REQUIRE(minherit(map, page, f) == 0);
+ else
+ ATF_REQUIRE(minherit(map, page, f) == -1);
+ return map;
+}
+
+ATF_TC(minherit_copy);
+ATF_TC_HEAD(minherit_copy, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_COPY from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_copy, tc)
+{
+ void *map1 = makemap(1, MAP_INHERIT_COPY);
+ void *map2 = makemap(1, MAP_INHERIT_COPY);
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(NULL) != -1);
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ memset(map1, 0, page);
+ exit(0);
+ }
+}
+
+ATF_TC(minherit_share);
+ATF_TC_HEAD(minherit_share, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_SHARE from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_share, tc)
+{
+ void *map1 = makemap(1, MAP_INHERIT_SHARE);
+ void *map2 = makemap(1, MAP_INHERIT_SHARE);
+
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(NULL) != -1);
+ memset(map2, 0, page);
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ memset(map1, 0, page);
+ exit(0);
+ }
+}
+
+static void
+segv(int n) {
+ _exit(n);
+}
+
+ATF_TC(minherit_none);
+ATF_TC_HEAD(minherit_none, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_NONE from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_none, tc)
+{
+ void *map1 = makemap(0, MAP_INHERIT_NONE);
+ int status;
+
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(&status) != -1);
+ ATF_REQUIRE(WEXITSTATUS(status) == SIGSEGV);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(signal(SIGSEGV, segv) != SIG_ERR);
+ memset(map1, 0, page);
+ exit(0);
+ }
+}
+
+ATF_TC(minherit_zero);
+ATF_TC_HEAD(minherit_zero, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_ZERO from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_zero, tc)
+{
+ void *map1 = makemap(1, MAP_INHERIT_ZERO);
+ void *map2 = makemap(0, MAP_INHERIT_SHARE);
+
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(NULL) != -1);
+ memset(map2, 1, page);
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ memset(map1, 2, page);
+ exit(0);
+ }
+}
+
+ATF_TC(minherit_bad);
+ATF_TC_HEAD(minherit_bad, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for bad minherit(2)");
+}
+
+ATF_TC_BODY(minherit_bad, tc)
+{
+ (void)makemap(0, 666);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ ATF_TP_ADD_TC(tp, minherit_copy);
+ ATF_TP_ADD_TC(tp, minherit_share);
+ ATF_TP_ADD_TC(tp, minherit_none);
+ ATF_TP_ADD_TC(tp, minherit_zero);
+ ATF_TP_ADD_TC(tp, minherit_bad);
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_pollts.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_pollts.c,v 1.1 2020/07/17 15:34:17 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2011, 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include "atf-c.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <poll.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+#ifndef POLLTS
+#define POLLTS pollts
+#endif
+
+ATF_TC(basic);
+ATF_TC_HEAD(basic, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr",
+ "Basis functionality test for ppoll(2)/pollts(2)");
+}
+
+ATF_TC_BODY(basic, tc)
+{
+ int fds[2];
+ struct pollfd pfds[2];
+ struct timespec timeout;
+ int ret;
+
+ ATF_REQUIRE_EQ(pipe(fds), 0);
+
+ pfds[0].fd = fds[0];
+ pfds[0].events = POLLIN;
+ pfds[1].fd = fds[1];
+ pfds[1].events = POLLOUT;
+
+ /* Use a timeout of 1 second. */
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+
+ /*
+ * Check that we get a timeout waiting for data on the read end
+ * of our pipe.
+ */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = POLLTS(&pfds[0], 1, &timeout, NULL), 0,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
+
+ /* Check that the write end of the pipe as reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = POLLTS(&pfds[1], 1, &timeout, NULL), 1,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
+ pfds[1].revents);
+
+ /* Check that only the write end of the pipe as reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = POLLTS(pfds, 2, &timeout, NULL), 1,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
+ pfds[1].revents);
+
+ /* Write data to our pipe. */
+ ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
+
+ /* Check that both ends of our pipe are reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = POLLTS(pfds, 2, &timeout, NULL), 2,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
+ pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
+ pfds[1].revents);
+
+ ATF_REQUIRE_EQ(close(fds[0]), 0);
+ ATF_REQUIRE_EQ(close(fds[1]), 0);
+}
+
+ATF_TC(err);
+ATF_TC_HEAD(err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Check errors from ppoll(2)/pollts(2)");
+}
+
+ATF_TC_BODY(err, tc)
+{
+ struct timespec timeout;
+ struct pollfd pfd;
+ int fd = 0;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, POLLTS((void *)-1, 1, &timeout, NULL) == -1);
+
+ timeout.tv_sec = -1;
+ timeout.tv_nsec = -1;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, POLLTS(&pfd, 1, &timeout, NULL) == -1);
+}
+
+ATF_TC(sigmask);
+ATF_TC_HEAD(sigmask, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr",
+ "Check that ppoll(2)/pollts(2) restores the signal mask (PR kern/44986)");
+}
+
+ATF_TC_BODY(sigmask, tc)
+{
+ int fd;
+ struct pollfd pfd;
+ struct timespec timeout;
+ sigset_t mask;
+ int ret;
+
+ fd = open(_PATH_DEVNULL, O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ /* Use a timeout of 1 second. */
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+
+ /* Unblock all signals. */
+ ATF_REQUIRE_EQ(sigfillset(&mask), 0);
+ ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
+
+ /*
+ * Check that ppoll(2)/pollts(2) immediately returns. We block *all*
+ * signals during ppoll(2)/pollts(2).
+ */
+ ATF_REQUIRE_EQ_MSG(ret = POLLTS(&pfd, 1, &timeout, &mask), 1,
+ "got: %d", ret);
+
+ /* Check that signals are now longer blocked. */
+ ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
+ ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
+ "signal mask was changed.");
+
+ ATF_REQUIRE_EQ(close(fd), 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, basic);
+ ATF_TP_ADD_TC(tp, err);
+ ATF_TP_ADD_TC(tp, sigmask);
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_ppoll.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_ppoll.c,v 1.1 2020/07/17 15:34:17 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2011, 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#define POLLTS ppoll
+#include "t_pollts.c"
--- /dev/null
+/* $OpenBSD: t_setrlimit.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_setrlimit.c,v 1.7 2020/10/13 06:58:57 rin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_setrlimit.c,v 1.7 2020/10/13 06:58:57 rin Exp $");
+
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#include "atf-c.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifndef __OpenBSD__
+#include <lwp.h>
+#endif
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef __OpenBSD__
+#include <ucontext.h>
+#endif
+#include <unistd.h>
+
+static void sighandler(int);
+static const char path[] = "setrlimit";
+
+static const int rlimit[] = {
+#ifndef __OpenBSD__
+ RLIMIT_AS,
+#endif
+ RLIMIT_CORE,
+ RLIMIT_CPU,
+ RLIMIT_DATA,
+ RLIMIT_FSIZE,
+ RLIMIT_MEMLOCK,
+ RLIMIT_NOFILE,
+ RLIMIT_NPROC,
+ RLIMIT_RSS,
+#ifndef __OpenBSD__
+ RLIMIT_SBSIZE,
+#endif
+ RLIMIT_STACK
+};
+
+ATF_TC(setrlimit_basic);
+ATF_TC_HEAD(setrlimit_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
+}
+
+ATF_TC_BODY(setrlimit_basic, tc)
+{
+ struct rlimit res;
+ int *buf, lim;
+ size_t i;
+
+ buf = calloc(__arraycount(rlimit), sizeof(int));
+
+ if (buf == NULL)
+ atf_tc_fail("initialization failed");
+
+ for (i = lim = 0; i < __arraycount(rlimit); i++) {
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ if (getrlimit(rlimit[i], &res) != 0)
+ continue;
+
+ if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
+ continue;
+
+ if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
+ continue;
+
+ buf[i] = res.rlim_cur;
+ res.rlim_cur = res.rlim_cur - 1;
+
+ if (setrlimit(rlimit[i], &res) != 0) {
+ lim = rlimit[i];
+ goto out;
+ }
+ }
+
+out:
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ if (buf[i] == 0)
+ continue;
+
+ if (getrlimit(rlimit[i], &res) != 0)
+ continue;
+
+ res.rlim_cur = buf[i];
+
+ (void)setrlimit(rlimit[i], &res);
+ }
+
+ if (lim != 0)
+ atf_tc_fail("failed to set limit (%d)", lim);
+ free(buf);
+}
+
+ATF_TC(setrlimit_current);
+ATF_TC_HEAD(setrlimit_current, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
+}
+
+ATF_TC_BODY(setrlimit_current, tc)
+{
+ struct rlimit res;
+ size_t i;
+
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
+ ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
+ }
+}
+
+ATF_TC(setrlimit_err);
+ATF_TC_HEAD(setrlimit_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions");
+}
+
+ATF_TC_BODY(setrlimit_err, tc)
+{
+ struct rlimit res;
+ size_t i;
+
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ errno = 0;
+
+ ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
+ ATF_REQUIRE(errno == EFAULT);
+ }
+
+ errno = 0;
+
+ ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
+ ATF_REQUIRE(errno == EINVAL);
+}
+
+ATF_TC_WITH_CLEANUP(setrlimit_fsize);
+ATF_TC_HEAD(setrlimit_fsize, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
+}
+
+ATF_TC_BODY(setrlimit_fsize, tc)
+{
+ struct rlimit res;
+ int fd, sta;
+ pid_t pid;
+
+ fd = open(path, O_RDWR | O_CREAT, 0700);
+
+ if (fd < 0)
+ atf_tc_fail("initialization failed");
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ res.rlim_cur = 2;
+ res.rlim_max = 2;
+
+ if (setrlimit(RLIMIT_FSIZE, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (signal(SIGXFSZ, sighandler) == SIG_ERR)
+ _exit(EXIT_FAILURE);
+
+ /*
+ * The third call should generate a SIGXFSZ.
+ */
+ (void)write(fd, "X", 1);
+ (void)write(fd, "X", 1);
+ (void)write(fd, "X", 1);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ (void)close(fd);
+ (void)wait(&sta);
+ (void)unlink(path);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_FSIZE not enforced");
+}
+
+ATF_TC_CLEANUP(setrlimit_fsize, tc)
+{
+ (void)unlink(path);
+}
+
+static void
+sighandler(int signo)
+{
+
+ if (signo != SIGXFSZ)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+}
+
+ATF_TC(setrlimit_memlock);
+ATF_TC_HEAD(setrlimit_memlock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
+}
+
+ATF_TC_BODY(setrlimit_memlock, tc)
+{
+ struct rlimit res;
+ void *buf;
+ long page;
+ pid_t pid;
+ int sta;
+
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ buf = malloc(page);
+ pid = fork();
+
+ if (buf == NULL || pid < 0)
+ atf_tc_fail("initialization failed");
+
+ if (pid == 0) {
+
+ /*
+ * Try to lock a page while
+ * RLIMIT_MEMLOCK is zero.
+ */
+ if (mlock(buf, page) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (munlock(buf, page) != 0)
+ _exit(EXIT_FAILURE);
+
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+
+ if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (mlock(buf, page) != 0)
+ _exit(EXIT_SUCCESS);
+
+ (void)munlock(buf, page);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ free(buf);
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_MEMLOCK not enforced");
+}
+
+ATF_TC(setrlimit_nofile_1);
+ATF_TC_HEAD(setrlimit_nofile_1, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
+}
+
+ATF_TC_BODY(setrlimit_nofile_1, tc)
+{
+ struct rlimit res;
+ int fd, i, rv, sta;
+ pid_t pid;
+
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Close all descriptors, set RLIMIT_NOFILE
+ * to zero, and try to open a random file.
+ * This should fail with EMFILE.
+ */
+ for (i = 0; i < 1024; i++)
+ (void)close(i);
+
+ rv = setrlimit(RLIMIT_NOFILE, &res);
+
+ if (rv != 0)
+ _exit(EXIT_FAILURE);
+
+ errno = 0;
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd >= 0 || errno != EMFILE)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_NOFILE not enforced");
+}
+
+ATF_TC(setrlimit_nofile_2);
+ATF_TC_HEAD(setrlimit_nofile_2, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
+}
+
+ATF_TC_BODY(setrlimit_nofile_2, tc)
+{
+ static const rlim_t lim = 12;
+ struct rlimit res;
+ int fd, i, rv, sta;
+ pid_t pid;
+
+ /*
+ * See that an arbitrary limit on
+ * open files is being enforced.
+ */
+ res.rlim_cur = lim;
+ res.rlim_max = lim;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ for (i = 0; i < 1024; i++)
+ (void)close(i);
+
+ rv = setrlimit(RLIMIT_NOFILE, &res);
+
+ if (rv != 0)
+ _exit(EXIT_FAILURE);
+
+ for (i = 0; i < (int)lim; i++) {
+
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd < 0)
+ _exit(EXIT_FAILURE);
+ }
+
+ /*
+ * After the limit has been reached,
+ * EMFILE should again follow.
+ */
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd >= 0 || errno != EMFILE)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_NOFILE not enforced");
+}
+
+ATF_TC(setrlimit_nproc);
+ATF_TC_HEAD(setrlimit_nproc, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setrlimit_nproc, tc)
+{
+ struct rlimit res;
+ pid_t pid, cpid;
+ int sta;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Set RLIMIT_NPROC to zero and try to fork.
+ */
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+
+ if (setrlimit(RLIMIT_NPROC, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ cpid = fork();
+
+ if (cpid < 0)
+ _exit(EXIT_SUCCESS);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ (void)waitpid(pid, &sta, 0);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_NPROC not enforced");
+}
+
+#ifndef __OpenBSD__
+
+ATF_TC(setrlimit_nthr);
+ATF_TC_HEAD(setrlimit_nthr, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+static void
+func(lwpid_t *id)
+{
+ printf("thread %d\n", *id);
+ fflush(stdout);
+ _lwp_exit();
+}
+
+ATF_TC_BODY(setrlimit_nthr, tc)
+{
+ struct rlimit res;
+ lwpid_t lwpid;
+ ucontext_t c;
+
+ /*
+ * Set RLIMIT_NTHR to zero and try to create a thread.
+ */
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+ ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
+ ATF_REQUIRE(getcontext(&c) == 0);
+ c.uc_link = NULL;
+ sigemptyset(&c.uc_sigmask);
+ c.uc_stack.ss_flags = 0;
+ c.uc_stack.ss_size = 4096;
+ ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
+ makecontext(&c, func, 1, &lwpid);
+ ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
+}
+#endif
+
+ATF_TC(setrlimit_perm);
+ATF_TC_HEAD(setrlimit_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setrlimit_perm, tc)
+{
+ struct rlimit res;
+ size_t i;
+
+ /*
+ * Try to raise the maximum limits as an user.
+ */
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
+
+ if (res.rlim_max == UINT64_MAX) /* Overflow. */
+ continue;
+
+ errno = 0;
+ res.rlim_max = res.rlim_max + 1;
+
+ ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
+ }
+}
+
+ATF_TC(setrlimit_stack);
+ATF_TC_HEAD(setrlimit_stack, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_STACK");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setrlimit_stack, tc)
+{
+ struct rlimit res;
+
+ /* Ensure soft limit is not bigger than hard limit */
+ res.rlim_cur = res.rlim_max = 6 * 1024 * 1024;
+ ATF_REQUIRE(setrlimit(RLIMIT_STACK, &res) == 0);
+ ATF_REQUIRE(getrlimit(RLIMIT_STACK, &res) == 0);
+ ATF_CHECK(res.rlim_cur <= res.rlim_max);
+
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, setrlimit_basic);
+ ATF_TP_ADD_TC(tp, setrlimit_current);
+ ATF_TP_ADD_TC(tp, setrlimit_err);
+ ATF_TP_ADD_TC(tp, setrlimit_fsize);
+ ATF_TP_ADD_TC(tp, setrlimit_memlock);
+ ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
+ ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
+ ATF_TP_ADD_TC(tp, setrlimit_nproc);
+ ATF_TP_ADD_TC(tp, setrlimit_perm);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, setrlimit_nthr);
+#endif
+ ATF_TP_ADD_TC(tp, setrlimit_stack);
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_sigaltstack.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_sigaltstack.c,v 1.2 2020/05/01 21:35:30 christos Exp $ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#include "macros.h"
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_sigaltstack.c,v 1.2 2020/05/01 21:35:30 christos Exp $");
+
+#include <signal.h>
+#include <stdbool.h>
+
+#include "atf-c.h"
+
+#include "h_macros.h"
+
+static stack_t sigstk;
+static bool handler_called;
+static bool handler_use_altstack;
+
+static void
+handler(int signo __unused)
+{
+ char sp[128];
+
+ handler_called = true;
+
+ /* checking if the stack pointer is within the range of altstack */
+ if ((char *)sigstk.ss_sp <= sp &&
+ ((char *)sigstk.ss_sp + sigstk.ss_size) > sp)
+ handler_use_altstack = true;
+ else
+ handler_use_altstack = false;
+}
+
+ATF_TC(sigaltstack_onstack);
+ATF_TC_HEAD(sigaltstack_onstack, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks for using signal stack with SA_ONSTACK");
+}
+
+ATF_TC_BODY(sigaltstack_onstack, tc)
+{
+ struct sigaction sa;
+ int i;
+
+ /* set a signal handler use alternative stack */
+ memset(&sigstk, 0, sizeof(sigstk));
+ sigstk.ss_sp = malloc(SIGSTKSZ);
+ ATF_REQUIRE(sigstk.ss_sp != NULL);
+ sigstk.ss_size = SIGSTKSZ;
+ sigstk.ss_flags = 0;
+ ATF_REQUIRE(sigaltstack(&sigstk, 0) == 0);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = handler;
+ sa.sa_flags = SA_ONSTACK;
+ sigaction(SIGUSR1, &sa, NULL);
+
+ /* test several times */
+ for (i = 1; i <= 5; i++) {
+ handler_called = false;
+ kill(getpid(), SIGUSR1);
+
+ if (!handler_called)
+ atf_tc_fail("signal handler wasn't called (count=%d)", i);
+ if (!handler_use_altstack)
+ atf_tc_fail("alternative stack wasn't used (count=%d)", i);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, sigaltstack_onstack);
+
+ return atf_no_error();
+}
-/* $OpenBSD: t_syscall.c,v 1.2 2020/11/10 14:43:14 bluhm Exp $ */
-/* $NetBSD: t_syscall.c,v 1.3 2018/05/28 07:55:56 martin Exp $ */
+/* $OpenBSD: t_syscall.c,v 1.3 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_syscall.c,v 1.4 2021/01/18 05:44:20 simonb Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
#include "macros.h"
#include <sys/cdefs.h>
-__RCSID("$NetBSD: t_syscall.c,v 1.3 2018/05/28 07:55:56 martin Exp $");
+__RCSID("$NetBSD: t_syscall.c,v 1.4 2021/01/18 05:44:20 simonb Exp $");
#include "atf-c.h"
p = (const char *)syscall(SYS_mmap,
0, sizeof(secrect_data), PROT_READ, MAP_PRIVATE, fd, 0, 0, 0);
- ATF_REQUIRE(p != NULL);
+ ATF_REQUIRE(p != MAP_FAILED);
ATF_REQUIRE(strcmp(p, secrect_data) == 0);
}
p = (const char *)__SYSCALL_TO_UINTPTR_T(__syscall(SYS_mmap,
0, sizeof(secrect_data), PROT_READ, MAP_PRIVATE, fd,
/* pad*/ 0, (off_t)0));
- ATF_REQUIRE(p != NULL);
+ ATF_REQUIRE(p != MAP_FAILED);
ATF_REQUIRE(strcmp(p, secrect_data) == 0);
}
--- /dev/null
+/* $OpenBSD: t_wait_noproc.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_wait_noproc.c,v 1.5 2016/11/09 17:50:19 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include "macros.h"
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_wait_noproc.c,v 1.5 2016/11/09 17:50:19 kamil Exp $");
+
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "atf-c.h"
+
+#ifndef TWAIT_OPTION
+#define TWAIT_OPTION 0
+#endif
+
+#if TWAIT_OPTION == 0
+ATF_TC(wait);
+ATF_TC_HEAD(wait, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that wait(2) returns ECHILD for no child");
+}
+
+ATF_TC_BODY(wait, tc)
+{
+ ATF_REQUIRE_ERRNO(ECHILD, wait(NULL) == -1);
+}
+#endif
+
+ATF_TC(waitpid);
+ATF_TC_HEAD(waitpid, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that waitpid(2) returns ECHILD for WAIT_ANY and option %s",
+ ___STRING(TWAIT_OPTION));
+}
+
+ATF_TC_BODY(waitpid, tc)
+{
+ ATF_REQUIRE_ERRNO(ECHILD, waitpid(WAIT_ANY, NULL, TWAIT_OPTION) == -1);
+}
+
+#ifndef __OpenBSD__
+ATF_TC(waitid);
+ATF_TC_HEAD(waitid, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that waitid(2) returns ECHILD for P_ALL and option %s",
+ ___STRING(TWAIT_OPTION));
+}
+
+ATF_TC_BODY(waitid, tc)
+{
+ ATF_REQUIRE_ERRNO(ECHILD,
+ waitid(P_ALL, 0, NULL,
+ WTRAPPED | WEXITED | TWAIT_OPTION) == -1);
+}
+#endif
+
+ATF_TC(wait3);
+ATF_TC_HEAD(wait3, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that wait3(2) returns ECHILD for no child");
+}
+
+ATF_TC_BODY(wait3, tc)
+{
+ ATF_REQUIRE_ERRNO(ECHILD, wait3(NULL, TWAIT_OPTION, NULL) == -1);
+}
+
+ATF_TC(wait4);
+ATF_TC_HEAD(wait4, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
+ ___STRING(TWAIT_OPTION));
+}
+
+ATF_TC_BODY(wait4, tc)
+{
+ ATF_REQUIRE_ERRNO(ECHILD,
+ wait4(WAIT_ANY, NULL, TWAIT_OPTION, NULL) == -1);
+}
+
+#ifndef __OpenBSD__
+ * Adjusted for OpenBSD, not available
+ * ATF_TC(wait6);
+ * ATF_TC_HEAD(wait6, tc)
+ * {
+ * atf_tc_set_md_var(tc, "descr",
+ * "Test that wait6(2) returns ECHILD for P_ALL and option %s",
+ * ___STRING(TWAIT_OPTION));
+ * }
+ *
+ * ATF_TC_BODY(wait6, tc)
+ * {
+ * ATF_REQUIRE_ERRNO(ECHILD,
+ * wait6(P_ALL, 0, NULL,
+ * WTRAPPED | WEXITED | TWAIT_OPTION, NULL, NULL) == -1);
+ * }
+ */
+
+/*
+ * Generator of valid combinations of options
+ * Usage: i = 0; while ((o = get_options_wait6(i++)) != -1) {}
+ */
+static int
+get_options6(size_t pos)
+{
+ int rv = 0;
+ size_t n;
+ /*
+ * waitid(2) must specify at least one of WEXITED, WUNTRACED,
+ * WSTOPPED, WTRAPPED or WCONTINUED. Single option WNOWAIT
+ * isn't valid.
+ */
+ const int matrix[] = {
+ WNOWAIT, // First in order to blacklist it easily
+ WEXITED,
+ WUNTRACED,
+ WSTOPPED, // SUS compatibility, equal to WUNTRACED
+ WTRAPPED,
+ WCONTINUED
+ };
+
+ const size_t M = (1 << __arraycount(matrix)) - 1;
+ /* Skip empty and sole WNOWAIT option */
+ pos+=2;
+
+ if (pos > M)
+ return -1;
+
+ for (n = 0; n < __arraycount(matrix); n++) {
+ if (pos & __BIT(n))
+ rv |= matrix[n];
+ }
+
+ return rv;
+}
+#endif
+
+/*
+ * Generator of valid combinations of options
+ * Usage: i = 0; while ((o = get_options_wait4(i++)) != -1) {}
+ */
+static int
+get_options4(size_t pos)
+{
+ int rv = 0;
+ size_t n;
+
+ const int special[] = {
+ 0,
+#ifndef __OpenBSD__
+ WALLSIG,
+ WALTSIG,
+ __WALL, // Linux compatibility, equal to WALLSIG
+ __WCLONE // Linux compatibility, equal to WALTSIG
+#endif
+ };
+
+ const int matrix[] = {
+#ifndef __OpenBSD__
+ WNOWAIT,
+ WEXITED,
+#endif
+ WUNTRACED,
+#ifndef __OpenBSD__
+ WSTOPPED, // SUS compatibility, equal to WUNTRACED
+ WTRAPPED,
+#endif
+ WCONTINUED
+ };
+
+ const size_t M = (1 << __arraycount(special)) - 1;
+
+ if (pos < __arraycount(special))
+ return special[pos];
+
+ pos -= __arraycount(special);
+
+ ++pos; /* Don't start with empty mask */
+
+ if (pos > M)
+ return -1;
+
+ for (n = 0; n < __arraycount(special); n++) {
+ if (pos & __BIT(n))
+ rv |= matrix[n];
+ }
+
+ return rv;
+}
+
+ATF_TC(waitpid_options);
+ATF_TC_HEAD(waitpid_options, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that waitpid(2) returns ECHILD for WAIT_ANY and valid "
+ "combination of options with%s WNOHANG",
+ TWAIT_OPTION == 0 ? "out" : "");
+}
+
+ATF_TC_BODY(waitpid_options, tc)
+{
+ size_t i = 0;
+ int o;
+
+ while((o = get_options4(i++)) != -1) {
+ printf("Testing waitpid(2) with options %x\n", o);
+
+ ATF_REQUIRE_ERRNO(ECHILD,
+ waitpid(WAIT_ANY, NULL, o | TWAIT_OPTION) == -1);
+ }
+}
+
+#ifndef __OpenBSD__
+ATF_TC(waitid_options);
+ATF_TC_HEAD(waitid_options, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that waitid(2) returns ECHILD for P_ALL and valid "
+ "combination of options with%s WNOHANG",
+ TWAIT_OPTION == 0 ? "out" : "");
+}
+
+ATF_TC_BODY(waitid_options, tc)
+{
+ size_t i = 0;
+ int o;
+
+ while((o = get_options6(i++)) != -1) {
+ printf("Testing waitid(2) with options %x\n", o);
+
+ ATF_REQUIRE_ERRNO(ECHILD,
+ waitid(P_ALL, 0, NULL, o | TWAIT_OPTION) == -1);
+ }
+}
+#endif
+
+ATF_TC(wait3_options);
+ATF_TC_HEAD(wait3_options, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that wait3(2) returns ECHILD for no child");
+}
+
+ATF_TC_BODY(wait3_options, tc)
+{
+ size_t i = 0;
+ int o;
+
+ while((o = get_options4(i++)) != -1) {
+ printf("Testing wait3(2) with options %x\n", o);
+
+ ATF_REQUIRE_ERRNO(ECHILD,
+ wait3(NULL, o | TWAIT_OPTION, NULL) == -1);
+ }
+}
+
+ATF_TC(wait4_options);
+ATF_TC_HEAD(wait4_options, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that wait4(2) returns ECHILD for WAIT_ANY and option %s",
+ ___STRING(TWAIT_OPTION));
+}
+
+ATF_TC_BODY(wait4_options, tc)
+{
+ size_t i = 0;
+ int o;
+
+ while((o = get_options4(i++)) != -1) {
+ printf("Testing wait4(2) with options %x\n", o);
+
+ ATF_REQUIRE_ERRNO(ECHILD,
+ wait4(WAIT_ANY, NULL, o | TWAIT_OPTION, NULL) == -1);
+ }
+}
+
+#ifndef __OpenBSD__
+ATF_TC(wait6_options);
+ATF_TC_HEAD(wait6_options, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that wait6(2) returns ECHILD for P_ALL and option %s",
+ ___STRING(TWAIT_OPTION));
+}
+
+ATF_TC_BODY(wait6_options, tc)
+{
+ size_t i = 0;
+ int o;
+
+ while((o = get_options6(i++)) != -1) {
+ printf("Testing wait6(2) with options %x\n", o);
+
+ ATF_REQUIRE_ERRNO(ECHILD,
+ wait6(P_ALL, 0, NULL, o | TWAIT_OPTION, NULL, NULL) == -1);
+ }
+}
+#endif
+
+ATF_TP_ADD_TCS(tp)
+{
+
+#if TWAIT_OPTION == 0
+ ATF_TP_ADD_TC(tp, wait);
+#endif
+ ATF_TP_ADD_TC(tp, waitpid);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, waitid);
+#endif
+ ATF_TP_ADD_TC(tp, wait3);
+ ATF_TP_ADD_TC(tp, wait4);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, wait6);
+#endif
+
+ ATF_TP_ADD_TC(tp, waitpid_options);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, waitid_options);
+#endif
+ ATF_TP_ADD_TC(tp, wait3_options);
+ ATF_TP_ADD_TC(tp, wait4_options);
+#ifndef __OpenBSD__
+ ATF_TP_ADD_TC(tp, wait6_options);
+#endif
+
+ return atf_no_error();
+}
--- /dev/null
+/* $OpenBSD: t_wait_noproc_wnohang.c,v 1.1 2021/09/02 12:40:44 mbuhl Exp $ */
+/* $NetBSD: t_wait_noproc_wnohang.c,v 1.1 2016/11/06 15:03:30 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#define TWAIT_OPTION WNOHANG
+#include "t_wait_noproc.c"