diff --git a/libc/calls/pledge.c b/libc/calls/pledge.c index d7b746a9c..e3c93e7c6 100644 --- a/libc/calls/pledge.c +++ b/libc/calls/pledge.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/bits/likely.h" #include "libc/calls/calls.h" #include "libc/calls/strace.internal.h" #include "libc/calls/struct/bpf.h" @@ -233,6 +234,7 @@ static const uint16_t kPledgeLinuxWpath[] = { static const uint16_t kPledgeLinuxCpath[] = { __NR_linux_open | CREATONLY, // __NR_linux_openat | CREATONLY, // + __NR_linux_creat | RESTRICT, // __NR_linux_rename, // __NR_linux_renameat, // __NR_linux_renameat2, // @@ -445,20 +447,18 @@ static const struct sock_filter kFilterEnd[] = { BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA)), }; -static bool AppendFilter(struct Filter *f, struct sock_filter *p, size_t n) { - if (f->n + n <= ARRAYLEN(f->p)) { - memcpy(f->p + f->n, p, n * sizeof(*f->p)); - f->n += n; - return true; - } else { - enomem(); - return false; +static void AppendFilter(struct Filter *f, struct sock_filter *p, size_t n) { + if (UNLIKELY(f->n + n > ARRAYLEN(f->p))) { + asm("hlt"); // need to increase array size + unreachable; } + memcpy(f->p + f->n, p, n * sizeof(*f->p)); + f->n += n; } // SYSCALL is only allowed in the .privileged section // We assume program image is loaded in 32-bit spaces -static bool AppendOriginVerification(struct Filter *f, long ipromises) { +static void AppendOriginVerification(struct Filter *f) { intptr_t x = (intptr_t)__privileged_start; intptr_t y = (intptr_t)__privileged_end; assert(0 < x && x < y && y < INT_MAX); @@ -472,7 +472,7 @@ static bool AppendOriginVerification(struct Filter *f, long ipromises) { /*L6*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L7*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The first argument of sys_clone_linux() must NOT have: @@ -481,7 +481,7 @@ static bool AppendOriginVerification(struct Filter *f, long ipromises) { // - CLONE_PTRACE (0x00002000) // - CLONE_UNTRACED (0x00800000) // -static bool AllowCloneRestrict(struct Filter *f) { +static void AllowCloneRestrict(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_clone, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), @@ -491,7 +491,7 @@ static bool AllowCloneRestrict(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The first argument of sys_clone_linux() must have: @@ -508,7 +508,7 @@ static bool AllowCloneRestrict(struct Filter *f) { // - CLONE_PTRACE (0x00002000) // - CLONE_UNTRACED (0x00800000) // -static bool AllowCloneThread(struct Filter *f) { +static void AllowCloneThread(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_clone, 0, 9 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), @@ -521,7 +521,7 @@ static bool AllowCloneThread(struct Filter *f) { /*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L9*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The second argument of ioctl() must be one of: @@ -531,7 +531,7 @@ static bool AllowCloneThread(struct Filter *f) { // - FIOCLEX (0x5451) // - FIONCLEX (0x5450) // -static bool AllowIoctlStdio(struct Filter *f) { +static void AllowIoctlStdio(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_ioctl, 0, 8 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -543,7 +543,7 @@ static bool AllowIoctlStdio(struct Filter *f) { /*L7*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L8*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The second argument of ioctl() must be one of: @@ -561,7 +561,7 @@ static bool AllowIoctlStdio(struct Filter *f) { // - TCSBRK (0x5409) // - TIOCSBRK (0x5427) // -static bool AllowIoctlTty(struct Filter *f) { +static void AllowIoctlTty(struct Filter *f) { static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_ioctl, 0, 16 - 1), /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -581,7 +581,7 @@ static bool AllowIoctlTty(struct Filter *f) { /*L15*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L16*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The level argument of setsockopt() must be one of: @@ -609,7 +609,7 @@ static bool AllowIoctlTty(struct Filter *f) { // - TCP_FASTOPEN (0x17) // - TCP_FASTOPEN_CONNECT (0x1e) // -static bool AllowSetsockoptRestrict(struct Filter *f) { +static void AllowSetsockoptRestrict(struct Filter *f) { static const int nr = __NR_linux_setsockopt; static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, nr, 0, 21 - 1), @@ -636,7 +636,7 @@ static bool AllowSetsockoptRestrict(struct Filter *f) { /*L20*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L21*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The level argument of getsockopt() must be one of: @@ -653,7 +653,7 @@ static bool AllowSetsockoptRestrict(struct Filter *f) { // - SO_RCVTIMEO (0x14) // - SO_SNDTIMEO (0x15) // -static bool AllowGetsockoptRestrict(struct Filter *f) { +static void AllowGetsockoptRestrict(struct Filter *f) { static const int nr = __NR_linux_getsockopt; static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, nr, 0, 13 - 1), @@ -671,7 +671,7 @@ static bool AllowGetsockoptRestrict(struct Filter *f) { /*L12*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L13*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The flags parameter of mmap() must not have: @@ -680,7 +680,7 @@ static bool AllowGetsockoptRestrict(struct Filter *f) { // - MAP_NONBLOCK (0x10000) // - MAP_HUGETLB (0x40000) // -static bool AllowMmapExec(struct Filter *f) { +static void AllowMmapExec(struct Filter *f) { intptr_t y = (intptr_t)__privileged_end; assert(0 < y && y < INT_MAX); struct sock_filter fragment[] = { @@ -692,7 +692,7 @@ static bool AllowMmapExec(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The prot parameter of mmap() may only have: @@ -708,7 +708,7 @@ static bool AllowMmapExec(struct Filter *f) { // - MAP_NONBLOCK (0x10000) // - MAP_HUGETLB (0x40000) // -static bool AllowMmapNoexec(struct Filter *f) { +static void AllowMmapNoexec(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_mmap, 0, 9 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), // prot @@ -721,7 +721,7 @@ static bool AllowMmapNoexec(struct Filter *f) { /*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L9*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The prot parameter of mprotect() may only have: @@ -730,7 +730,7 @@ static bool AllowMmapNoexec(struct Filter *f) { // - PROT_READ (1) // - PROT_WRITE (2) // -static bool AllowMprotectNoexec(struct Filter *f) { +static void AllowMprotectNoexec(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_mprotect, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), // prot @@ -740,84 +740,119 @@ static bool AllowMprotectNoexec(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The open() system call is permitted only when // // - (flags & O_ACCMODE) == O_RDONLY // -static bool AllowOpenReadonly(struct Filter *f) { - static const struct sock_filter fragment[] = { - /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_open, 0, 6 - 1), - /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), - /*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, O_ACCMODE), - /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_RDONLY, 0, 1), - /*L4*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), - /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), - /*L6*/ /* next filter */ - }; - return AppendFilter(f, PLEDGE(fragment)); -} - // The flags parameter of open() must not have: // -// - O_WRONLY (1) -// - O_RDWR (2) +// - O_CREAT (000000100) +// - O_TRUNC (000001000) +// - __O_TMPFILE (020000000) // -static bool AllowOpenatReadonly(struct Filter *f) { +static void AllowOpenReadonly(struct Filter *f) { static const struct sock_filter fragment[] = { - /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_openat, 0, 6 - 1), + /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_open, 0, 9 - 1), + /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), + /*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, O_ACCMODE), + /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_RDONLY, 0, 8 - 4), + /*L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), + /*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 020001100), + /*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), + /*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + /*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), + /*L9*/ /* next filter */ + }; + AppendFilter(f, PLEDGE(fragment)); +} + +// The open() system call is permitted only when +// +// - (flags & O_ACCMODE) == O_RDONLY +// +// The flags parameter of open() must not have: +// +// - O_CREAT (000000100) +// - O_TRUNC (000001000) +// - __O_TMPFILE (020000000) +// +static void AllowOpenatReadonly(struct Filter *f) { + static const struct sock_filter fragment[] = { + /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_openat, 0, 9 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), /*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, O_ACCMODE), - /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_RDONLY, 0, 1), - /*L4*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), - /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), - /*L6*/ /* next filter */ + /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_RDONLY, 0, 8 - 4), + /*L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), + /*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 020001100), + /*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), + /*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + /*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), + /*L9*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } +// The open() system call is permitted only when +// +// - (flags & O_ACCMODE) == O_WRONLY +// - (flags & O_ACCMODE) == O_RDWR +// // The open() flags parameter must not contain // -// - O_CREAT (000000100) -// - O_TMPFILE (020200000) +// - O_CREAT (000000100) +// - __O_TMPFILE (020000000) // -static bool AllowOpenWriteonly(struct Filter *f) { +static void AllowOpenWriteonly(struct Filter *f) { static const struct sock_filter fragment[] = { - /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_open, 0, 6 - 1), - /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), - /*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 020200100), - /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), - /*L4*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), - /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), - /*L6*/ /* next filter */ + /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_open, 0, 10 - 1), + /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), + /* L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, O_ACCMODE), + /* L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_WRONLY, 1, 0), + /* L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_RDWR, 0, 9 - 5), + /* L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), + /* L6*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 020000100), + /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), + /* L8*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + /* L9*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), + /*L10*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } +// The open() system call is permitted only when +// +// - (flags & O_ACCMODE) == O_WRONLY +// - (flags & O_ACCMODE) == O_RDWR +// // The openat() flags parameter must not contain // -// - O_CREAT (000000100) -// - O_TMPFILE (020200000) +// - O_CREAT (000000100) +// - __O_TMPFILE (020000000) // -static bool AllowOpenatWriteonly(struct Filter *f) { +static void AllowOpenatWriteonly(struct Filter *f) { static const struct sock_filter fragment[] = { - /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_openat, 0, 6 - 1), - /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), - /*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 020200100), - /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), - /*L4*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), - /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), - /*L6*/ /* next filter */ + /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_openat, 0, 10 - 1), + /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), + /* L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, O_ACCMODE), + /* L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_WRONLY, 1, 0), + /* L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, O_RDWR, 0, 9 - 5), + /* L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), + /* L6*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 020000100), + /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), + /* L8*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + /* L9*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), + /*L10*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // If the flags parameter of open() has one of: // -// - O_CREAT (000000100) -// - O_TMPFILE (020200000) +// - O_CREAT (000000100) +// - __O_TMPFILE (020000000) // // Then the mode parameter must not have: // @@ -825,7 +860,7 @@ static bool AllowOpenatWriteonly(struct Filter *f) { // - S_ISGID (02000 setgid) // - S_ISUID (04000 setuid) // -static bool AllowOpenCreatonly(struct Filter *f) { +static void AllowOpenCreatonly(struct Filter *f) { static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_open, 0, 12 - 1), /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -841,13 +876,13 @@ static bool AllowOpenCreatonly(struct Filter *f) { /*L11*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L12*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // If the flags parameter of openat() has one of: // -// - O_CREAT (000000100) -// - O_TMPFILE (020200000) +// - O_CREAT (000000100) +// - __O_TMPFILE (020000000) // // Then the mode parameter must not have: // @@ -855,7 +890,7 @@ static bool AllowOpenCreatonly(struct Filter *f) { // - S_ISGID (02000 setgid) // - S_ISUID (04000 setuid) // -static bool AllowOpenatCreatonly(struct Filter *f) { +static void AllowOpenatCreatonly(struct Filter *f) { static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_openat, 0, 12 - 1), /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), @@ -871,7 +906,26 @@ static bool AllowOpenatCreatonly(struct Filter *f) { /*L11*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L12*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); +} + +// Then the mode parameter must not have: +// +// - S_ISVTX (01000 sticky) +// - S_ISGID (02000 setgid) +// - S_ISUID (04000 setuid) +// +static void AllowCreatRestrict(struct Filter *f) { + static const struct sock_filter fragment[] = { + /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_creat, 0, 6 - 1), + /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), + /*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 07000), + /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1), + /*L4*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), + /*L6*/ /* next filter */ + }; + AppendFilter(f, PLEDGE(fragment)); } // The second argument of fcntl() must be one of: @@ -883,7 +937,7 @@ static bool AllowOpenatCreatonly(struct Filter *f) { // - F_GETFL (3) // - F_SETFL (4) // -static bool AllowFcntlStdio(struct Filter *f) { +static void AllowFcntlStdio(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_fcntl, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -893,7 +947,7 @@ static bool AllowFcntlStdio(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The second argument of fcntl() must be one of: @@ -902,7 +956,7 @@ static bool AllowFcntlStdio(struct Filter *f) { // - F_SETLK (6) // - F_SETLKW (7) // -static bool AllowFcntlLock(struct Filter *f) { +static void AllowFcntlLock(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_fcntl, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -912,14 +966,14 @@ static bool AllowFcntlLock(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The addr parameter of sendto() must be // // - NULL // -static bool AllowSendtoAddrless(struct Filter *f) { +static void AllowSendtoAddrless(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_sendto, 0, 7 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[4]) + 0), @@ -930,14 +984,14 @@ static bool AllowSendtoAddrless(struct Filter *f) { /*L6*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L7*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The sig parameter of sigaction() must NOT be // // - SIGSYS (31) // -static bool AllowSigactionNosigsys(struct Filter *f) { +static void AllowSigactionNosigsys(struct Filter *f) { static const int nr = __NR_linux_sigaction; static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, nr, 0, 5 - 1), @@ -947,7 +1001,7 @@ static bool AllowSigactionNosigsys(struct Filter *f) { /*L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L5*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The family parameter of socket() must be one of: @@ -972,7 +1026,7 @@ static bool AllowSigactionNosigsys(struct Filter *f) { // - IPPROTO_TCP (0x06) // - IPPROTO_UDP (0x11) // -static bool AllowSocketInet(struct Filter *f) { +static void AllowSocketInet(struct Filter *f) { static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_socket, 0, 15 - 1), /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), @@ -991,7 +1045,7 @@ static bool AllowSocketInet(struct Filter *f) { /*L14*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L15*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The family parameter of socket() must be one of: @@ -1013,7 +1067,7 @@ static bool AllowSocketInet(struct Filter *f) { // // - 0 // -static bool AllowSocketUnix(struct Filter *f) { +static void AllowSocketUnix(struct Filter *f) { static const struct sock_filter fragment[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_socket, 0, 11 - 1), /* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), @@ -1028,7 +1082,7 @@ static bool AllowSocketUnix(struct Filter *f) { /*L10*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L11*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The first parameter of prctl() can be any of @@ -1040,7 +1094,7 @@ static bool AllowSocketUnix(struct Filter *f) { // - PR_SET_NO_NEW_PRIVS (38) // - PR_CAPBSET_READ (23) // -static bool AllowPrctlStdio(struct Filter *f) { +static void AllowPrctlStdio(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_prctl, 0, 10 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), @@ -1054,7 +1108,7 @@ static bool AllowPrctlStdio(struct Filter *f) { /*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L9*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The mode parameter of chmod() can't have the following: @@ -1063,7 +1117,7 @@ static bool AllowPrctlStdio(struct Filter *f) { // - S_ISGID (02000 setgid) // - S_ISUID (04000 setuid) // -static bool AllowChmodNobits(struct Filter *f) { +static void AllowChmodNobits(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_chmod, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -1073,7 +1127,7 @@ static bool AllowChmodNobits(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The mode parameter of fchmod() can't have the following: @@ -1082,7 +1136,7 @@ static bool AllowChmodNobits(struct Filter *f) { // - S_ISGID (02000 setgid) // - S_ISUID (04000 setuid) // -static bool AllowFchmodNobits(struct Filter *f) { +static void AllowFchmodNobits(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_fchmod, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), @@ -1092,7 +1146,7 @@ static bool AllowFchmodNobits(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The mode parameter of fchmodat() can't have the following: @@ -1101,7 +1155,7 @@ static bool AllowFchmodNobits(struct Filter *f) { // - S_ISGID (02000 setgid) // - S_ISUID (04000 setuid) // -static bool AllowFchmodatNobits(struct Filter *f) { +static void AllowFchmodatNobits(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_fchmodat, 0, 6 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), @@ -1111,14 +1165,14 @@ static bool AllowFchmodatNobits(struct Filter *f) { /*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L6*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } // The new_limit parameter of prlimit() must be // // - NULL (0) // -static bool AllowPrlimitStdio(struct Filter *f) { +static void AllowPrlimitStdio(struct Filter *f) { static const struct sock_filter fragment[] = { /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_prlimit, 0, 7 - 1), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), @@ -1129,7 +1183,7 @@ static bool AllowPrlimitStdio(struct Filter *f) { /*L6*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L7*/ /* next filter */ }; - return AppendFilter(f, PLEDGE(fragment)); + AppendFilter(f, PLEDGE(fragment)); } static int CountUnspecial(const uint16_t *p, size_t len) { @@ -1142,7 +1196,7 @@ static int CountUnspecial(const uint16_t *p, size_t len) { return count; } -static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) { +static void AppendPledge(struct Filter *f, const uint16_t *p, size_t len) { int i, j, count; // handle ordinals which allow syscalls regardless of args @@ -1158,17 +1212,13 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) { count - j - 1, // jump if true displacement j == count - 1), // jump if false displacement }; - if (!AppendFilter(f, PLEDGE(fragment))) { - return false; - } + AppendFilter(f, PLEDGE(fragment)); ++j; } struct sock_filter fragment[] = { BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), }; - if (!AppendFilter(f, PLEDGE(fragment))) { - return false; - } + AppendFilter(f, PLEDGE(fragment)); } else { asm("hlt"); // list of ordinals exceeds max displacement unreachable; @@ -1180,123 +1230,113 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) { if (!(p[i] & SPECIAL)) continue; switch (p[i]) { case __NR_linux_mmap | EXEC: - if (!AllowMmapExec(f)) return false; + AllowMmapExec(f); break; case __NR_linux_mmap | NOEXEC: - if (!AllowMmapNoexec(f)) return false; + AllowMmapNoexec(f); break; case __NR_linux_mprotect | NOEXEC: - if (!AllowMprotectNoexec(f)) return false; + AllowMprotectNoexec(f); break; case __NR_linux_chmod | NOBITS: - if (!AllowChmodNobits(f)) return false; + AllowChmodNobits(f); break; case __NR_linux_fchmod | NOBITS: - if (!AllowFchmodNobits(f)) return false; + AllowFchmodNobits(f); break; case __NR_linux_fchmodat | NOBITS: - if (!AllowFchmodatNobits(f)) return false; + AllowFchmodatNobits(f); break; case __NR_linux_sigaction | NOSIGSYS: - if (!AllowSigactionNosigsys(f)) return false; + AllowSigactionNosigsys(f); break; case __NR_linux_prctl | STDIO: - if (!AllowPrctlStdio(f)) return false; + AllowPrctlStdio(f); break; case __NR_linux_open | CREATONLY: - if (!AllowOpenCreatonly(f)) return false; + AllowOpenCreatonly(f); break; case __NR_linux_openat | CREATONLY: - if (!AllowOpenatCreatonly(f)) return false; + AllowOpenatCreatonly(f); break; case __NR_linux_open | READONLY: - if (!AllowOpenReadonly(f)) return false; + AllowOpenReadonly(f); break; case __NR_linux_openat | READONLY: - if (!AllowOpenatReadonly(f)) return false; + AllowOpenatReadonly(f); break; case __NR_linux_open | WRITEONLY: - if (!AllowOpenWriteonly(f)) return false; + AllowOpenWriteonly(f); break; case __NR_linux_openat | WRITEONLY: - if (!AllowOpenatWriteonly(f)) return false; + AllowOpenatWriteonly(f); break; case __NR_linux_setsockopt | RESTRICT: - if (!AllowSetsockoptRestrict(f)) return false; + AllowSetsockoptRestrict(f); break; case __NR_linux_getsockopt | RESTRICT: - if (!AllowGetsockoptRestrict(f)) return false; + AllowGetsockoptRestrict(f); + break; + case __NR_linux_creat | RESTRICT: + AllowCreatRestrict(f); break; case __NR_linux_fcntl | STDIO: - if (!AllowFcntlStdio(f)) return false; + AllowFcntlStdio(f); break; case __NR_linux_fcntl | LOCK: - if (!AllowFcntlLock(f)) return false; + AllowFcntlLock(f); break; case __NR_linux_ioctl | RESTRICT: - if (!AllowIoctlStdio(f)) return false; + AllowIoctlStdio(f); break; case __NR_linux_ioctl | TTY: - if (!AllowIoctlTty(f)) return false; + AllowIoctlTty(f); break; case __NR_linux_socket | INET: - if (!AllowSocketInet(f)) return false; + AllowSocketInet(f); break; case __NR_linux_socket | UNIX: - if (!AllowSocketUnix(f)) return false; + AllowSocketUnix(f); break; case __NR_linux_sendto | ADDRLESS: - if (!AllowSendtoAddrless(f)) return false; + AllowSendtoAddrless(f); break; case __NR_linux_clone | RESTRICT: - if (!AllowCloneRestrict(f)) return false; + AllowCloneRestrict(f); break; case __NR_linux_clone | THREAD: - if (!AllowCloneThread(f)) return false; + AllowCloneThread(f); break; case __NR_linux_prlimit | STDIO: - if (!AllowPrlimitStdio(f)) return false; + AllowPrlimitStdio(f); break; default: asm("hlt"); // switch forgot to define a special ordinal unreachable; } } - - return true; } int sys_pledge_linux(unsigned long ipromises) { - bool ok = true; int i, rc = -1; struct Filter f; CheckLargeStackAllocation(&f, sizeof(f)); f.n = 0; - ipromises = ~ipromises; - if (AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) && - ((ipromises & (1ul << PROMISE_EXEC)) || - AppendOriginVerification(&f, ipromises)) && - AppendPledge(&f, kPledgeLinuxDefault, ARRAYLEN(kPledgeLinuxDefault))) { - for (i = 0; i < ARRAYLEN(kPledgeLinux); ++i) { - if ((ipromises & (1ul << i)) && kPledgeLinux[i].name) { - ipromises &= ~(1ul << i); - if (!AppendPledge(&f, kPledgeLinux[i].syscalls, kPledgeLinux[i].len)) { - ok = false; - rc = einval(); - break; - } - } - } - if (ipromises) { - ok = false; - rc = einval(); - } - if (ok && AppendFilter(&f, kFilterEnd, ARRAYLEN(kFilterEnd)) && - (rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) != -1) { - struct sock_fprog sandbox = {.len = f.n, .filter = f.p}; - rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox); + AppendFilter(&f, PLEDGE(kFilterStart)); + if (!(~ipromises & (1ul << PROMISE_EXEC))) { + AppendOriginVerification(&f); + } + AppendPledge(&f, PLEDGE(kPledgeLinuxDefault)); + for (i = 0; i < ARRAYLEN(kPledgeLinux); ++i) { + if (~ipromises & (1ul << i)) { + AppendPledge(&f, kPledgeLinux[i].syscalls, kPledgeLinux[i].len); } } + AppendFilter(&f, PLEDGE(kFilterEnd)); + if ((rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) != -1) { + struct sock_fprog sandbox = {.len = f.n, .filter = f.p}; + rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox); + } return rc; } @@ -1530,7 +1570,7 @@ int pledge(const char *promises, const char *execpromises) { } else { rc = sys_pledge(promises, execpromises); } - if (!rc && (IsOpenbsd() || getpid() == gettid())) { + if (!rc && (IsOpenbsd() || (IsLinux() && getpid() == gettid()))) { __promises = ipromises; __execpromises = iexecpromises; } diff --git a/libc/runtime/mapshared.c b/libc/runtime/mapshared.c new file mode 100644 index 000000000..f2f086504 --- /dev/null +++ b/libc/runtime/mapshared.c @@ -0,0 +1,41 @@ +/*-*- 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/weaken.h" +#include "libc/calls/calls.h" +#include "libc/errno.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.h" + +/** + * Creates anonymous shared memory mapping. + * + * @return memory map address on success, or null w/ errno + */ +void *_mapshared(size_t size) { + void *m; + m = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (m != MAP_FAILED) { + return m; + } + if (errno == ENOMEM && weaken(__oom_hook)) { + weaken(__oom_hook)(size); + } + return 0; +} diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index c3a16c559..13ba29ba8 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -48,6 +48,7 @@ void mcount(void); int _freestack(void *); unsigned long getauxval(unsigned long); void *_mapanon(size_t) attributeallocsize((1)) mallocesque; +void *_mapshared(size_t) attributeallocsize((1)) mallocesque; void *_mapstack(void) returnsaligned((FRAMESIZE)) mallocesque; int setjmp(jmp_buf) libcesque returnstwice paramsnonnull(); void longjmp(jmp_buf, int) libcesque wontreturn paramsnonnull(); diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index cc03f446f..1d24f4943 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -196,7 +196,7 @@ syscon open O_SEQUENTIAL 0 0 0 0 0 0x40000000 # kNtFileFlagSequen syscon open O_COMPRESSED 0 0 0 0 0 0x20000000 # kNtFileAttributeCompressed [SYNC libc/calls/open-nt.c] syscon open O_INDEXED 0 0 0 0 0 0x10000000 # !kNtFileAttributeNotContentIndexed [SYNC libc/calls/open-nt.c] syscon open O_CLOEXEC 0x00080000 0x01000000 0x00100000 0x00010000 0x00400000 0x00080000 # NT faked as Linux [SYNC libc/calls/open-nt.c] -syscon open O_TMPFILE 0x00410000 0 0 0 0 0x00410000 # Linux 3.11+ (c. 2013) & kNtFileAttributeTemporary|kNtFileFlagDeleteOnClose [SYNC libc/calls/open-nt.c] +syscon open O_TMPFILE 0x00410000 0 0 0 0 0x00410000 # Linux 3.11+ (c. 2013) __O_TMPFILE | O_DIRECTORY; kNtFileAttributeTemporary|kNtFileFlagDeleteOnClose [SYNC libc/calls/open-nt.c] syscon open O_SPARSE 0 0 0 0 0 0 # wut syscon open O_NONBLOCK 0x00000800 0x00000004 0x00000004 0x00000004 0x00000004 0x00000800 # bsd consensus syscon open O_ASYNC 0x00002000 0x00000040 0x00000040 0x00000040 0x00000040 0 # bsd consensus diff --git a/test/libc/calls/pledge_test.c b/test/libc/calls/pledge_test.c index 57d9a926a..06f8ab88c 100644 --- a/test/libc/calls/pledge_test.c +++ b/test/libc/calls/pledge_test.c @@ -54,6 +54,7 @@ #include "libc/testlib/testlib.h" #include "libc/thread/spawn.h" #include "libc/time/time.h" +#include "libc/x/x.h" STATIC_YOINK("zip_uri_support"); @@ -266,6 +267,30 @@ TEST(pledge, unix_forbidsInetSockets) { EXPECT_TRUE(WIFEXITED(ws) && !WEXITSTATUS(ws)); } +TEST(pledge, wpath_doesNotImplyRpath) { + int ws, pid; + bool *gotsome; + ASSERT_NE(-1, (gotsome = _mapshared(FRAMESIZE))); + ASSERT_SYS(0, 0, touch("foo", 0644)); + ASSERT_NE(-1, (pid = fork())); + if (!pid) { + ASSERT_SYS(0, 0, pledge("stdio wpath", 0)); + ASSERT_SYS(0, 3, open("foo", O_WRONLY)); + *gotsome = true; + ASSERT_SYS(EPERM, -1, open("foo", O_RDONLY)); + _Exit(0); + } + EXPECT_NE(-1, wait(&ws)); + ASSERT_TRUE(*gotsome); + if (IsOpenbsd()) { + ASSERT_TRUE(WIFSIGNALED(ws)); + ASSERT_EQ(SIGABRT, WTERMSIG(ws)); + } else { + ASSERT_TRUE(WIFEXITED(ws)); + ASSERT_EQ(0, WEXITSTATUS(ws)); + } +} + TEST(pledge, inet_forbidsOtherSockets) { if (IsOpenbsd()) return; // b/c testing linux bpf int ws, pid; @@ -378,6 +403,8 @@ TEST(pledge, open_rpath) { if (!pid) { ASSERT_SYS(0, 0, pledge("stdio rpath", 0)); ASSERT_SYS(0, 3, open("foo", O_RDONLY)); + ASSERT_SYS(EPERM, -1, open("foo", O_RDONLY | O_TRUNC)); + ASSERT_SYS(EPERM, -1, open("foo", O_RDONLY | O_TMPFILE)); ASSERT_SYS(EPERM, -1, open("foo", O_RDWR | O_TRUNC | O_CREAT, 0644)); ASSERT_SYS(EPERM, -1, open("foo", O_WRONLY | O_TRUNC | O_CREAT, 0644)); _Exit(0); @@ -393,9 +420,9 @@ TEST(pledge, open_wpath) { ASSERT_NE(-1, (pid = fork())); if (!pid) { ASSERT_SYS(0, 0, pledge("stdio wpath", 0)); - ASSERT_SYS(0, 3, open("foo", O_RDONLY)); ASSERT_SYS(EPERM, -1, open(".", O_RDWR | O_TMPFILE, 07644)); - ASSERT_SYS(0, 4, open("foo", O_WRONLY | O_TRUNC, 07644)); + ASSERT_SYS(0, 3, open("foo", O_WRONLY | O_TRUNC)); + ASSERT_SYS(0, 4, open("foo", O_RDWR)); ASSERT_SYS(EPERM, -1, open("foo", O_WRONLY | O_TRUNC | O_CREAT, 0644)); _Exit(0); } diff --git a/test/libc/calls/unveil_test.c b/test/libc/calls/unveil_test.c index 804e290bb..1aaa9cee6 100644 --- a/test/libc/calls/unveil_test.c +++ b/test/libc/calls/unveil_test.c @@ -351,8 +351,7 @@ TEST(unveil, isThreadSpecificOnLinux_isProcessWideOnOpenbsd) { TEST(unveil, usedTwice_forbidden_worksWithPledge) { int ws, pid; bool *gotsome; - ASSERT_NE(-1, (gotsome = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, -1, 0))); + ASSERT_NE(-1, (gotsome = _mapshared(FRAMESIZE))); ASSERT_NE(-1, (pid = fork())); if (!pid) { // install our first seccomp filter