mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 13:52:28 +00:00
Improve system calls
- Wrap clock_getres() - Wrap sched_setscheduler() - Make sleep() api conformant - Polyfill sleep() using select() - Improve clock_gettime() polyfill - Make nanosleep() POSIX conformant - Slightly improve some DNS functions - Further strengthen pledge() sandboxing - Improve rounding of timeval / timespec - Allow layering of pledge() calls on Linux - Polyfill sched_yield() using select() on XNU - Delete more system constants we probably don't need
This commit is contained in:
parent
5df3e4e7a8
commit
853b6c3864
330 changed files with 1971 additions and 1223 deletions
83
test/libc/calls/clock_getres_test.c
Normal file
83
test/libc/calls/clock_getres_test.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
struct timespec ts;
|
||||
|
||||
TEST(clock_getres, realtimeHasMillisecondPrecisionOrBetter) {
|
||||
ASSERT_EQ(0, clock_getres(CLOCK_REALTIME, &ts));
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 1000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, realtimeFastHasMillisecondPrecisionOrBetter) {
|
||||
ASSERT_EQ(0, clock_getres(CLOCK_REALTIME_FAST, &ts));
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 1000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, realtimeCoarseHasMillisecondPrecisionOrBetter) {
|
||||
if (clock_getres(CLOCK_REALTIME_COARSE, &ts)) return;
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 100000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, realtimePreciseHasMillisecondPrecisionOrBetter) {
|
||||
if (clock_getres(CLOCK_REALTIME_PRECISE, &ts)) return;
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 100000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, monotonicHasMillisecondPrecisionOrBetter) {
|
||||
ASSERT_EQ(0, clock_getres(CLOCK_MONOTONIC, &ts));
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 1000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, monotonicFastHasMillisecondPrecisionOrBetter) {
|
||||
ASSERT_EQ(0, clock_getres(CLOCK_MONOTONIC_FAST, &ts));
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 1000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, monotonicCoarseHasMillisecondPrecisionOrBetter) {
|
||||
if (clock_getres(CLOCK_MONOTONIC_COARSE, &ts)) return;
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 100000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
||||
|
||||
TEST(clock_getres, monotonicPreciseHasMillisecondPrecisionOrBetter) {
|
||||
if (clock_getres(CLOCK_MONOTONIC_PRECISE, &ts)) return;
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_LT(ts.tv_nsec, 100000000);
|
||||
EXPECT_GT(ts.tv_nsec, 0);
|
||||
}
|
|
@ -30,6 +30,10 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
TEST(clock_gettime, fault) {
|
||||
ASSERT_SYS(EFAULT, -1, clock_gettime(0, 0));
|
||||
}
|
||||
|
||||
TEST(clock_gettime, test) {
|
||||
bool isfast;
|
||||
struct timespec ts = {0};
|
||||
|
|
64
test/libc/calls/nanosleep_test.c
Normal file
64
test/libc/calls/nanosleep_test.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sysv/consts/itimer.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
void OnAlrm(int sig) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
TEST(nanosleep, testFault) {
|
||||
EXPECT_SYS(EFAULT, -1, nanosleep(0, 0));
|
||||
}
|
||||
|
||||
TEST(nanosleep, testInvalid) {
|
||||
struct timespec ts = {0, -1};
|
||||
EXPECT_SYS(EINVAL, -1, nanosleep(&ts, 0));
|
||||
}
|
||||
|
||||
TEST(nanosleep, testNoSignalIsDelivered_remIsSetToZero) {
|
||||
struct timespec ts = {0, 1};
|
||||
ASSERT_SYS(0, 0, nanosleep(&ts, &ts));
|
||||
EXPECT_EQ(0, ts.tv_sec);
|
||||
EXPECT_EQ(0, ts.tv_nsec);
|
||||
}
|
||||
|
||||
TEST(nanosleep, testInterrupt_remIsUpdated) {
|
||||
struct sigaction sa = {
|
||||
.sa_handler = OnAlrm,
|
||||
.sa_flags = SA_RESETHAND,
|
||||
};
|
||||
ASSERT_SYS(0, 0, sigaction(SIGALRM, &sa, 0));
|
||||
struct itimerval it = {{0, 0}, {0, 10000}}; // 10ms singleshot
|
||||
ASSERT_SYS(0, 0, setitimer(ITIMER_REAL, &it, 0));
|
||||
struct timespec ts = {500, 0};
|
||||
ASSERT_SYS(EINTR, -1, nanosleep(&ts, &ts));
|
||||
ASSERT_LT(ts.tv_sec, 500);
|
||||
ASSERT_GT(ts.tv_sec, 400);
|
||||
ASSERT_NE(0, ts.tv_nsec);
|
||||
}
|
66
test/libc/calls/sched_setscheduler_test.c
Normal file
66
test/libc/calls/sched_setscheduler_test.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/midpoint.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sched.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define DEFAULT_POLICY SCHED_OTHER
|
||||
|
||||
void SetUp(void) {
|
||||
if (IsXnu() || IsWindows() || IsOpenbsd() || IsWindows()) {
|
||||
exit(0);
|
||||
}
|
||||
int oldpolicy = sched_getscheduler(0);
|
||||
struct sched_param p = {sched_get_priority_min(DEFAULT_POLICY)};
|
||||
EXPECT_SYS(0, oldpolicy, sched_setscheduler(0, DEFAULT_POLICY, &p));
|
||||
}
|
||||
|
||||
bool CanTuneRealtimeSchedulers(void) {
|
||||
int e = errno;
|
||||
int policy = SCHED_FIFO;
|
||||
struct sched_param p = {sched_get_priority_min(policy)};
|
||||
if (sched_setscheduler(0, policy, &p) != -1) {
|
||||
struct sched_param p = {sched_get_priority_min(DEFAULT_POLICY)};
|
||||
EXPECT_SYS(0, policy, sched_setscheduler(0, DEFAULT_POLICY, &p));
|
||||
return true;
|
||||
} else if (errno == EPERM) {
|
||||
errno = e;
|
||||
return false;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(sched_setscheduler, test) {
|
||||
struct sched_param p = {sched_get_priority_min(SCHED_OTHER)};
|
||||
EXPECT_SYS(0, DEFAULT_POLICY, sched_setscheduler(0, SCHED_OTHER, &p));
|
||||
}
|
||||
|
||||
TEST(sched_setscheduler, testMidpoint) {
|
||||
if (!CanTuneRealtimeSchedulers()) return;
|
||||
struct sched_param p = {_midpoint(sched_get_priority_min(SCHED_FIFO),
|
||||
sched_get_priority_max(SCHED_FIFO))};
|
||||
EXPECT_SYS(0, DEFAULT_POLICY, sched_setscheduler(0, SCHED_FIFO, &p));
|
||||
}
|
24
test/libc/intrin/sched_yield_test.c
Normal file
24
test/libc/intrin/sched_yield_test.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(sched_yield, test) {
|
||||
EXPECT_SYS(0, 0, sched_yield());
|
||||
}
|
|
@ -23,10 +23,12 @@
|
|||
#include "libc/calls/struct/filter.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/calls/struct/seccomp.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
@ -47,6 +49,10 @@
|
|||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
void OnSig(int sig) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void SetUp(void) {
|
||||
if (!__is_linux_2_6_23() && !IsOpenbsd()) {
|
||||
exit(0);
|
||||
|
@ -65,7 +71,8 @@ TEST(pledge, default_allowsExit) {
|
|||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, stdio_forbidsOpeningPasswd) {
|
||||
TEST(pledge, stdio_forbidsOpeningPasswd1) {
|
||||
if (!IsLinux()) return;
|
||||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
|
@ -74,13 +81,70 @@ TEST(pledge, stdio_forbidsOpeningPasswd) {
|
|||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
if (IsLinux()) {
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
} else {
|
||||
EXPECT_TRUE(WIFSIGNALED(ws));
|
||||
EXPECT_EQ(SIGABRT, WTERMSIG(ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, stdio_forbidsOpeningPasswd2) {
|
||||
if (!IsOpenbsd()) return;
|
||||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||
ASSERT_SYS(EPERM, -1, open("/etc/passwd", O_RDWR));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFSIGNALED(ws));
|
||||
EXPECT_EQ(SIGABRT, WTERMSIG(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, multipleCalls_canOnlyBecomeMoreRestrictive1) {
|
||||
if (IsOpenbsd()) return;
|
||||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||
ASSERT_SYS(0, 0, pledge("stdio unix", 0));
|
||||
ASSERT_SYS(0, 3, dup(2));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_UNIX, SOCK_STREAM, 0));
|
||||
ASSERT_SYS(EPERM, -1, prctl(PR_SET_NO_NEW_PRIVS, 0, 0, 0, 0));
|
||||
ASSERT_SYS(EPERM, -1, prctl(PR_GET_SECCOMP, SECCOMP_MODE_FILTER, 0));
|
||||
ASSERT_SYS(EPERM, -1, prctl(PR_SET_SECCOMP, 33, 0));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, multipleCalls_canOnlyBecomeMoreRestrictive2) {
|
||||
if (!IsOpenbsd()) return;
|
||||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||
ASSERT_SYS(EPERM, -1, pledge("stdio unix", 0));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, multipleCalls_canOnlyBecomeMoreRestrictive3) {
|
||||
if (!IsOpenbsd()) return;
|
||||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio unix", 0));
|
||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||
ASSERT_SYS(0, 3, dup(2));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, stdio_fcntl_allowsSomeFirstArgs) {
|
||||
|
@ -89,6 +153,7 @@ TEST(pledge, stdio_fcntl_allowsSomeFirstArgs) {
|
|||
struct flock lk;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio inet", 0));
|
||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||
ASSERT_NE(-1, fcntl(0, F_GETFL));
|
||||
ASSERT_SYS(0, 0, fcntl(0, F_GETFD));
|
||||
|
@ -108,7 +173,6 @@ TEST(pledge, stdio_fcntl_allowsSomeFirstArgs) {
|
|||
TEST(pledge, stdioTty_sendtoRestricted_requiresNullAddr) {
|
||||
if (IsOpenbsd()) return; // b/c testing linux bpf
|
||||
int ws, pid, sv[2];
|
||||
struct sockaddr_in sa = {AF_UNIX};
|
||||
ASSERT_SYS(0, 0, socketpair(AF_UNIX, SOCK_STREAM, 0, sv));
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
|
@ -118,7 +182,12 @@ TEST(pledge, stdioTty_sendtoRestricted_requiresNullAddr) {
|
|||
isatty(0);
|
||||
ASSERT_NE(EPERM, errno);
|
||||
errno = 0;
|
||||
ASSERT_SYS(EPERM, -1, sendto(sv[0], "hello", 5, 0, &sa, sizeof(sa)));
|
||||
// set lower 32-bit word of pointer to zero lool
|
||||
struct sockaddr_in *sin =
|
||||
mmap((void *)0x300000000000, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
sin->sin_family = AF_INET;
|
||||
ASSERT_SYS(EPERM, -1, sendto(sv[0], "hello", 5, 0, sin, sizeof(*sin)));
|
||||
_Exit(0);
|
||||
}
|
||||
close(sv[0]);
|
||||
|
@ -134,8 +203,11 @@ TEST(pledge, unix_forbidsInetSockets) {
|
|||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio unix", 0));
|
||||
ASSERT_SYS(0, 3, socket(AF_UNIX, SOCK_STREAM, 0));
|
||||
ASSERT_SYS(0, 4, socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_UNIX, SOCK_RAW, 0));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_UNIX, SOCK_STREAM, 1));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
|
@ -148,10 +220,20 @@ TEST(pledge, inet_forbidsOtherSockets) {
|
|||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio inet", 0));
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 4, socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP));
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
||||
ASSERT_SYS(0, 4, socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
||||
ASSERT_SYS(0, 5, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 6, socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP));
|
||||
ASSERT_SYS(0, 7, socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_UNIX, SOCK_STREAM, 0));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_BLUETOOTH, SOCK_STREAM, 0));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_BLUETOOTH, SOCK_DGRAM, IPPROTO_UDP));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_RAW, IPPROTO_UDP));
|
||||
ASSERT_SYS(EPERM, -1, socket(AF_INET, SOCK_DGRAM, IPPROTO_RAW));
|
||||
struct sockaddr_in sin = {AF_INET, 0, {htonl(0x7f000001)}};
|
||||
ASSERT_SYS(0, 0, bind(4, &sin, sizeof(sin)));
|
||||
uint32_t az = sizeof(sin);
|
||||
ASSERT_SYS(0, 0, getsockname(4, &sin, &az));
|
||||
ASSERT_SYS(0, 5, sendto(3, "hello", 5, 0, &sin, sizeof(sin)));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
|
@ -179,6 +261,26 @@ TEST(pledge, mmap) {
|
|||
EXPECT_TRUE(WIFEXITED(ws) && !WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, mmapExec) {
|
||||
if (IsOpenbsd()) return; // b/c testing linux bpf
|
||||
char *p;
|
||||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio exec", 0));
|
||||
ASSERT_NE(MAP_FAILED, (p = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)));
|
||||
ASSERT_SYS(0, 0, mprotect(p, FRAMESIZE, PROT_READ));
|
||||
ASSERT_SYS(EPERM, MAP_FAILED,
|
||||
mprotect(p, FRAMESIZE, PROT_READ | PROT_EXEC));
|
||||
ASSERT_NE(MAP_FAILED, mmap(0, FRAMESIZE, PROT_EXEC | PROT_READ,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws) && !WEXITSTATUS(ws));
|
||||
}
|
||||
|
||||
TEST(pledge, msyscall) {
|
||||
if (IsOpenbsd()) return; // b/c testing linux bpf
|
||||
int ax, ws, pid;
|
||||
|
@ -204,7 +306,7 @@ TEST(pledge, chmod_ignoresDangerBits) {
|
|||
ASSERT_SYS(0, 3, creat("foo", 0644));
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio rpath", 0));
|
||||
ASSERT_SYS(0, 0, pledge("stdio rpath wpath", 0));
|
||||
ASSERT_SYS(0, 0, fchmod(3, 00700));
|
||||
ASSERT_SYS(0, 0, chmod("foo", 00700));
|
||||
ASSERT_SYS(0, 0, fchmodat(AT_FDCWD, "foo", 00700, 0));
|
||||
|
@ -233,7 +335,6 @@ TEST(pledge, open_rpath) {
|
|||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws) && !WEXITSTATUS(ws));
|
||||
close(3);
|
||||
}
|
||||
|
||||
TEST(pledge, open_wpath) {
|
||||
|
@ -252,5 +353,20 @@ TEST(pledge, open_wpath) {
|
|||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws) && !WEXITSTATUS(ws));
|
||||
close(3);
|
||||
}
|
||||
|
||||
TEST(pledge, sigaction_isFineButForbidsSigsys) {
|
||||
if (IsOpenbsd()) return; // b/c testing linux bpf
|
||||
int ws, pid;
|
||||
struct stat st;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||
struct sigaction sa = {.sa_handler = OnSig};
|
||||
ASSERT_SYS(0, 0, sigaction(SIGINT, &sa, 0));
|
||||
ASSERT_SYS(EPERM, -1, sigaction(SIGSYS, &sa, 0));
|
||||
_Exit(0);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws) && !WEXITSTATUS(ws));
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ TEST(unix, datagram) {
|
|||
alarm(3);
|
||||
while (!fileexists(addr.sun_path)) usleep(10000);
|
||||
ASSERT_SYS(0, 3, socket(AF_UNIX, SOCK_DGRAM, 0));
|
||||
ASSERT_SYS(0, 5, sendto(3, "hello", 5, 0, (void *)&addr, len));
|
||||
ASSERT_SYS(0, 5, sendto(3, "hello", 5, 0, &addr, len));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_NE(-1, wait(&ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue