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:
Justine Tunney 2022-08-15 19:52:00 -07:00
parent 255d834f8f
commit ce588dd56b
19 changed files with 190 additions and 39 deletions

View file

@ -56,6 +56,7 @@
#define Sa_Restart 0x10000000
#define SPECIAL 0xf000
#define SELF 0x8000
#define ADDRLESS 0x2000
#define INET 0x8000
#define LOCK 0x4000
@ -476,7 +477,6 @@ static const uint16_t kPledgeStdio[] = {
__NR_linux_sysinfo, //
__NR_linux_fdatasync, //
__NR_linux_ftruncate, //
__NR_linux_getdents, //
__NR_linux_getrandom, //
__NR_linux_getgroups, //
__NR_linux_getpgid, //
@ -546,6 +546,8 @@ static const uint16_t kPledgeStdio[] = {
__NR_linux_sigprocmask, //
__NR_linux_sigsuspend, //
__NR_linux_sigpending, //
__NR_linux_kill | SELF, //
__NR_linux_tkill | SELF, //
__NR_linux_socketpair, //
__NR_linux_getrusage, //
__NR_linux_times, //
@ -581,6 +583,7 @@ static const uint16_t kPledgeRpath[] = {
__NR_linux_readlinkat, //
__NR_linux_statfs, //
__NR_linux_fstatfs, //
__NR_linux_getdents, //
};
static const uint16_t kPledgeWpath[] = {
@ -592,6 +595,7 @@ static const uint16_t kPledgeWpath[] = {
__NR_linux_lstat, //
__NR_linux_fstatat, //
__NR_linux_access, //
__NR_linux_truncate, //
__NR_linux_faccessat, //
__NR_linux_faccessat2, //
__NR_linux_readlinkat, //
@ -728,6 +732,13 @@ static const uint16_t kPledgeId[] = {
__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[] = {
__NR_linux_settimeofday, //
__NR_linux_clock_adjtime, //
@ -789,6 +800,7 @@ const struct Pledges kPledge[PROMISE_LEN_] = {
[PROMISE_PROT_EXEC] = {"prot_exec", PLEDGE(kPledgeProtExec)}, //
[PROMISE_VMINFO] = {"vminfo", PLEDGE(kPledgeVminfo)}, //
[PROMISE_TMPPATH] = {"tmppath", PLEDGE(kPledgeTmppath)}, //
[PROMISE_CHOWN] = {"chown", PLEDGE(kPledgeChown)}, //
};
static const struct sock_filter kPledgeStart[] = {
@ -993,7 +1005,7 @@ static privileged void MonitorSigSys(void) {
};
// we block changing sigsys once pledge is installed
// 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,
@ -1005,6 +1017,36 @@ static privileged void AppendFilter(struct Filter *f, struct sock_filter *p,
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:
//
// - write(2) to allow logging
@ -1884,6 +1926,12 @@ static privileged void AppendPledge(struct Filter *f, //
case __NR_linux_prlimit | STDIO:
AllowPrlimitStdio(f);
break;
case __NR_linux_kill | SELF:
AllowKillSelf(f);
break;
case __NR_linux_tkill | SELF:
AllowTkillSelf(f);
break;
default:
AbortPledge("switch forgot to define a special ordinal");
}

View file

@ -30,6 +30,7 @@
/**
* Permits system operations, e.g.
*
* __pledge_mode = PLEDGE_PENALTY_KILL_PROCESS | PLEDGE_STDERR_LOGGING;
* if (pledge("stdio rfile tty", 0)) {
* perror("pledge");
* exit(1);

View file

@ -25,7 +25,6 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/sock/ppoll.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/sysv/consts/sig.h"
@ -41,9 +40,14 @@
* poll(fds, nfds, timeout);
* sigprocmask(SIG_SETMASK, old, 0);
*
* Except it'll happen atomically if the kernel supports doing that. On
* kernel such as XNU and NetBSD which don't, this wrapper falls back to
* doing the thing described above.
* Except it happens atomically when the kernel supports doing that. On
* kernel such as XNU and NetBSD which don't, this wrapper will fall
* 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 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;
uint64_t millis;
sigset_t oldmask;
struct timespec ts, *tsp;
if (IsAsan() && (!__asan_is_valid(fds, nfds * sizeof(struct pollfd)) ||
(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();
} else if (!IsWindows()) {
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) {
errno = e;
if (!timeout ||
@ -71,9 +82,9 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
&millis)) {
millis = -1;
}
if (sigmask) sys_sigprocmask(SIG_SETMASK, sigmask, &oldmask);
if (sigmask) sigprocmask(SIG_SETMASK, sigmask, &oldmask);
rc = poll(fds, nfds, millis);
if (sigmask) sys_sigprocmask(SIG_SETMASK, &oldmask, 0);
if (sigmask) sigprocmask(SIG_SETMASK, &oldmask, 0);
}
} else {
if (!timeout || __builtin_add_overflow(

View file

@ -26,7 +26,6 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/weaken.h"
#include "libc/log/log.h"
#include "libc/str/str.h"