mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-28 22:18:29 +00:00
Release pledge.com 1.7 and landlockmake.com 1.3
- pledge("chown") now supported - pledge("stdio") now allows killing self - Write tests for pselect() and ppoll()
This commit is contained in:
parent
255d834f8f
commit
ce588dd56b
19 changed files with 190 additions and 39 deletions
libc
calls
intrin
runtime
sock
test/libc
third_party/make
tool
|
@ -56,6 +56,7 @@
|
||||||
#define Sa_Restart 0x10000000
|
#define Sa_Restart 0x10000000
|
||||||
|
|
||||||
#define SPECIAL 0xf000
|
#define SPECIAL 0xf000
|
||||||
|
#define SELF 0x8000
|
||||||
#define ADDRLESS 0x2000
|
#define ADDRLESS 0x2000
|
||||||
#define INET 0x8000
|
#define INET 0x8000
|
||||||
#define LOCK 0x4000
|
#define LOCK 0x4000
|
||||||
|
@ -476,7 +477,6 @@ static const uint16_t kPledgeStdio[] = {
|
||||||
__NR_linux_sysinfo, //
|
__NR_linux_sysinfo, //
|
||||||
__NR_linux_fdatasync, //
|
__NR_linux_fdatasync, //
|
||||||
__NR_linux_ftruncate, //
|
__NR_linux_ftruncate, //
|
||||||
__NR_linux_getdents, //
|
|
||||||
__NR_linux_getrandom, //
|
__NR_linux_getrandom, //
|
||||||
__NR_linux_getgroups, //
|
__NR_linux_getgroups, //
|
||||||
__NR_linux_getpgid, //
|
__NR_linux_getpgid, //
|
||||||
|
@ -546,6 +546,8 @@ static const uint16_t kPledgeStdio[] = {
|
||||||
__NR_linux_sigprocmask, //
|
__NR_linux_sigprocmask, //
|
||||||
__NR_linux_sigsuspend, //
|
__NR_linux_sigsuspend, //
|
||||||
__NR_linux_sigpending, //
|
__NR_linux_sigpending, //
|
||||||
|
__NR_linux_kill | SELF, //
|
||||||
|
__NR_linux_tkill | SELF, //
|
||||||
__NR_linux_socketpair, //
|
__NR_linux_socketpair, //
|
||||||
__NR_linux_getrusage, //
|
__NR_linux_getrusage, //
|
||||||
__NR_linux_times, //
|
__NR_linux_times, //
|
||||||
|
@ -581,6 +583,7 @@ static const uint16_t kPledgeRpath[] = {
|
||||||
__NR_linux_readlinkat, //
|
__NR_linux_readlinkat, //
|
||||||
__NR_linux_statfs, //
|
__NR_linux_statfs, //
|
||||||
__NR_linux_fstatfs, //
|
__NR_linux_fstatfs, //
|
||||||
|
__NR_linux_getdents, //
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint16_t kPledgeWpath[] = {
|
static const uint16_t kPledgeWpath[] = {
|
||||||
|
@ -592,6 +595,7 @@ static const uint16_t kPledgeWpath[] = {
|
||||||
__NR_linux_lstat, //
|
__NR_linux_lstat, //
|
||||||
__NR_linux_fstatat, //
|
__NR_linux_fstatat, //
|
||||||
__NR_linux_access, //
|
__NR_linux_access, //
|
||||||
|
__NR_linux_truncate, //
|
||||||
__NR_linux_faccessat, //
|
__NR_linux_faccessat, //
|
||||||
__NR_linux_faccessat2, //
|
__NR_linux_faccessat2, //
|
||||||
__NR_linux_readlinkat, //
|
__NR_linux_readlinkat, //
|
||||||
|
@ -728,6 +732,13 @@ static const uint16_t kPledgeId[] = {
|
||||||
__NR_linux_setfsgid, //
|
__NR_linux_setfsgid, //
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint16_t kPledgeChown[] = {
|
||||||
|
__NR_linux_chown, //
|
||||||
|
__NR_linux_fchown, //
|
||||||
|
__NR_linux_lchown, //
|
||||||
|
__NR_linux_fchownat, //
|
||||||
|
};
|
||||||
|
|
||||||
static const uint16_t kPledgeSettime[] = {
|
static const uint16_t kPledgeSettime[] = {
|
||||||
__NR_linux_settimeofday, //
|
__NR_linux_settimeofday, //
|
||||||
__NR_linux_clock_adjtime, //
|
__NR_linux_clock_adjtime, //
|
||||||
|
@ -789,6 +800,7 @@ const struct Pledges kPledge[PROMISE_LEN_] = {
|
||||||
[PROMISE_PROT_EXEC] = {"prot_exec", PLEDGE(kPledgeProtExec)}, //
|
[PROMISE_PROT_EXEC] = {"prot_exec", PLEDGE(kPledgeProtExec)}, //
|
||||||
[PROMISE_VMINFO] = {"vminfo", PLEDGE(kPledgeVminfo)}, //
|
[PROMISE_VMINFO] = {"vminfo", PLEDGE(kPledgeVminfo)}, //
|
||||||
[PROMISE_TMPPATH] = {"tmppath", PLEDGE(kPledgeTmppath)}, //
|
[PROMISE_TMPPATH] = {"tmppath", PLEDGE(kPledgeTmppath)}, //
|
||||||
|
[PROMISE_CHOWN] = {"chown", PLEDGE(kPledgeChown)}, //
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct sock_filter kPledgeStart[] = {
|
static const struct sock_filter kPledgeStart[] = {
|
||||||
|
@ -993,7 +1005,7 @@ static privileged void MonitorSigSys(void) {
|
||||||
};
|
};
|
||||||
// we block changing sigsys once pledge is installed
|
// we block changing sigsys once pledge is installed
|
||||||
// so we aren't terribly concerned if this will fail
|
// so we aren't terribly concerned if this will fail
|
||||||
SigAction(Sigsys, &sa, 0);
|
if (SigAction(Sigsys, &sa, 0) == -1) asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
static privileged void AppendFilter(struct Filter *f, struct sock_filter *p,
|
static privileged void AppendFilter(struct Filter *f, struct sock_filter *p,
|
||||||
|
@ -1005,6 +1017,36 @@ static privileged void AppendFilter(struct Filter *f, struct sock_filter *p,
|
||||||
f->n += n;
|
f->n += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The first argument of kill() must be
|
||||||
|
//
|
||||||
|
// - getpid()
|
||||||
|
//
|
||||||
|
static privileged void AllowKillSelf(struct Filter *f) {
|
||||||
|
struct sock_filter fragment[] = {
|
||||||
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_kill, 0, 4),
|
||||||
|
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])),
|
||||||
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, GetPid(), 0, 1),
|
||||||
|
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||||
|
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||||
|
};
|
||||||
|
AppendFilter(f, PLEDGE(fragment));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first argument of tkill() must be
|
||||||
|
//
|
||||||
|
// - gettid()
|
||||||
|
//
|
||||||
|
static privileged void AllowTkillSelf(struct Filter *f) {
|
||||||
|
struct sock_filter fragment[] = {
|
||||||
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_tkill, 0, 4),
|
||||||
|
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])),
|
||||||
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, GetTid(), 0, 1),
|
||||||
|
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||||
|
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||||
|
};
|
||||||
|
AppendFilter(f, PLEDGE(fragment));
|
||||||
|
}
|
||||||
|
|
||||||
// The following system calls are allowed:
|
// The following system calls are allowed:
|
||||||
//
|
//
|
||||||
// - write(2) to allow logging
|
// - write(2) to allow logging
|
||||||
|
@ -1884,6 +1926,12 @@ static privileged void AppendPledge(struct Filter *f, //
|
||||||
case __NR_linux_prlimit | STDIO:
|
case __NR_linux_prlimit | STDIO:
|
||||||
AllowPrlimitStdio(f);
|
AllowPrlimitStdio(f);
|
||||||
break;
|
break;
|
||||||
|
case __NR_linux_kill | SELF:
|
||||||
|
AllowKillSelf(f);
|
||||||
|
break;
|
||||||
|
case __NR_linux_tkill | SELF:
|
||||||
|
AllowTkillSelf(f);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
AbortPledge("switch forgot to define a special ordinal");
|
AbortPledge("switch forgot to define a special ordinal");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
/**
|
/**
|
||||||
* Permits system operations, e.g.
|
* Permits system operations, e.g.
|
||||||
*
|
*
|
||||||
|
* __pledge_mode = PLEDGE_PENALTY_KILL_PROCESS | PLEDGE_STDERR_LOGGING;
|
||||||
* if (pledge("stdio rfile tty", 0)) {
|
* if (pledge("stdio rfile tty", 0)) {
|
||||||
* perror("pledge");
|
* perror("pledge");
|
||||||
* exit(1);
|
* exit(1);
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/sock/ppoll.h"
|
|
||||||
#include "libc/sock/struct/pollfd.h"
|
#include "libc/sock/struct/pollfd.h"
|
||||||
#include "libc/sock/struct/pollfd.internal.h"
|
#include "libc/sock/struct/pollfd.internal.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
@ -41,9 +40,14 @@
|
||||||
* poll(fds, nfds, timeout);
|
* poll(fds, nfds, timeout);
|
||||||
* sigprocmask(SIG_SETMASK, old, 0);
|
* sigprocmask(SIG_SETMASK, old, 0);
|
||||||
*
|
*
|
||||||
* Except it'll happen atomically if the kernel supports doing that. On
|
* Except it happens atomically when the kernel supports doing that. On
|
||||||
* kernel such as XNU and NetBSD which don't, this wrapper falls back to
|
* kernel such as XNU and NetBSD which don't, this wrapper will fall
|
||||||
* doing the thing described above.
|
* back to using the example above. Consider using pselect() which is
|
||||||
|
* atomic on all supported platforms.
|
||||||
|
*
|
||||||
|
* The Linux Kernel modifies the timeout parameter. This wrapper gives
|
||||||
|
* it a local variable due to POSIX requiring that `timeout` be const.
|
||||||
|
* If you need that information from the Linux Kernel use sys_ppoll().
|
||||||
*
|
*
|
||||||
* @param timeout if null will block indefinitely
|
* @param timeout if null will block indefinitely
|
||||||
* @param sigmask may be null in which case no mask change happens
|
* @param sigmask may be null in which case no mask change happens
|
||||||
|
@ -56,6 +60,7 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
|
||||||
int e, i, rc;
|
int e, i, rc;
|
||||||
uint64_t millis;
|
uint64_t millis;
|
||||||
sigset_t oldmask;
|
sigset_t oldmask;
|
||||||
|
struct timespec ts, *tsp;
|
||||||
|
|
||||||
if (IsAsan() && (!__asan_is_valid(fds, nfds * sizeof(struct pollfd)) ||
|
if (IsAsan() && (!__asan_is_valid(fds, nfds * sizeof(struct pollfd)) ||
|
||||||
(timeout && !__asan_is_valid(timeout, sizeof(timeout))) ||
|
(timeout && !__asan_is_valid(timeout, sizeof(timeout))) ||
|
||||||
|
@ -63,7 +68,13 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
|
||||||
rc = efault();
|
rc = efault();
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
e = errno;
|
e = errno;
|
||||||
rc = sys_ppoll(fds, nfds, timeout, sigmask);
|
if (timeout) {
|
||||||
|
ts = *timeout;
|
||||||
|
tsp = &ts;
|
||||||
|
} else {
|
||||||
|
tsp = 0;
|
||||||
|
}
|
||||||
|
rc = sys_ppoll(fds, nfds, tsp, sigmask, 8);
|
||||||
if (rc == -1 && errno == ENOSYS) {
|
if (rc == -1 && errno == ENOSYS) {
|
||||||
errno = e;
|
errno = e;
|
||||||
if (!timeout ||
|
if (!timeout ||
|
||||||
|
@ -71,9 +82,9 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
|
||||||
&millis)) {
|
&millis)) {
|
||||||
millis = -1;
|
millis = -1;
|
||||||
}
|
}
|
||||||
if (sigmask) sys_sigprocmask(SIG_SETMASK, sigmask, &oldmask);
|
if (sigmask) sigprocmask(SIG_SETMASK, sigmask, &oldmask);
|
||||||
rc = poll(fds, nfds, millis);
|
rc = poll(fds, nfds, millis);
|
||||||
if (sigmask) sys_sigprocmask(SIG_SETMASK, &oldmask, 0);
|
if (sigmask) sigprocmask(SIG_SETMASK, &oldmask, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!timeout || __builtin_add_overflow(
|
if (!timeout || __builtin_add_overflow(
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
#define PROMISE_PROT_EXEC 18
|
#define PROMISE_PROT_EXEC 18
|
||||||
#define PROMISE_VMINFO 19
|
#define PROMISE_VMINFO 19
|
||||||
#define PROMISE_TMPPATH 20
|
#define PROMISE_TMPPATH 20
|
||||||
#define PROMISE_LEN_ 21
|
#define PROMISE_CHOWN 21
|
||||||
|
#define PROMISE_LEN_ 22
|
||||||
|
|
||||||
#define PLEDGED(x) ((~__promises >> PROMISE_##x) & 1)
|
#define PLEDGED(x) ((~__promises >> PROMISE_##x) & 1)
|
||||||
|
|
||||||
|
|
|
@ -354,8 +354,9 @@ static wontreturn void NetbsdThreadMain(void *arg, // rdi
|
||||||
int *ztid, // r8
|
int *ztid, // r8
|
||||||
int *ptid) { // r9
|
int *ptid) { // r9
|
||||||
int ax, dx;
|
int ax, dx;
|
||||||
ax = *tid;
|
// TODO(jart): Why are we seeing flakes where *tid is zero?
|
||||||
*ptid = ax;
|
// ax = *tid;
|
||||||
|
ax = sys_gettid();
|
||||||
*ctid = ax;
|
*ctid = ax;
|
||||||
func(arg, ax);
|
func(arg, ax);
|
||||||
// we no longer use the stack after this point
|
// we no longer use the stack after this point
|
||||||
|
@ -402,6 +403,7 @@ static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,
|
||||||
sp -= sizeof(int);
|
sp -= sizeof(int);
|
||||||
sp = sp & -alignof(int);
|
sp = sp & -alignof(int);
|
||||||
tid = (int *)sp;
|
tid = (int *)sp;
|
||||||
|
*tid = 0;
|
||||||
|
|
||||||
// align the stack
|
// align the stack
|
||||||
sp = sp & -16;
|
sp = sp & -16;
|
||||||
|
|
|
@ -73,8 +73,8 @@ ssize_t sys_sendto(int, const void *, size_t, int, const void *,
|
||||||
uint32_t) hidden;
|
uint32_t) hidden;
|
||||||
int32_t sys_select(int32_t, fd_set *, fd_set *, fd_set *,
|
int32_t sys_select(int32_t, fd_set *, fd_set *, fd_set *,
|
||||||
struct timeval *) hidden;
|
struct timeval *) hidden;
|
||||||
int sys_pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
|
int sys_pselect(int, fd_set *, fd_set *, fd_set *, struct timespec *,
|
||||||
const sigset_t *);
|
const void *) hidden;
|
||||||
int sys_setsockopt(int, int, int, const void *, uint32_t) hidden;
|
int sys_setsockopt(int, int, int, const void *, uint32_t) hidden;
|
||||||
int32_t sys_epoll_create(int32_t) hidden;
|
int32_t sys_epoll_create(int32_t) hidden;
|
||||||
int32_t sys_epoll_ctl(int32_t, int32_t, int32_t, void *) hidden;
|
int32_t sys_epoll_ctl(int32_t, int32_t, int32_t, void *) hidden;
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_SOCK_PPOLL_H_
|
|
||||||
#define COSMOPOLITAN_LIBC_SOCK_PPOLL_H_
|
|
||||||
#include "libc/calls/struct/sigset.h"
|
|
||||||
#include "libc/calls/struct/timespec.h"
|
|
||||||
#include "libc/sock/struct/pollfd.h"
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
int ppoll(struct pollfd *, uint64_t, const struct timespec *,
|
|
||||||
const struct sigset *);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_SOCK_PPOLL_H_ */
|
|
|
@ -29,6 +29,19 @@
|
||||||
/**
|
/**
|
||||||
* Does what poll() does except with bitset API.
|
* Does what poll() does except with bitset API.
|
||||||
*
|
*
|
||||||
|
* This function is the same as saying:
|
||||||
|
*
|
||||||
|
* sigset_t old;
|
||||||
|
* sigprocmask(SIG_SETMASK, sigmask, &old);
|
||||||
|
* select(nfds, readfds, writefds, exceptfds, timeout);
|
||||||
|
* sigprocmask(SIG_SETMASK, old, 0);
|
||||||
|
*
|
||||||
|
* Except it happens atomically.
|
||||||
|
*
|
||||||
|
* The Linux Kernel modifies the timeout parameter. This wrapper gives
|
||||||
|
* it a local variable due to POSIX requiring that `timeout` be const.
|
||||||
|
* If you need that information from the Linux Kernel use sys_pselect.
|
||||||
|
*
|
||||||
* This system call is supported on all platforms. It's like select()
|
* This system call is supported on all platforms. It's like select()
|
||||||
* except that it atomically changes the sigprocmask() during the op.
|
* except that it atomically changes the sigprocmask() during the op.
|
||||||
*/
|
*/
|
||||||
|
@ -37,6 +50,11 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||||
int rc;
|
int rc;
|
||||||
sigset_t oldmask;
|
sigset_t oldmask;
|
||||||
struct timeval tv, *tvp;
|
struct timeval tv, *tvp;
|
||||||
|
struct timespec ts, *tsp;
|
||||||
|
struct {
|
||||||
|
sigset_t *s;
|
||||||
|
size_t n;
|
||||||
|
} ss;
|
||||||
if (nfds < 0) {
|
if (nfds < 0) {
|
||||||
rc = einval();
|
rc = einval();
|
||||||
} else if (IsAsan() &&
|
} else if (IsAsan() &&
|
||||||
|
@ -46,6 +64,16 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))) ||
|
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))) ||
|
||||||
(sigmask && !__asan_is_valid(sigmask, sizeof(*sigmask))))) {
|
(sigmask && !__asan_is_valid(sigmask, sizeof(*sigmask))))) {
|
||||||
rc = efault();
|
rc = efault();
|
||||||
|
} else if (IsLinux()) {
|
||||||
|
if (timeout) {
|
||||||
|
ts = *timeout;
|
||||||
|
tsp = &ts;
|
||||||
|
} else {
|
||||||
|
tsp = 0;
|
||||||
|
}
|
||||||
|
ss.s = sigmask;
|
||||||
|
ss.n = 8;
|
||||||
|
rc = sys_pselect(nfds, readfds, writefds, exceptfds, tsp, &ss);
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
rc = sys_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
rc = sys_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
|
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
|
||||||
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
|
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
|
||||||
|
#include "libc/calls/struct/sigset.h"
|
||||||
|
#include "libc/calls/struct/timespec.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
@ -10,6 +12,8 @@ struct pollfd {
|
||||||
};
|
};
|
||||||
|
|
||||||
int poll(struct pollfd *, uint64_t, int32_t);
|
int poll(struct pollfd *, uint64_t, int32_t);
|
||||||
|
int ppoll(struct pollfd *, uint64_t, const struct timespec *,
|
||||||
|
const struct sigset *);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -8,7 +8,7 @@ COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
int32_t sys_poll(struct pollfd *, uint64_t, signed) hidden;
|
int32_t sys_poll(struct pollfd *, uint64_t, signed) hidden;
|
||||||
int sys_ppoll(struct pollfd *, size_t, const struct timespec *,
|
int sys_ppoll(struct pollfd *, size_t, const struct timespec *,
|
||||||
const sigset_t *);
|
const sigset_t *, size_t);
|
||||||
int sys_poll_metal(struct pollfd *, size_t, unsigned);
|
int sys_poll_metal(struct pollfd *, size_t, unsigned);
|
||||||
int sys_poll_nt(struct pollfd *, uint64_t, uint64_t *, const sigset_t *) hidden;
|
int sys_poll_nt(struct pollfd *, uint64_t, uint64_t *, const sigset_t *) hidden;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/pledge.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/log/libfatal.internal.h"
|
#include "libc/log/libfatal.internal.h"
|
||||||
#include "libc/nexgen32e/rdtsc.h"
|
#include "libc/nexgen32e/rdtsc.h"
|
||||||
|
@ -39,10 +41,21 @@
|
||||||
#include "tool/decode/lib/flagger.h"
|
#include "tool/decode/lib/flagger.h"
|
||||||
#include "tool/decode/lib/pollnames.h"
|
#include "tool/decode/lib/pollnames.h"
|
||||||
|
|
||||||
|
bool gotsig;
|
||||||
|
|
||||||
void SetUpOnce(void) {
|
void SetUpOnce(void) {
|
||||||
|
__pledge_mode = PLEDGE_PENALTY_KILL_PROCESS | PLEDGE_STDERR_LOGGING;
|
||||||
ASSERT_SYS(0, 0, pledge("stdio proc inet", 0));
|
ASSERT_SYS(0, 0, pledge("stdio proc inet", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetUp(void) {
|
||||||
|
gotsig = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnSig(int sig) {
|
||||||
|
gotsig = true;
|
||||||
|
}
|
||||||
|
|
||||||
dontdiscard char *FormatPollFd(struct pollfd p[2]) {
|
dontdiscard char *FormatPollFd(struct pollfd p[2]) {
|
||||||
return xasprintf("fd:%d revents:%s\n"
|
return xasprintf("fd:%d revents:%s\n"
|
||||||
"fd:%d revents:%s\n",
|
"fd:%d revents:%s\n",
|
||||||
|
@ -50,10 +63,32 @@ dontdiscard char *FormatPollFd(struct pollfd p[2]) {
|
||||||
p[1].fd, gc(RecreateFlags(kPollNames, p[1].revents)));
|
p[1].fd, gc(RecreateFlags(kPollNames, p[1].revents)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(poll, allZero_doesNothing_exceptValidateAndCheckForSignals) {
|
TEST(poll, allZero_doesNothingPrettyMuch) {
|
||||||
EXPECT_SYS(0, 0, poll(0, 0, 0));
|
EXPECT_SYS(0, 0, poll(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ppoll, weCanProveItChecksForSignals) {
|
||||||
|
if (IsXnu()) return;
|
||||||
|
if (IsNetbsd()) return;
|
||||||
|
int pipefds[2];
|
||||||
|
sigset_t set, old;
|
||||||
|
struct sigaction oldss;
|
||||||
|
struct sigaction sa = {.sa_handler = OnSig};
|
||||||
|
EXPECT_SYS(0, 0, pipe(pipefds));
|
||||||
|
struct pollfd fds[] = {{pipefds[0], POLLIN}};
|
||||||
|
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &sa, &oldss));
|
||||||
|
ASSERT_SYS(0, 0, sigfillset(&set));
|
||||||
|
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &set, &old));
|
||||||
|
EXPECT_SYS(0, 0, kill(getpid(), SIGUSR1));
|
||||||
|
EXPECT_FALSE(gotsig);
|
||||||
|
EXPECT_SYS(EINTR, -1, ppoll(fds, 1, 0, &old));
|
||||||
|
EXPECT_TRUE(gotsig);
|
||||||
|
EXPECT_SYS(0, 0, sigprocmask(SIG_SETMASK, &old, 0));
|
||||||
|
EXPECT_SYS(0, 0, sigaction(SIGUSR1, &oldss, 0));
|
||||||
|
EXPECT_SYS(0, 0, close(pipefds[0]));
|
||||||
|
EXPECT_SYS(0, 0, close(pipefds[1]));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(poll, testNegativeOneFd_isIgnored) {
|
TEST(poll, testNegativeOneFd_isIgnored) {
|
||||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
struct sockaddr_in addr = {AF_INET, 0, {htonl(INADDR_LOOPBACK)}};
|
struct sockaddr_in addr = {AF_INET, 0, {htonl(INADDR_LOOPBACK)}};
|
|
@ -48,6 +48,7 @@ TEST_LIBC_CALLS_DIRECTDEPS = \
|
||||||
LIBC_TESTLIB \
|
LIBC_TESTLIB \
|
||||||
LIBC_X \
|
LIBC_X \
|
||||||
LIBC_ZIPOS \
|
LIBC_ZIPOS \
|
||||||
|
TOOL_DECODE_LIB \
|
||||||
THIRD_PARTY_XED
|
THIRD_PARTY_XED
|
||||||
|
|
||||||
TEST_LIBC_CALLS_DEPS := \
|
TEST_LIBC_CALLS_DEPS := \
|
||||||
|
@ -96,6 +97,9 @@ o/$(MODE)/test/libc/calls/life-classic.com.zip.o: private \
|
||||||
o/$(MODE)/test/libc/calls/ioctl_siocgifconf_test.com.runs: \
|
o/$(MODE)/test/libc/calls/ioctl_siocgifconf_test.com.runs: \
|
||||||
private .PLEDGE =
|
private .PLEDGE =
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/calls/poll_test.com.runs: \
|
||||||
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/calls
|
.PHONY: o/$(MODE)/test/libc/calls
|
||||||
o/$(MODE)/test/libc/calls: \
|
o/$(MODE)/test/libc/calls: \
|
||||||
$(TEST_LIBC_CALLS_BINS) \
|
$(TEST_LIBC_CALLS_BINS) \
|
||||||
|
|
0
test/libc/sock/pselect_test.c
Normal file
0
test/libc/sock/pselect_test.c
Normal file
|
@ -17,20 +17,47 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/pledge.h"
|
||||||
|
#include "libc/calls/struct/sigaction.h"
|
||||||
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/calls/struct/timeval.h"
|
#include "libc/calls/struct/timeval.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/select.h"
|
#include "libc/sock/select.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
|
||||||
|
bool gotsig;
|
||||||
|
|
||||||
void SetUpOnce(void) {
|
void SetUpOnce(void) {
|
||||||
|
__pledge_mode = PLEDGE_PENALTY_KILL_PROCESS | PLEDGE_STDERR_LOGGING;
|
||||||
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
ASSERT_SYS(0, 0, pledge("stdio", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST(select, allZero) {
|
void SetUp(void) {
|
||||||
// // todo: figure out how to test block until signal w/ select
|
gotsig = false;
|
||||||
// EXPECT_SYS(0, 0, select(0, 0, 0, 0, 0));
|
}
|
||||||
// }
|
|
||||||
|
void OnSig(int sig) {
|
||||||
|
gotsig = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(select, allZero1) {
|
||||||
|
sigset_t set, old;
|
||||||
|
struct sigaction oldss;
|
||||||
|
struct sigaction sa = {.sa_handler = OnSig};
|
||||||
|
ASSERT_SYS(0, 0, sigaction(SIGQUIT, &sa, &oldss));
|
||||||
|
ASSERT_SYS(0, 0, sigfillset(&set));
|
||||||
|
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &set, &old));
|
||||||
|
EXPECT_SYS(0, 0, kill(getpid(), SIGQUIT));
|
||||||
|
EXPECT_SYS(EINTR, -1, pselect(0, 0, 0, 0, 0, &old));
|
||||||
|
EXPECT_TRUE(gotsig);
|
||||||
|
EXPECT_SYS(0, 0, sigprocmask(SIG_SETMASK, &old, 0));
|
||||||
|
EXPECT_SYS(0, 0, sigaction(SIGQUIT, &oldss, 0));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(select, pipe_hasInputFromSameProcess) {
|
TEST(select, pipe_hasInputFromSameProcess) {
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
|
|
2
third_party/make/job.c
vendored
2
third_party/make/job.c
vendored
|
@ -2259,7 +2259,7 @@ child_execute_job (struct childbase *child,
|
||||||
RETURN_ON_ERROR (Unveil ("/etc/ssl/certs/ca-certificates.crt", "r"));
|
RETURN_ON_ERROR (Unveil ("/etc/ssl/certs/ca-certificates.crt", "r"));
|
||||||
|
|
||||||
/* Unveil .PLEDGE = rpath. */
|
/* Unveil .PLEDGE = rpath. */
|
||||||
if (promises && (~ipromises & (1ul << PROMISE_INET)))
|
if (promises && (~ipromises & (1ul << PROMISE_RPATH)))
|
||||||
RETURN_ON_ERROR (Unveil ("/proc/filesystems", "r"));
|
RETURN_ON_ERROR (Unveil ("/proc/filesystems", "r"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
2
third_party/make/main.c
vendored
2
third_party/make/main.c
vendored
|
@ -2974,7 +2974,7 @@ print_version (void)
|
||||||
/* Do it only once. */
|
/* Do it only once. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf ("%sLandlock Make 1.2 (GNU Make %s)\n", precede, version_string);
|
printf ("%sLandlock Make 1.3 (GNU Make %s)\n", precede, version_string);
|
||||||
|
|
||||||
if (!remote_description || *remote_description == '\0')
|
if (!remote_description || *remote_description == '\0')
|
||||||
printf (_("%sBuilt for %s\n"), precede, make_host);
|
printf (_("%sBuilt for %s\n"), precede, make_host);
|
||||||
|
|
|
@ -98,6 +98,7 @@ usage: pledge.com [-hnN] PROG ARGS...\n\
|
||||||
- wpath: write path ops\n\
|
- wpath: write path ops\n\
|
||||||
- cpath: create path ops\n\
|
- cpath: create path ops\n\
|
||||||
- dpath: create special files\n\
|
- dpath: create special files\n\
|
||||||
|
- chown: allows file ownership changes\n\
|
||||||
- flock: file locks\n\
|
- flock: file locks\n\
|
||||||
- tty: terminal ioctls\n\
|
- tty: terminal ioctls\n\
|
||||||
- recvfd: allow SCM_RIGHTS\n\
|
- recvfd: allow SCM_RIGHTS\n\
|
||||||
|
@ -113,7 +114,7 @@ usage: pledge.com [-hnN] PROG ARGS...\n\
|
||||||
- vminfo: allows /proc/stat, /proc/self/maps, etc.\n\
|
- vminfo: allows /proc/stat, /proc/self/maps, etc.\n\
|
||||||
- tmppath: allows /tmp, $TMPPATH, lstat, unlink\n\
|
- tmppath: allows /tmp, $TMPPATH, lstat, unlink\n\
|
||||||
\n\
|
\n\
|
||||||
pledge.com v1.6\n\
|
pledge.com v1.7\n\
|
||||||
copyright 2022 justine alexandra roberts tunney\n\
|
copyright 2022 justine alexandra roberts tunney\n\
|
||||||
https://twitter.com/justinetunney\n\
|
https://twitter.com/justinetunney\n\
|
||||||
https://linkedin.com/in/jtunney\n\
|
https://linkedin.com/in/jtunney\n\
|
||||||
|
|
|
@ -3880,7 +3880,7 @@ UNIX MODULE
|
||||||
shutdown, sigaction, sigsuspend, sigprocmask, socketpair, umask,
|
shutdown, sigaction, sigsuspend, sigprocmask, socketpair, umask,
|
||||||
wait4, getrusage, ioctl(FIONREAD), ioctl(FIONBIO), ioctl(FIOCLEX),
|
wait4, getrusage, ioctl(FIONREAD), ioctl(FIONBIO), ioctl(FIOCLEX),
|
||||||
ioctl(FIONCLEX), fcntl(F_GETFD), fcntl(F_SETFD), fcntl(F_GETFL),
|
ioctl(FIONCLEX), fcntl(F_GETFD), fcntl(F_SETFD), fcntl(F_GETFL),
|
||||||
fcntl(F_SETFL).
|
fcntl(F_SETFL), raise, kill(getpid()).
|
||||||
|
|
||||||
rpath
|
rpath
|
||||||
|
|
||||||
|
@ -3943,6 +3943,10 @@ UNIX MODULE
|
||||||
|
|
||||||
Allows settimeofday and clock_adjtime.
|
Allows settimeofday and clock_adjtime.
|
||||||
|
|
||||||
|
chown
|
||||||
|
|
||||||
|
Allows chown.
|
||||||
|
|
||||||
unveil
|
unveil
|
||||||
|
|
||||||
Allows unveil().
|
Allows unveil().
|
||||||
|
|
Loading…
Add table
Reference in a new issue