From 38c3fa63fecc76e6583f112b4bb5cc14f5f97c9d Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Mon, 18 Jul 2022 02:11:06 -0700 Subject: [PATCH] Write some tests for unveil() See #490 --- libc/calls/landlock.h | 10 +- libc/intrin/assertfail.greg.c | 3 +- libc/intrin/promises.internal.h | 3 +- libc/log/oncrash.c | 2 +- libc/mem/pledge.c | 11 + libc/mem/unveil.c | 45 ++- libc/sysv/calls/sys_unveil.s | 2 +- libc/sysv/calls/unveil.s | 2 - libc/sysv/consts/nrlinux.h | 666 +++++++++++++++++--------------- libc/sysv/syscalls.sh | 3 +- libc/testlib/testrunner.c | 3 +- test/libc/mem/life.c | 22 ++ test/libc/mem/test.mk | 28 +- test/libc/mem/unveil_test.c | 198 ++++++++++ 14 files changed, 646 insertions(+), 352 deletions(-) delete mode 100644 libc/sysv/calls/unveil.s create mode 100644 test/libc/mem/life.c create mode 100644 test/libc/mem/unveil_test.c diff --git a/libc/calls/landlock.h b/libc/calls/landlock.h index 0f4f460bb..5c8a26fb6 100644 --- a/libc/calls/landlock.h +++ b/libc/calls/landlock.h @@ -16,7 +16,15 @@ #define LANDLOCK_ACCESS_FS_MAKE_FIFO 0x0400ul #define LANDLOCK_ACCESS_FS_MAKE_BLOCK 0x0800ul #define LANDLOCK_ACCESS_FS_MAKE_SYM 0x1000ul -#define LANDLOCK_ACCESS_FS_REFER 0x2000ul + +/** + * Allow renaming or linking file to a different directory. + * + * @see https://lore.kernel.org/r/20220329125117.1393824-8-mic@digikod.net + * @see https://docs.kernel.org/userspace-api/landlock.html + * @note ABI 2+ + */ +#define LANDLOCK_ACCESS_FS_REFER 0x2000ul #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ diff --git a/libc/intrin/assertfail.greg.c b/libc/intrin/assertfail.greg.c index e24603215..92e3823e1 100644 --- a/libc/intrin/assertfail.greg.c +++ b/libc/intrin/assertfail.greg.c @@ -19,6 +19,7 @@ #include "libc/assert.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" +#include "libc/calls/state.internal.h" #include "libc/calls/syscall-sysv.internal.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/lockcmpxchgp.h" @@ -40,7 +41,7 @@ relegated void __assert_fail(const char *expr, const char *file, int line) { owner = 0; me = sys_gettid(); kprintf("%s:%d: assert(%s) failed (tid %d)\n", file, line, expr, me); - if (_lockcmpxchgp(&sync, &owner, me)) { + if (__vforked || _lockcmpxchgp(&sync, &owner, me)) { __restore_tty(); if (weaken(ShowBacktrace)) { weaken(ShowBacktrace)(2, __builtin_frame_address(0)); diff --git a/libc/intrin/promises.internal.h b/libc/intrin/promises.internal.h index 84938cbd3..67106985c 100644 --- a/libc/intrin/promises.internal.h +++ b/libc/intrin/promises.internal.h @@ -19,7 +19,8 @@ #define PROMISE_EXEC 15 #define PROMISE_EXECNATIVE 16 #define PROMISE_ID 17 -#define PROMISE_MAX 17 +#define PROMISE_UNVEIL 18 +#define PROMISE_MAX 18 #define PLEDGED(x) (~__promises & (1L << PROMISE_##x)) diff --git a/libc/log/oncrash.c b/libc/log/oncrash.c index f54431db4..df6827ae2 100644 --- a/libc/log/oncrash.c +++ b/libc/log/oncrash.c @@ -288,7 +288,7 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) { --__strace; owner = 0; me = sys_gettid(); - if (_lockcmpxchgp(&sync, &owner, me)) { + if (__vforked || _lockcmpxchgp(&sync, &owner, me)) { if (!__vforked) { rip = ctx ? ctx->uc_mcontext.rip : 0; err = errno; diff --git a/libc/mem/pledge.c b/libc/mem/pledge.c index 4e82a4998..96e9f4b41 100644 --- a/libc/mem/pledge.c +++ b/libc/mem/pledge.c @@ -302,6 +302,12 @@ static const uint16_t kPledgeLinuxExec2[] = { __NR_linux_execveat, // }; +static const uint16_t kPledgeLinuxUnveil[] = { + __NR_linux_landlock_create_ruleset, // + __NR_linux_landlock_add_rule, // + __NR_linux_landlock_restrict_self, // +}; + static const struct Pledges { const char *name; const uint16_t *syscalls; @@ -325,6 +331,7 @@ static const struct Pledges { [PROMISE_EXEC] = {"exec", PLEDGE(kPledgeLinuxExec)}, // [PROMISE_EXECNATIVE] = {"execnative", PLEDGE(kPledgeLinuxExec2)}, // [PROMISE_ID] = {"id", PLEDGE(kPledgeLinuxId)}, // + [PROMISE_UNVEIL] = {"unveil", PLEDGE(kPledgeLinuxUnveil)}, // [PROMISE_MAX + 1] = {0}, // }; @@ -1231,6 +1238,10 @@ static void SetPromises(const char *promises) { * System call origin verification can't be enabled. If you always * assimilate your APE binaries, then this should be preferred. * + * - "unveil" allows unveil() to be called, as well as the underlying + * landlock_create_ruleset, landlock_add_rule, landlock_restrict_self + * calls on Linux. + * * @return 0 on success, or -1 w/ errno * @raise ENOSYS if host os isn't Linux or OpenBSD * @raise EINVAL if `execpromises` is used on Linux diff --git a/libc/mem/unveil.c b/libc/mem/unveil.c index ed7cdf7b7..192ba2107 100644 --- a/libc/mem/unveil.c +++ b/libc/mem/unveil.c @@ -26,6 +26,7 @@ #include "libc/errno.h" #include "libc/mem/mem.h" #include "libc/str/str.h" +#include "libc/sysv/consts/f.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/pr.h" #include "libc/sysv/consts/s.h" @@ -45,7 +46,7 @@ * - Integrate with pledge and remove the file access? * - Stuff state into the .protected section? */ -static struct { +_Thread_local static struct { int abi; int fd; uint64_t read; @@ -54,7 +55,6 @@ static struct { uint64_t create; } State = { .abi = 2, - .fd = 0, .read = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_REFER, .write = LANDLOCK_ACCESS_FS_WRITE_FILE, @@ -65,21 +65,27 @@ static struct { LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM, }; -forceinline int unveil_final(void) { +static int unveil_final(void) { int rc; if (State.fd == -1) return 0; assert(State.fd > 0); if ((rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) != -1 && (rc = landlock_restrict_self(State.fd, 0)) != -1 && - (rc = close(State.fd)) != -1) + (rc = sys_close(State.fd)) != -1) State.fd = -1; return rc; } -forceinline int unveil_init(void) { - int rc; - if ((rc = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION)) < - 0) +static int err_close(int rc, int fd) { + int serrno = errno; + sys_close(fd); + errno = serrno; + return rc; +} + +static int unveil_init(void) { + int rc, fd; + if ((rc = landlock_create_ruleset(0, 0, LANDLOCK_CREATE_RULESET_VERSION)) < 0) return -1; State.abi = rc; if (State.abi < 2) State.read &= ~LANDLOCK_ACCESS_FS_REFER; @@ -87,21 +93,17 @@ forceinline int unveil_init(void) { .handled_access_fs = State.read | State.write | State.exec | State.create, }; if ((rc = landlock_create_ruleset(&attr, sizeof(attr), 0)) < 0) return -1; - State.fd = rc; + // grant file descriptor a higher number that's less likely to interfere + if ((fd = __sys_fcntl(rc, F_DUPFD, 100)) == -1) return err_close(-1, rc); + if (sys_close(rc) == -1) return err_close(-1, fd); + State.fd = fd; return 0; } -forceinline int err_close(int rc, int fd) { - int serrno = errno; - close(fd); - errno = serrno; - return rc; -} - static int sys_unveil_linux(const char *path, const char *permissions) { int rc; - if (State.fd == 0 && (rc = unveil_init()) == -1) return rc; - if (path == NULL && permissions == NULL) return unveil_final(); + if (!State.fd && (rc = unveil_init()) == -1) return rc; + if (!path && !permissions) return unveil_final(); struct landlock_path_beneath_attr pb = {0}; for (const char *c = permissions; *c != '\0'; c++) { switch (*c) { @@ -121,17 +123,20 @@ static int sys_unveil_linux(const char *path, const char *permissions) { return einval(); } } - if ((rc = open(path, O_RDONLY | O_PATH | O_CLOEXEC)) == -1) return rc; + if ((rc = sys_open(path, O_PATH | O_CLOEXEC, 0)) == -1) return rc; pb.parent_fd = rc; struct stat st; if ((rc = fstat(pb.parent_fd, &st)) == -1) return err_close(rc, pb.parent_fd); if (!S_ISDIR(st.st_mode)) pb.allowed_access &= FILE_BITS; if ((rc = landlock_add_rule(State.fd, LANDLOCK_RULE_PATH_BENEATH, &pb, 0))) return err_close(rc, pb.parent_fd); - close(pb.parent_fd); + sys_close(pb.parent_fd); return rc; } +/** + * Unveil parts of a restricted filesystem view. + */ int unveil(const char *path, const char *permissions) { int rc; if (IsLinux()) { diff --git a/libc/sysv/calls/sys_unveil.s b/libc/sysv/calls/sys_unveil.s index 937d8bf64..82311a7cc 100644 --- a/libc/sysv/calls/sys_unveil.s +++ b/libc/sysv/calls/sys_unveil.s @@ -1,2 +1,2 @@ .include "o/libc/sysv/macros.internal.inc" -.scall sys_unveil,0xfff072ffffffffff,globl +.scall sys_unveil,0xfff072ffffffffff,globl,hidden diff --git a/libc/sysv/calls/unveil.s b/libc/sysv/calls/unveil.s deleted file mode 100644 index f6fccd4ea..000000000 --- a/libc/sysv/calls/unveil.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall unveil,0xfff072ffffffffff,globl diff --git a/libc/sysv/consts/nrlinux.h b/libc/sysv/consts/nrlinux.h index d428b84fd..309968a89 100644 --- a/libc/sysv/consts/nrlinux.h +++ b/libc/sysv/consts/nrlinux.h @@ -1,326 +1,350 @@ #ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_NRLINUX_H_ #define COSMOPOLITAN_LIBC_SYSV_CONSTS_NRLINUX_H_ -#define __NR_linux_exit 0x003c -#define __NR_linux_exit_group 0x00e7 -#define __NR_linux_read 0x0000 -#define __NR_linux_write 0x0001 -#define __NR_linux_open 0x0002 -#define __NR_linux_close 0x0003 -#define __NR_linux_stat 0x0004 -#define __NR_linux_fstat 0x0005 -#define __NR_linux_lstat 0x0006 -#define __NR_linux_poll 0x0007 -#define __NR_linux_ppoll 0x010f -#define __NR_linux_brk 0x000c -#define __NR_linux_sigreturn 0x000f -#define __NR_linux_lseek 0x0008 -#define __NR_linux_mmap 0x0009 -#define __NR_linux_msync 0x001a -#define __NR_linux_mprotect 0x000a -#define __NR_linux_munmap 0x000b -#define __NR_linux_sigaction 0x000d -#define __NR_linux_sigprocmask 0x000e -#define __NR_linux_ioctl 0x0010 -#define __NR_linux_pread 0x0011 -#define __NR_linux_pwrite 0x0012 -#define __NR_linux_readv 0x0013 -#define __NR_linux_writev 0x0014 -#define __NR_linux_access 0x0015 -#define __NR_linux_pipe 0x0016 -#define __NR_linux_select 0x0017 -#define __NR_linux_pselect6 0x010e -#define __NR_linux_sched_yield 0x0018 -#define __NR_linux_mremap 0x0019 -#define __NR_linux_mincore 0x001b -#define __NR_linux_madvise 0x001c -#define __NR_linux_shmget 0x001d -#define __NR_linux_shmat 0x001e -#define __NR_linux_shmctl 0x001f -#define __NR_linux_dup 0x0020 -#define __NR_linux_dup2 0x0021 -#define __NR_linux_pause 0x0022 -#define __NR_linux_nanosleep 0x0023 -#define __NR_linux_getitimer 0x0024 -#define __NR_linux_setitimer 0x0026 -#define __NR_linux_alarm 0x0025 -#define __NR_linux_getpid 0x0027 -#define __NR_linux_sendfile 0x0028 -#define __NR_linux_socket 0x0029 -#define __NR_linux_connect 0x002a -#define __NR_linux_accept 0x002b -#define __NR_linux_sendto 0x002c -#define __NR_linux_recvfrom 0x002d -#define __NR_linux_sendmsg 0x002e -#define __NR_linux_recvmsg 0x002f -#define __NR_linux_shutdown 0x0030 -#define __NR_linux_bind 0x0031 -#define __NR_linux_listen 0x0032 -#define __NR_linux_getsockname 0x0033 -#define __NR_linux_getpeername 0x0034 -#define __NR_linux_socketpair 0x0035 -#define __NR_linux_setsockopt 0x0036 -#define __NR_linux_getsockopt 0x0037 -#define __NR_linux_fork 0x0039 -#define __NR_linux_vfork 0x003a -#define __NR_linux_execve 0x003b -#define __NR_linux_wait4 0x003d -#define __NR_linux_kill 0x003e -#define __NR_linux_clone 0x0038 -#define __NR_linux_tkill 0x00c8 -#define __NR_linux_futex 0x00ca -#define __NR_linux_set_robust_list 0x0111 -#define __NR_linux_get_robust_list 0x0112 -#define __NR_linux_uname 0x003f -#define __NR_linux_semget 0x0040 -#define __NR_linux_semop 0x0041 -#define __NR_linux_semctl 0x0042 -#define __NR_linux_shmdt 0x0043 -#define __NR_linux_msgget 0x0044 -#define __NR_linux_msgsnd 0x0045 -#define __NR_linux_msgrcv 0x0046 -#define __NR_linux_msgctl 0x0047 -#define __NR_linux_fcntl 0x0048 -#define __NR_linux_flock 0x0049 -#define __NR_linux_fsync 0x004a -#define __NR_linux_fdatasync 0x004b -#define __NR_linux_truncate 0x004c -#define __NR_linux_ftruncate 0x004d -#define __NR_linux_getcwd 0x004f -#define __NR_linux_chdir 0x0050 -#define __NR_linux_fchdir 0x0051 -#define __NR_linux_rename 0x0052 -#define __NR_linux_mkdir 0x0053 -#define __NR_linux_rmdir 0x0054 -#define __NR_linux_creat 0x0055 -#define __NR_linux_link 0x0056 -#define __NR_linux_unlink 0x0057 -#define __NR_linux_symlink 0x0058 -#define __NR_linux_readlink 0x0059 -#define __NR_linux_chmod 0x005a -#define __NR_linux_fchmod 0x005b -#define __NR_linux_chown 0x005c -#define __NR_linux_fchown 0x005d -#define __NR_linux_lchown 0x005e -#define __NR_linux_umask 0x005f -#define __NR_linux_gettimeofday 0x0060 -#define __NR_linux_getrlimit 0x0061 -#define __NR_linux_getrusage 0x0062 -#define __NR_linux_sysinfo 0x0063 -#define __NR_linux_times 0x0064 -#define __NR_linux_ptrace 0x0065 -#define __NR_linux_syslog 0x0067 -#define __NR_linux_getuid 0x0066 -#define __NR_linux_getgid 0x0068 -#define __NR_linux_getppid 0x006e -#define __NR_linux_getpgrp 0x006f -#define __NR_linux_setsid 0x0070 -#define __NR_linux_getsid 0x007c -#define __NR_linux_getpgid 0x0079 -#define __NR_linux_setpgid 0x006d -#define __NR_linux_geteuid 0x006b -#define __NR_linux_getegid 0x006c -#define __NR_linux_getgroups 0x0073 -#define __NR_linux_setgroups 0x0074 -#define __NR_linux_setreuid 0x0071 -#define __NR_linux_setregid 0x0072 -#define __NR_linux_setuid 0x0069 -#define __NR_linux_setgid 0x006a -#define __NR_linux_setresuid 0x0075 -#define __NR_linux_setresgid 0x0077 -#define __NR_linux_getresuid 0x0076 -#define __NR_linux_getresgid 0x0078 -#define __NR_linux_sigpending 0x007f -#define __NR_linux_sigsuspend 0x0082 -#define __NR_linux_sigaltstack 0x0083 -#define __NR_linux_mknod 0x0085 -#define __NR_linux_mknodat 0x0103 -#define __NR_linux_statfs 0x0089 -#define __NR_linux_fstatfs 0x008a -#define __NR_linux_getpriority 0x008c -#define __NR_linux_setpriority 0x008d -#define __NR_linux_mlock 0x0095 -#define __NR_linux_munlock 0x0096 -#define __NR_linux_mlockall 0x0097 -#define __NR_linux_munlockall 0x0098 -#define __NR_linux_setrlimit 0x00a0 -#define __NR_linux_chroot 0x00a1 -#define __NR_linux_sync 0x00a2 -#define __NR_linux_acct 0x00a3 -#define __NR_linux_settimeofday 0x00a4 -#define __NR_linux_mount 0x00a5 -#define __NR_linux_reboot 0x00a9 -#define __NR_linux_quotactl 0x00b3 -#define __NR_linux_setfsuid 0x007a -#define __NR_linux_setfsgid 0x007b -#define __NR_linux_capget 0x007d -#define __NR_linux_capset 0x007e -#define __NR_linux_sigtimedwait 0x0080 -#define __NR_linux_rt_sigqueueinfo 0x0081 -#define __NR_linux_personality 0x0087 -#define __NR_linux_ustat 0x0088 -#define __NR_linux_sysfs 0x008b -#define __NR_linux_sched_setparam 0x008e -#define __NR_linux_sched_getparam 0x008f -#define __NR_linux_sched_setscheduler 0x0090 -#define __NR_linux_sched_getscheduler 0x0091 -#define __NR_linux_sched_get_priority_max 0x0092 -#define __NR_linux_sched_get_priority_min 0x0093 -#define __NR_linux_sched_rr_get_interval 0x0094 -#define __NR_linux_vhangup 0x0099 -#define __NR_linux_modify_ldt 0x009a -#define __NR_linux_pivot_root 0x009b -#define __NR_linux__sysctl 0x009c -#define __NR_linux_prctl 0x009d -#define __NR_linux_arch_prctl 0x009e -#define __NR_linux_adjtimex 0x009f -#define __NR_linux_umount2 0x00a6 -#define __NR_linux_swapon 0x00a7 -#define __NR_linux_swapoff 0x00a8 -#define __NR_linux_sethostname 0x00aa -#define __NR_linux_setdomainname 0x00ab -#define __NR_linux_iopl 0x00ac -#define __NR_linux_ioperm 0x00ad -#define __NR_linux_init_module 0x00af -#define __NR_linux_delete_module 0x00b0 -#define __NR_linux_gettid 0x00ba -#define __NR_linux_readahead 0x00bb -#define __NR_linux_setxattr 0x00bc -#define __NR_linux_fsetxattr 0x00be -#define __NR_linux_getxattr 0x00bf -#define __NR_linux_fgetxattr 0x00c1 -#define __NR_linux_listxattr 0x00c2 -#define __NR_linux_flistxattr 0x00c4 -#define __NR_linux_removexattr 0x00c5 -#define __NR_linux_fremovexattr 0x00c7 -#define __NR_linux_lsetxattr 0x00bd -#define __NR_linux_lgetxattr 0x00c0 -#define __NR_linux_llistxattr 0x00c3 -#define __NR_linux_lremovexattr 0x00c6 -#define __NR_linux_sched_setaffinity 0x00cb -#define __NR_linux_sched_getaffinity 0x00cc -#define __NR_linux_io_setup 0x00ce -#define __NR_linux_io_destroy 0x00cf -#define __NR_linux_io_getevents 0x00d0 -#define __NR_linux_io_submit 0x00d1 -#define __NR_linux_io_cancel 0x00d2 -#define __NR_linux_lookup_dcookie 0x00d4 -#define __NR_linux_epoll_create 0x00d5 -#define __NR_linux_epoll_wait 0x00e8 -#define __NR_linux_epoll_ctl 0x00e9 -#define __NR_linux_getdents 0x00d9 -#define __NR_linux_set_tid_address 0x00da -#define __NR_linux_restart_syscall 0x00db -#define __NR_linux_semtimedop 0x00dc -#define __NR_linux_fadvise 0x00dd -#define __NR_linux_timer_create 0x00de -#define __NR_linux_timer_settime 0x00df -#define __NR_linux_timer_gettime 0x00e0 -#define __NR_linux_timer_getoverrun 0x00e1 -#define __NR_linux_timer_delete 0x00e2 -#define __NR_linux_clock_settime 0x00e3 -#define __NR_linux_clock_gettime 0x00e4 -#define __NR_linux_clock_getres 0x00e5 -#define __NR_linux_clock_nanosleep 0x00e6 -#define __NR_linux_tgkill 0x00ea -#define __NR_linux_mbind 0x00ed -#define __NR_linux_set_mempolicy 0x00ee -#define __NR_linux_get_mempolicy 0x00ef -#define __NR_linux_mq_open 0x00f0 -#define __NR_linux_mq_unlink 0x00f1 -#define __NR_linux_mq_timedsend 0x00f2 -#define __NR_linux_mq_timedreceive 0x00f3 -#define __NR_linux_mq_notify 0x00f4 -#define __NR_linux_mq_getsetattr 0x00f5 -#define __NR_linux_kexec_load 0x00f6 -#define __NR_linux_waitid 0x00f7 -#define __NR_linux_add_key 0x00f8 -#define __NR_linux_request_key 0x00f9 -#define __NR_linux_keyctl 0x00fa -#define __NR_linux_ioprio_set 0x00fb -#define __NR_linux_ioprio_get 0x00fc -#define __NR_linux_inotify_init 0x00fd -#define __NR_linux_inotify_add_watch 0x00fe -#define __NR_linux_inotify_rm_watch 0x00ff -#define __NR_linux_openat 0x0101 -#define __NR_linux_mkdirat 0x0102 -#define __NR_linux_fchownat 0x0104 -#define __NR_linux_utime 0x0084 -#define __NR_linux_utimes 0x00eb -#define __NR_linux_futimesat 0x0105 -#define __NR_linux_fstatat 0x0106 -#define __NR_linux_unlinkat 0x0107 -#define __NR_linux_renameat 0x0108 -#define __NR_linux_linkat 0x0109 -#define __NR_linux_symlinkat 0x010a -#define __NR_linux_readlinkat 0x010b -#define __NR_linux_fchmodat 0x010c -#define __NR_linux_faccessat 0x010d -#define __NR_linux_unshare 0x0110 -#define __NR_linux_splice 0x0113 -#define __NR_linux_tee 0x0114 -#define __NR_linux_sync_file_range 0x0115 -#define __NR_linux_vmsplice 0x0116 -#define __NR_linux_migrate_pages 0x0100 -#define __NR_linux_move_pages 0x0117 -#define __NR_linux_preadv 0x0127 -#define __NR_linux_pwritev 0x0128 -#define __NR_linux_utimensat 0x0118 -#define __NR_linux_fallocate 0x011d -#define __NR_linux_accept4 0x0120 -#define __NR_linux_dup3 0x0124 -#define __NR_linux_pipe2 0x0125 -#define __NR_linux_epoll_pwait 0x0119 -#define __NR_linux_epoll_create1 0x0123 -#define __NR_linux_perf_event_open 0x012a -#define __NR_linux_inotify_init1 0x0126 -#define __NR_linux_rt_tgsigqueueinfo 0x0129 -#define __NR_linux_signalfd 0x011a -#define __NR_linux_signalfd4 0x0121 -#define __NR_linux_eventfd 0x011c -#define __NR_linux_eventfd2 0x0122 -#define __NR_linux_timerfd_create 0x011b -#define __NR_linux_timerfd_settime 0x011e -#define __NR_linux_timerfd_gettime 0x011f -#define __NR_linux_recvmmsg 0x012b -#define __NR_linux_fanotify_init 0x012c -#define __NR_linux_fanotify_mark 0x012d -#define __NR_linux_prlimit 0x012e -#define __NR_linux_name_to_handle_at 0x012f -#define __NR_linux_open_by_handle_at 0x0130 -#define __NR_linux_clock_adjtime 0x0131 -#define __NR_linux_syncfs 0x0132 -#define __NR_linux_sendmmsg 0x0133 -#define __NR_linux_setns 0x0134 -#define __NR_linux_getcpu 0x0135 -#define __NR_linux_process_vm_readv 0x0136 -#define __NR_linux_process_vm_writev 0x0137 -#define __NR_linux_kcmp 0x0138 -#define __NR_linux_finit_module 0x0139 -#define __NR_linux_sched_setattr 0x013a -#define __NR_linux_sched_getattr 0x013b -#define __NR_linux_renameat2 0x013c -#define __NR_linux_seccomp 0x013d -#define __NR_linux_getrandom 0x013e -#define __NR_linux_memfd_create 0x013f -#define __NR_linux_kexec_file_load 0x0140 -#define __NR_linux_bpf 0x0141 -#define __NR_linux_execveat 0x0142 -#define __NR_linux_userfaultfd 0x0143 -#define __NR_linux_membarrier 0x0144 -#define __NR_linux_mlock2 0x0145 -#define __NR_linux_copy_file_range 0x0146 -#define __NR_linux_preadv2 0x0147 -#define __NR_linux_pwritev2 0x0148 -#define __NR_linux_pkey_mprotect 0x0149 -#define __NR_linux_pkey_alloc 0x014a -#define __NR_linux_pkey_free 0x014b -#define __NR_linux_statx 0x014c -#define __NR_linux_io_pgetevents 0x014d -#define __NR_linux_rseq 0x014e -#define __NR_linux_pidfd_send_signal 0x01a8 -#define __NR_linux_io_uring_setup 0x01a9 -#define __NR_linux_io_uring_enter 0x01aa -#define __NR_linux_io_uring_register 0x01ab +#define __NR_linux_exit 0x003c +#define __NR_linux_exit_group 0x00e7 +#define __NR_linux_read 0x0000 +#define __NR_linux_write 0x0001 +#define __NR_linux_open 0x0002 +#define __NR_linux_close 0x0003 +#define __NR_linux_stat 0x0004 +#define __NR_linux_fstat 0x0005 +#define __NR_linux_lstat 0x0006 +#define __NR_linux_poll 0x0007 +#define __NR_linux_ppoll 0x010f +#define __NR_linux_brk 0x000c +#define __NR_linux_sigreturn 0x000f +#define __NR_linux_lseek 0x0008 +#define __NR_linux_mmap 0x0009 +#define __NR_linux_msync 0x001a +#define __NR_linux_mprotect 0x000a +#define __NR_linux_munmap 0x000b +#define __NR_linux_sigaction 0x000d +#define __NR_linux_sigprocmask 0x000e +#define __NR_linux_ioctl 0x0010 +#define __NR_linux_pread 0x0011 +#define __NR_linux_pwrite 0x0012 +#define __NR_linux_readv 0x0013 +#define __NR_linux_writev 0x0014 +#define __NR_linux_access 0x0015 +#define __NR_linux_pipe 0x0016 +#define __NR_linux_select 0x0017 +#define __NR_linux_pselect6 0x010e +#define __NR_linux_sched_yield 0x0018 +#define __NR_linux_mremap 0x0019 +#define __NR_linux_mincore 0x001b +#define __NR_linux_madvise 0x001c +#define __NR_linux_shmget 0x001d +#define __NR_linux_shmat 0x001e +#define __NR_linux_shmctl 0x001f +#define __NR_linux_dup 0x0020 +#define __NR_linux_dup2 0x0021 +#define __NR_linux_pause 0x0022 +#define __NR_linux_nanosleep 0x0023 +#define __NR_linux_getitimer 0x0024 +#define __NR_linux_setitimer 0x0026 +#define __NR_linux_alarm 0x0025 +#define __NR_linux_getpid 0x0027 +#define __NR_linux_sendfile 0x0028 +#define __NR_linux_socket 0x0029 +#define __NR_linux_connect 0x002a +#define __NR_linux_accept 0x002b +#define __NR_linux_sendto 0x002c +#define __NR_linux_recvfrom 0x002d +#define __NR_linux_sendmsg 0x002e +#define __NR_linux_recvmsg 0x002f +#define __NR_linux_shutdown 0x0030 +#define __NR_linux_bind 0x0031 +#define __NR_linux_listen 0x0032 +#define __NR_linux_getsockname 0x0033 +#define __NR_linux_getpeername 0x0034 +#define __NR_linux_socketpair 0x0035 +#define __NR_linux_setsockopt 0x0036 +#define __NR_linux_getsockopt 0x0037 +#define __NR_linux_fork 0x0039 +#define __NR_linux_vfork 0x003a +#define __NR_linux_execve 0x003b +#define __NR_linux_wait4 0x003d +#define __NR_linux_kill 0x003e +#define __NR_linux_clone 0x0038 +#define __NR_linux_tkill 0x00c8 +#define __NR_linux_futex 0x00ca +#define __NR_linux_set_robust_list 0x0111 +#define __NR_linux_get_robust_list 0x0112 +#define __NR_linux_uname 0x003f +#define __NR_linux_semget 0x0040 +#define __NR_linux_semop 0x0041 +#define __NR_linux_semctl 0x0042 +#define __NR_linux_shmdt 0x0043 +#define __NR_linux_msgget 0x0044 +#define __NR_linux_msgsnd 0x0045 +#define __NR_linux_msgrcv 0x0046 +#define __NR_linux_msgctl 0x0047 +#define __NR_linux_fcntl 0x0048 +#define __NR_linux_flock 0x0049 +#define __NR_linux_fsync 0x004a +#define __NR_linux_fdatasync 0x004b +#define __NR_linux_truncate 0x004c +#define __NR_linux_ftruncate 0x004d +#define __NR_linux_getcwd 0x004f +#define __NR_linux_chdir 0x0050 +#define __NR_linux_fchdir 0x0051 +#define __NR_linux_rename 0x0052 +#define __NR_linux_mkdir 0x0053 +#define __NR_linux_rmdir 0x0054 +#define __NR_linux_creat 0x0055 +#define __NR_linux_link 0x0056 +#define __NR_linux_unlink 0x0057 +#define __NR_linux_symlink 0x0058 +#define __NR_linux_readlink 0x0059 +#define __NR_linux_chmod 0x005a +#define __NR_linux_fchmod 0x005b +#define __NR_linux_chown 0x005c +#define __NR_linux_fchown 0x005d +#define __NR_linux_lchown 0x005e +#define __NR_linux_umask 0x005f +#define __NR_linux_gettimeofday 0x0060 +#define __NR_linux_getrlimit 0x0061 +#define __NR_linux_getrusage 0x0062 +#define __NR_linux_sysinfo 0x0063 +#define __NR_linux_times 0x0064 +#define __NR_linux_ptrace 0x0065 +#define __NR_linux_syslog 0x0067 +#define __NR_linux_getuid 0x0066 +#define __NR_linux_getgid 0x0068 +#define __NR_linux_getppid 0x006e +#define __NR_linux_getpgrp 0x006f +#define __NR_linux_setsid 0x0070 +#define __NR_linux_getsid 0x007c +#define __NR_linux_getpgid 0x0079 +#define __NR_linux_setpgid 0x006d +#define __NR_linux_geteuid 0x006b +#define __NR_linux_getegid 0x006c +#define __NR_linux_getgroups 0x0073 +#define __NR_linux_setgroups 0x0074 +#define __NR_linux_setreuid 0x0071 +#define __NR_linux_setregid 0x0072 +#define __NR_linux_setuid 0x0069 +#define __NR_linux_setgid 0x006a +#define __NR_linux_setresuid 0x0075 +#define __NR_linux_setresgid 0x0077 +#define __NR_linux_getresuid 0x0076 +#define __NR_linux_getresgid 0x0078 +#define __NR_linux_sigpending 0x007f +#define __NR_linux_sigsuspend 0x0082 +#define __NR_linux_sigaltstack 0x0083 +#define __NR_linux_mknod 0x0085 +#define __NR_linux_mknodat 0x0103 +#define __NR_linux_statfs 0x0089 +#define __NR_linux_fstatfs 0x008a +#define __NR_linux_getpriority 0x008c +#define __NR_linux_setpriority 0x008d +#define __NR_linux_mlock 0x0095 +#define __NR_linux_munlock 0x0096 +#define __NR_linux_mlockall 0x0097 +#define __NR_linux_munlockall 0x0098 +#define __NR_linux_setrlimit 0x00a0 +#define __NR_linux_chroot 0x00a1 +#define __NR_linux_sync 0x00a2 +#define __NR_linux_acct 0x00a3 +#define __NR_linux_settimeofday 0x00a4 +#define __NR_linux_mount 0x00a5 +#define __NR_linux_reboot 0x00a9 +#define __NR_linux_quotactl 0x00b3 +#define __NR_linux_setfsuid 0x007a +#define __NR_linux_setfsgid 0x007b +#define __NR_linux_capget 0x007d +#define __NR_linux_capset 0x007e +#define __NR_linux_sigtimedwait 0x0080 +#define __NR_linux_rt_sigqueueinfo 0x0081 +#define __NR_linux_personality 0x0087 +#define __NR_linux_ustat 0x0088 +#define __NR_linux_sysfs 0x008b +#define __NR_linux_sched_setparam 0x008e +#define __NR_linux_sched_getparam 0x008f +#define __NR_linux_sched_setscheduler 0x0090 +#define __NR_linux_sched_getscheduler 0x0091 +#define __NR_linux_sched_get_priority_max 0x0092 +#define __NR_linux_sched_get_priority_min 0x0093 +#define __NR_linux_sched_rr_get_interval 0x0094 +#define __NR_linux_vhangup 0x0099 +#define __NR_linux_modify_ldt 0x009a +#define __NR_linux_pivot_root 0x009b +#define __NR_linux__sysctl 0x009c +#define __NR_linux_prctl 0x009d +#define __NR_linux_arch_prctl 0x009e +#define __NR_linux_adjtimex 0x009f +#define __NR_linux_umount2 0x00a6 +#define __NR_linux_swapon 0x00a7 +#define __NR_linux_swapoff 0x00a8 +#define __NR_linux_sethostname 0x00aa +#define __NR_linux_setdomainname 0x00ab +#define __NR_linux_iopl 0x00ac +#define __NR_linux_ioperm 0x00ad +#define __NR_linux_init_module 0x00af +#define __NR_linux_delete_module 0x00b0 +#define __NR_linux_gettid 0x00ba +#define __NR_linux_readahead 0x00bb +#define __NR_linux_setxattr 0x00bc +#define __NR_linux_fsetxattr 0x00be +#define __NR_linux_getxattr 0x00bf +#define __NR_linux_fgetxattr 0x00c1 +#define __NR_linux_listxattr 0x00c2 +#define __NR_linux_flistxattr 0x00c4 +#define __NR_linux_removexattr 0x00c5 +#define __NR_linux_fremovexattr 0x00c7 +#define __NR_linux_lsetxattr 0x00bd +#define __NR_linux_lgetxattr 0x00c0 +#define __NR_linux_llistxattr 0x00c3 +#define __NR_linux_lremovexattr 0x00c6 +#define __NR_linux_sched_setaffinity 0x00cb +#define __NR_linux_sched_getaffinity 0x00cc +#define __NR_linux_io_setup 0x00ce +#define __NR_linux_io_destroy 0x00cf +#define __NR_linux_io_getevents 0x00d0 +#define __NR_linux_io_submit 0x00d1 +#define __NR_linux_io_cancel 0x00d2 +#define __NR_linux_lookup_dcookie 0x00d4 +#define __NR_linux_epoll_create 0x00d5 +#define __NR_linux_epoll_wait 0x00e8 +#define __NR_linux_epoll_ctl 0x00e9 +#define __NR_linux_getdents 0x00d9 +#define __NR_linux_set_tid_address 0x00da +#define __NR_linux_restart_syscall 0x00db +#define __NR_linux_semtimedop 0x00dc +#define __NR_linux_fadvise 0x00dd +#define __NR_linux_timer_create 0x00de +#define __NR_linux_timer_settime 0x00df +#define __NR_linux_timer_gettime 0x00e0 +#define __NR_linux_timer_getoverrun 0x00e1 +#define __NR_linux_timer_delete 0x00e2 +#define __NR_linux_clock_settime 0x00e3 +#define __NR_linux_clock_gettime 0x00e4 +#define __NR_linux_clock_getres 0x00e5 +#define __NR_linux_clock_nanosleep 0x00e6 +#define __NR_linux_tgkill 0x00ea +#define __NR_linux_mbind 0x00ed +#define __NR_linux_set_mempolicy 0x00ee +#define __NR_linux_get_mempolicy 0x00ef +#define __NR_linux_mq_open 0x00f0 +#define __NR_linux_mq_unlink 0x00f1 +#define __NR_linux_mq_timedsend 0x00f2 +#define __NR_linux_mq_timedreceive 0x00f3 +#define __NR_linux_mq_notify 0x00f4 +#define __NR_linux_mq_getsetattr 0x00f5 +#define __NR_linux_kexec_load 0x00f6 +#define __NR_linux_waitid 0x00f7 +#define __NR_linux_add_key 0x00f8 +#define __NR_linux_request_key 0x00f9 +#define __NR_linux_keyctl 0x00fa +#define __NR_linux_ioprio_set 0x00fb +#define __NR_linux_ioprio_get 0x00fc +#define __NR_linux_inotify_init 0x00fd +#define __NR_linux_inotify_add_watch 0x00fe +#define __NR_linux_inotify_rm_watch 0x00ff +#define __NR_linux_openat 0x0101 +#define __NR_linux_mkdirat 0x0102 +#define __NR_linux_fchownat 0x0104 +#define __NR_linux_utime 0x0084 +#define __NR_linux_utimes 0x00eb +#define __NR_linux_futimesat 0x0105 +#define __NR_linux_fstatat 0x0106 +#define __NR_linux_unlinkat 0x0107 +#define __NR_linux_renameat 0x0108 +#define __NR_linux_linkat 0x0109 +#define __NR_linux_symlinkat 0x010a +#define __NR_linux_readlinkat 0x010b +#define __NR_linux_fchmodat 0x010c +#define __NR_linux_faccessat 0x010d +#define __NR_linux_unshare 0x0110 +#define __NR_linux_splice 0x0113 +#define __NR_linux_tee 0x0114 +#define __NR_linux_sync_file_range 0x0115 +#define __NR_linux_vmsplice 0x0116 +#define __NR_linux_migrate_pages 0x0100 +#define __NR_linux_move_pages 0x0117 +#define __NR_linux_preadv 0x0127 +#define __NR_linux_pwritev 0x0128 +#define __NR_linux_utimensat 0x0118 +#define __NR_linux_fallocate 0x011d +#define __NR_linux_accept4 0x0120 +#define __NR_linux_dup3 0x0124 +#define __NR_linux_pipe2 0x0125 +#define __NR_linux_epoll_pwait 0x0119 +#define __NR_linux_epoll_create1 0x0123 +#define __NR_linux_perf_event_open 0x012a +#define __NR_linux_inotify_init1 0x0126 +#define __NR_linux_rt_tgsigqueueinfo 0x0129 +#define __NR_linux_signalfd 0x011a +#define __NR_linux_signalfd4 0x0121 +#define __NR_linux_eventfd 0x011c +#define __NR_linux_eventfd2 0x0122 +#define __NR_linux_timerfd_create 0x011b +#define __NR_linux_timerfd_settime 0x011e +#define __NR_linux_timerfd_gettime 0x011f +#define __NR_linux_recvmmsg 0x012b +#define __NR_linux_fanotify_init 0x012c +#define __NR_linux_fanotify_mark 0x012d +#define __NR_linux_prlimit 0x012e +#define __NR_linux_name_to_handle_at 0x012f +#define __NR_linux_open_by_handle_at 0x0130 +#define __NR_linux_clock_adjtime 0x0131 +#define __NR_linux_syncfs 0x0132 +#define __NR_linux_sendmmsg 0x0133 +#define __NR_linux_setns 0x0134 +#define __NR_linux_getcpu 0x0135 +#define __NR_linux_process_vm_readv 0x0136 +#define __NR_linux_process_vm_writev 0x0137 +#define __NR_linux_kcmp 0x0138 +#define __NR_linux_finit_module 0x0139 +#define __NR_linux_sched_setattr 0x013a +#define __NR_linux_sched_getattr 0x013b +#define __NR_linux_renameat2 0x013c +#define __NR_linux_seccomp 0x013d +#define __NR_linux_getrandom 0x013e +#define __NR_linux_memfd_create 0x013f +#define __NR_linux_kexec_file_load 0x0140 +#define __NR_linux_bpf 0x0141 +#define __NR_linux_execveat 0x0142 +#define __NR_linux_userfaultfd 0x0143 +#define __NR_linux_membarrier 0x0144 +#define __NR_linux_mlock2 0x0145 +#define __NR_linux_copy_file_range 0x0146 +#define __NR_linux_preadv2 0x0147 +#define __NR_linux_pwritev2 0x0148 +#define __NR_linux_pkey_mprotect 0x0149 +#define __NR_linux_pkey_alloc 0x014a +#define __NR_linux_pkey_free 0x014b +#define __NR_linux_statx 0x014c +#define __NR_linux_io_pgetevents 0x014d +#define __NR_linux_rseq 0x014e +#define __NR_linux_pidfd_send_signal 0x01a8 +#define __NR_linux_io_uring_setup 0x01a9 +#define __NR_linux_io_uring_enter 0x01aa +#define __NR_linux_io_uring_register 0x01ab +#define __NR_linux_open_tree 0x01ac +#define __NR_linux_move_mount 0x01ad +#define __NR_linux_fsopen 0x01ae +#define __NR_linux_fsconfig 0x01af +#define __NR_linux_fsmount 0x01b0 +#define __NR_linux_fspick 0x01b1 +#define __NR_linux_pidfd_open 0x01b2 +#define __NR_linux_clone3 0x01b3 +#define __NR_linux_close_range 0x01b4 +#define __NR_linux_openat2 0x01b5 +#define __NR_linux_pidfd_getfd 0x01b6 +#define __NR_linux_faccessat2 0x01b7 +#define __NR_linux_process_madvise 0x01b8 +#define __NR_linux_epoll_pwait2 0x01b9 +#define __NR_linux_mount_setattr 0x01ba +#define __NR_linux_quotactl_fd 0x01bb +#define __NR_linux_landlock_create_ruleset 0x01bc +#define __NR_linux_landlock_add_rule 0x01bd +#define __NR_linux_landlock_restrict_self 0x01be +#define __NR_linux_memfd_secret 0x01bf +#define __NR_linux_process_mrelease 0x01c0 +#define __NR_linux_futex_waitv 0x01c1 +#define __NR_linux_set_mempolicy_home_node 0x01c2 +#define __NR_linux_sys_unveil 0x0fff #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_NRLINUX_H_ */ diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index b8f7af124..86fbc666d 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -399,7 +399,6 @@ scall memfd_secret 0xfffffffffffff1bf globl scall process_mrelease 0xfffffffffffff1c0 globl scall futex_waitv 0xfffffffffffff1c1 globl scall set_mempolicy_home_node 0xfffffffffffff1c2 globl -scall sys_unveil 0xfff072ffffffffff globl # The Fifth Bell System Interface, Community Edition # » besiyata dishmaya @@ -799,7 +798,7 @@ scall sendsyslog 0xfff070ffffffffff globl scall setrtable 0xfff136ffffffffff globl scall swapctl 0x10f0c1ffffffffff globl scall thrkill 0xfff077ffffffffff globl -scall unveil 0xfff072ffffffffff globl +scall sys_unveil 0xfff072ffffffffff globl hidden # The Fifth Bell System Interface, Community Edition # » beyond the pale diff --git a/libc/testlib/testrunner.c b/libc/testlib/testrunner.c index e32c4a39d..b004ff2b3 100644 --- a/libc/testlib/testrunner.c +++ b/libc/testlib/testrunner.c @@ -20,6 +20,7 @@ #include "libc/bits/atomic.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" +#include "libc/calls/state.internal.h" #include "libc/calls/strace.internal.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigset.h" @@ -63,7 +64,7 @@ void testlib_finish(void) { void testlib_error_enter(const char *file, const char *func) { atomic_fetch_sub_explicit(&__ftrace, 1, memory_order_relaxed); atomic_fetch_sub_explicit(&__strace, 1, memory_order_relaxed); - _spinlock(&testlib_error_lock); + if (!__vforked) _spinlock(&testlib_error_lock); if (!IsWindows()) sys_getpid(); /* make strace easier to read */ if (!IsWindows()) sys_getpid(); if (g_testlib_shoulddebugbreak) { diff --git a/test/libc/mem/life.c b/test/libc/mem/life.c new file mode 100644 index 000000000..9407a24e9 --- /dev/null +++ b/test/libc/mem/life.c @@ -0,0 +1,22 @@ +/*-*- 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. │ +╚─────────────────────────────────────────────────────────────────────────────*/ + +int main(int argc, char *argv[]) { + return 42; +} diff --git a/test/libc/mem/test.mk b/test/libc/mem/test.mk index 72bd64e96..e547852ac 100644 --- a/test/libc/mem/test.mk +++ b/test/libc/mem/test.mk @@ -42,8 +42,11 @@ TEST_LIBC_MEM_DIRECTDEPS = \ LIBC_STR \ LIBC_STUBS \ LIBC_SYSV \ - LIBC_THREAD \ + LIBC_SYSV_CALLS \ LIBC_TESTLIB \ + LIBC_THREAD \ + LIBC_X \ + LIBC_ZIPOS \ THIRD_PARTY_DLMALLOC \ THIRD_PARTY_LIBCXX @@ -58,11 +61,34 @@ o/$(MODE)/test/libc/mem/%.com.dbg: \ $(TEST_LIBC_MEM_DEPS) \ o/$(MODE)/test/libc/mem/%.o \ o/$(MODE)/test/libc/mem/mem.pkg \ + o/$(MODE)/test/libc/mem/life.elf.zip.o \ $(LIBC_TESTMAIN) \ $(CRT) \ $(APE_NO_MODIFY_SELF) @$(APELINK) +o/$(MODE)/test/libc/mem/life.com.dbg: \ + $(LIBC_RUNTIME) \ + o/$(MODE)/test/libc/mem/life.o \ + $(CRT) \ + $(APE) + @$(APELINK) + +o/$(MODE)/test/libc/mem/life.elf: \ + o/$(MODE)/tool/build/assimilate.com \ + o/$(MODE)/test/libc/mem/life.com + @$(COMPILE) -ACP -T$@ \ + build/bootstrap/cp.com \ + o/$(MODE)/test/libc/mem/life.com \ + o/$(MODE)/test/libc/mem/life.elf + @$(COMPILE) -AASSIMILATE -T$@ \ + o/$(MODE)/tool/build/assimilate.com \ + o/$(MODE)/test/libc/mem/life.elf + +o/$(MODE)/test/libc/mem/life.elf.zip.o: \ + ZIPOBJ_FLAGS += \ + -B + $(TEST_LIBC_MEM_OBJS): \ DEFAULT_CCFLAGS += \ -fno-builtin diff --git a/test/libc/mem/unveil_test.c b/test/libc/mem/unveil_test.c new file mode 100644 index 000000000..d17cd69db --- /dev/null +++ b/test/libc/mem/unveil_test.c @@ -0,0 +1,198 @@ +/*-*- 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/landlock.h" +#include "libc/calls/struct/dirent.h" +#include "libc/calls/struct/stat.h" +#include "libc/dce.h" +#include "libc/errno.h" +#include "libc/intrin/kprintf.h" +#include "libc/mem/io.h" +#include "libc/runtime/gc.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/s.h" +#include "libc/testlib/testlib.h" +#include "libc/x/x.h" + +STATIC_YOINK("zip_uri_support"); + +#define EACCES_OR_ENOENT (IsOpenbsd() ? ENOENT : EACCES) + +#define SPAWN() \ + { \ + int ws, pid; \ + ASSERT_NE(-1, (pid = fork())); \ + if (!pid) { + +#define EXITS(rc) \ + _Exit(0); \ + } \ + ASSERT_NE(-1, wait(&ws)); \ + ASSERT_TRUE(WIFEXITED(ws)); \ + ASSERT_EQ(rc, WEXITSTATUS(ws)); \ + } + +char testlib_enable_tmp_setup_teardown; + +struct stat st; + +static bool SupportsLandlock(void) { + int e = errno; + bool r = landlock_create_ruleset(0, 0, LANDLOCK_CREATE_RULESET_VERSION) >= 0; + errno = e; + return r; +} + +__attribute__((__constructor__)) static void init(void) { + if (!(IsLinux() && SupportsLandlock()) && !IsOpenbsd()) exit(0); +} + +void SetUp(void) { + // make sure zipos maps executable into memory early + ASSERT_SYS(0, 0, stat("/zip/life.elf", &st)); +} + +int extract(const char *from, const char *to, int mode) { + int fdin, fdout; + if ((fdin = open(from, O_RDONLY)) == -1) return -1; + if ((fdout = creat(to, mode)) == -1) { + close(fdin); + return -1; + } + if (_copyfd(fdin, fdout, -1) == -1) { + close(fdout); + close(fdin); + return -1; + } + return close(fdout) | close(fdin); +} + +TEST(unveil, api_differences) { + SPAWN(); + ASSERT_SYS(0, 0, stat("/", &st)); + ASSERT_SYS(0, 0, unveil(".", "rw")); + if (IsOpenbsd()) { + // openbsd imposes restrictions immediately + ASSERT_SYS(ENOENT, -1, open("/", O_RDONLY | O_DIRECTORY)); + } else { + // restrictions on linux don't go into effect until unveil(0,0) + ASSERT_SYS(0, 3, open("/", O_RDONLY | O_DIRECTORY)); + ASSERT_SYS(0, 0, close(3)); + } + ASSERT_SYS(0, 0, unveil(0, 0)); + // error numbers are inconsistent + ASSERT_SYS(EACCES_OR_ENOENT, -1, open("/", O_RDONLY | O_DIRECTORY)); + // wut + if (IsLinux()) { + ASSERT_SYS(0, 3, open("/", O_PATH)); // wut + ASSERT_SYS(0, 0, stat("/", &st)); // wut + } + EXITS(0); +} + +TEST(unveil, rx_readOnlyPreexistingExecutable_worksFine) { + SPAWN(); + ASSERT_SYS(0, 0, mkdir("folder", 0755)); + ASSERT_SYS(0, 0, extract("/zip/life.elf", "folder/life.elf", 0755)); + ASSERT_SYS(0, 0, unveil("folder", "rx")); + ASSERT_SYS(0, 0, unveil(0, 0)); + SPAWN(); + execv("folder/life.elf", (char *[]){"folder/life.elf", 0}); + EXITS(42); + EXITS(0); +} + +TEST(unveil, r_noExecutePreexistingExecutable_raisesEacces) { + SPAWN(); + ASSERT_SYS(0, 0, mkdir("folder", 0755)); + ASSERT_SYS(0, 0, extract("/zip/life.elf", "folder/life.elf", 0755)); + ASSERT_SYS(0, 0, unveil("folder", "r")); + ASSERT_SYS(0, 0, unveil(0, 0)); + SPAWN(); + ASSERT_SYS(EACCES, -1, + execv("folder/life.elf", (char *[]){"folder/life.elf", 0})); + EXITS(0); + EXITS(0); +} + +TEST(unveil, rwc_createExecutableFile_isAllowedButCantBeRun) { + SPAWN(); + ASSERT_SYS(0, 0, mkdir("folder", 0755)); + ASSERT_SYS(0, 0, unveil("folder", "rwc")); + ASSERT_SYS(0, 0, unveil(0, 0)); + ASSERT_SYS(0, 0, extract("/zip/life.elf", "folder/life.elf", 0755)); + SPAWN(); + ASSERT_SYS(0, 0, stat("folder/life.elf", &st)); + ASSERT_SYS(EACCES, -1, + execv("folder/life.elf", (char *[]){"folder/life.elf", 0})); + EXITS(0); + EXITS(0); +} + +TEST(unveil, rwcx_createExecutableFile_canAlsoBeRun) { + SPAWN(); + ASSERT_SYS(0, 0, mkdir("folder", 0755)); + ASSERT_SYS(0, 0, unveil("folder", "rwcx")); + ASSERT_SYS(0, 0, unveil(0, 0)); + ASSERT_SYS(0, 0, extract("/zip/life.elf", "folder/life.elf", 0755)); + SPAWN(); + ASSERT_SYS(0, 0, stat("folder/life.elf", &st)); + execv("folder/life.elf", (char *[]){"folder/life.elf", 0}); + EXITS(42); + EXITS(0); +} + +TEST(unveil, dirfdHacking_doesntWork) { + SPAWN(); + ASSERT_SYS(0, 0, mkdir("jail", 0755)); + ASSERT_SYS(0, 0, mkdir("garden", 0755)); + ASSERT_SYS(0, 0, touch("garden/secret.txt", 0644)); + ASSERT_SYS(0, 3, open("garden", O_RDONLY | O_DIRECTORY)); + ASSERT_SYS(0, 0, unveil("jail", "rw")); + ASSERT_SYS(0, 0, unveil(0, 0)); + ASSERT_SYS(EACCES_OR_ENOENT, -1, openat(3, "secret.txt", O_RDONLY)); + EXITS(0); +} + +TEST(unveil, overlappingDirectories_inconsistentBehavior) { + SPAWN(); + ASSERT_SYS(0, 0, makedirs("f1/f2", 0755)); + ASSERT_SYS(0, 0, extract("/zip/life.elf", "f1/f2/life.elf", 0755)); + ASSERT_SYS(0, 0, unveil("f1", "x")); + ASSERT_SYS(0, 0, unveil("f1/f2", "r")); + ASSERT_SYS(0, 0, unveil(0, 0)); + if (IsOpenbsd()) { + // OpenBSD favors the most restrictive policy + SPAWN(); + ASSERT_SYS(0, 0, stat("f1/f2/life.elf", &st)); + ASSERT_SYS(EACCES, -1, + execv("f1/f2/life.elf", (char *[]){"f1/f2/life.elf", 0})); + EXITS(0); + } else { + // Landlock (Linux) uses the union of policies + SPAWN(); + ASSERT_SYS(0, 0, stat("f1/f2/life.elf", &st)); + execv("f1/f2/life.elf", (char *[]){"f1/f2/life.elf", 0}); + EXITS(42); + } + EXITS(0); +}