From abbaa2745fb6bc1626d89c16a2088aa4589b729d Mon Sep 17 00:00:00 2001 From: mbuhl Date: Thu, 2 Sep 2021 12:40:44 +0000 Subject: [PATCH] Import more NetBSD system call regression tests. OK bluhm@ --- regress/lib/libc/sys/Makefile | 35 +- regress/lib/libc/sys/README | 82 +-- regress/lib/libc/sys/atf-c.h | 3 +- regress/lib/libc/sys/h_macros.h | 1 + regress/lib/libc/sys/macros.h | 14 +- regress/lib/libc/sys/t_clock_gettime.c | 1 + regress/lib/libc/sys/t_connect.c | 135 +++++ regress/lib/libc/sys/t_fork.c | 387 +++++++++++++ regress/lib/libc/sys/t_kevent.c | 236 ++++++++ regress/lib/libc/sys/t_minherit.c | 203 +++++++ regress/lib/libc/sys/t_pollts.c | 203 +++++++ regress/lib/libc/sys/t_ppoll.c | 34 ++ regress/lib/libc/sys/t_setrlimit.c | 559 +++++++++++++++++++ regress/lib/libc/sys/t_sigaltstack.c | 102 ++++ regress/lib/libc/sys/t_syscall.c | 10 +- regress/lib/libc/sys/t_wait_noproc.c | 364 ++++++++++++ regress/lib/libc/sys/t_wait_noproc_wnohang.c | 31 + 17 files changed, 2350 insertions(+), 50 deletions(-) create mode 100644 regress/lib/libc/sys/t_connect.c create mode 100644 regress/lib/libc/sys/t_fork.c create mode 100644 regress/lib/libc/sys/t_kevent.c create mode 100644 regress/lib/libc/sys/t_minherit.c create mode 100644 regress/lib/libc/sys/t_pollts.c create mode 100644 regress/lib/libc/sys/t_ppoll.c create mode 100644 regress/lib/libc/sys/t_setrlimit.c create mode 100644 regress/lib/libc/sys/t_sigaltstack.c create mode 100644 regress/lib/libc/sys/t_wait_noproc.c create mode 100644 regress/lib/libc/sys/t_wait_noproc_wnohang.c diff --git a/regress/lib/libc/sys/Makefile b/regress/lib/libc/sys/Makefile index 7a3b920426d..acb5c898966 100644 --- a/regress/lib/libc/sys/Makefile +++ b/regress/lib/libc/sys/Makefile @@ -1,4 +1,4 @@ -# $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 # Copyright (c) 2019 Alexander Bluhm @@ -29,20 +29,45 @@ PROGS = 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 diff --git a/regress/lib/libc/sys/README b/regress/lib/libc/sys/README index 0f7d82e7b6f..5606fcaa153 100644 --- a/regress/lib/libc/sys/README +++ b/regress/lib/libc/sys/README @@ -3,24 +3,33 @@ Regression tests for system calls ported from NetBSD. 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 @@ -28,40 +37,37 @@ t_mmap - ENOTBLK on test NetBSD is skipping, remove mmap_va0 test 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 diff --git a/regress/lib/libc/sys/atf-c.h b/regress/lib/libc/sys/atf-c.h index 93e2026ca17..c10628be262 100644 --- a/regress/lib/libc/sys/atf-c.h +++ b/regress/lib/libc/sys/atf-c.h @@ -1,4 +1,4 @@ -/* $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 * @@ -76,6 +76,7 @@ ATF_TC_FUNCTIONS(fn) #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, ...) \ diff --git a/regress/lib/libc/sys/h_macros.h b/regress/lib/libc/sys/h_macros.h index 227db0f31be..22f7ed83f42 100644 --- a/regress/lib/libc/sys/h_macros.h +++ b/regress/lib/libc/sys/h_macros.h @@ -1,3 +1,4 @@ +/* $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 $ */ /*- diff --git a/regress/lib/libc/sys/macros.h b/regress/lib/libc/sys/macros.h index ef858d137a1..56f9ff1a1a6 100644 --- a/regress/lib/libc/sys/macros.h +++ b/regress/lib/libc/sys/macros.h @@ -1,4 +1,4 @@ -/* $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 @@ -49,6 +49,14 @@ sysctlbyname(char* s, void *oldp, size_t *oldlenp, void *newp, size_t newlen) 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 @@ -63,3 +71,7 @@ sysctlbyname(char* s, void *oldp, size_t *oldlenp, void *newp, size_t newlen) /* t_write.c */ #define _PATH_DEVZERO "/dev/zero" + +/* t_wait_noproc.c */ +#define ___STRING(x) #x +#define __BIT(n) (1 << (n)) diff --git a/regress/lib/libc/sys/t_clock_gettime.c b/regress/lib/libc/sys/t_clock_gettime.c index 206710799e3..b75be63e4cd 100644 --- a/regress/lib/libc/sys/t_clock_gettime.c +++ b/regress/lib/libc/sys/t_clock_gettime.c @@ -1,3 +1,4 @@ +/* $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 $ */ /*- diff --git a/regress/lib/libc/sys/t_connect.c b/regress/lib/libc/sys/t_connect.c new file mode 100644 index 00000000000..c1730a40c76 --- /dev/null +++ b/regress/lib/libc/sys/t_connect.c @@ -0,0 +1,135 @@ +/* $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 +#include +#include +#include +#include + +#include +#include + +#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(); +} diff --git a/regress/lib/libc/sys/t_fork.c b/regress/lib/libc/sys/t_fork.c new file mode 100644 index 00000000000..76d66ce9d4d --- /dev/null +++ b/regress/lib/libc/sys/t_fork.c @@ -0,0 +1,387 @@ +/* $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 +__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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(); +} diff --git a/regress/lib/libc/sys/t_kevent.c b/regress/lib/libc/sys/t_kevent.c new file mode 100644 index 00000000000..171e1f3dc99 --- /dev/null +++ b/regress/lib/libc/sys/t_kevent.c @@ -0,0 +1,236 @@ +/* $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 +__RCSID("$NetBSD: t_kevent.c,v 1.9 2020/10/31 01:08:32 christos Exp $"); + +#include +#include + +#include "atf-c.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __OpenBSD__ +#include +#endif +#include +#include +#include +#include + +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(); +} diff --git a/regress/lib/libc/sys/t_minherit.c b/regress/lib/libc/sys/t_minherit.c new file mode 100644 index 00000000000..dd9ddf1d1ed --- /dev/null +++ b/regress/lib/libc/sys/t_minherit.c @@ -0,0 +1,203 @@ +/* $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 +__RCSID("$NetBSD: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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(); +} diff --git a/regress/lib/libc/sys/t_pollts.c b/regress/lib/libc/sys/t_pollts.c new file mode 100644 index 00000000000..966b8c7721a --- /dev/null +++ b/regress/lib/libc/sys/t_pollts.c @@ -0,0 +1,203 @@ +/* $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 +#include + +#include "atf-c.h" +#include +#include +#include +#include +#include +#include +#include + +#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(); +} diff --git a/regress/lib/libc/sys/t_ppoll.c b/regress/lib/libc/sys/t_ppoll.c new file mode 100644 index 00000000000..c5daef1f5f7 --- /dev/null +++ b/regress/lib/libc/sys/t_ppoll.c @@ -0,0 +1,34 @@ +/* $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" diff --git a/regress/lib/libc/sys/t_setrlimit.c b/regress/lib/libc/sys/t_setrlimit.c new file mode 100644 index 00000000000..d72ec5216d7 --- /dev/null +++ b/regress/lib/libc/sys/t_setrlimit.c @@ -0,0 +1,559 @@ +/* $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 +__RCSID("$NetBSD: t_setrlimit.c,v 1.7 2020/10/13 06:58:57 rin Exp $"); + +#include +#include +#include + +#include "atf-c.h" +#include +#include +#include +#ifndef __OpenBSD__ +#include +#endif +#include +#include +#include +#include +#include +#ifndef __OpenBSD__ +#include +#endif +#include + +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(); +} diff --git a/regress/lib/libc/sys/t_sigaltstack.c b/regress/lib/libc/sys/t_sigaltstack.c new file mode 100644 index 00000000000..ac02650296a --- /dev/null +++ b/regress/lib/libc/sys/t_sigaltstack.c @@ -0,0 +1,102 @@ +/* $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 +__RCSID("$NetBSD: t_sigaltstack.c,v 1.2 2020/05/01 21:35:30 christos Exp $"); + +#include +#include + +#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(); +} diff --git a/regress/lib/libc/sys/t_syscall.c b/regress/lib/libc/sys/t_syscall.c index 72ad9139d67..454905837fa 100644 --- a/regress/lib/libc/sys/t_syscall.c +++ b/regress/lib/libc/sys/t_syscall.c @@ -1,5 +1,5 @@ -/* $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. @@ -33,7 +33,7 @@ #include "macros.h" #include -__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" @@ -84,7 +84,7 @@ ATF_TC_BODY(mmap_syscall, tc) 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); } @@ -110,7 +110,7 @@ ATF_TC_BODY(mmap___syscall, tc) 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); } diff --git a/regress/lib/libc/sys/t_wait_noproc.c b/regress/lib/libc/sys/t_wait_noproc.c new file mode 100644 index 00000000000..73fc7ae0352 --- /dev/null +++ b/regress/lib/libc/sys/t_wait_noproc.c @@ -0,0 +1,364 @@ +/* $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 +__RCSID("$NetBSD: t_wait_noproc.c,v 1.5 2016/11/09 17:50:19 kamil Exp $"); + +#include +#include + +#include +#include + +#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(); +} diff --git a/regress/lib/libc/sys/t_wait_noproc_wnohang.c b/regress/lib/libc/sys/t_wait_noproc_wnohang.c new file mode 100644 index 00000000000..d1dcb981649 --- /dev/null +++ b/regress/lib/libc/sys/t_wait_noproc_wnohang.c @@ -0,0 +1,31 @@ +/* $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" -- 2.20.1