mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
Make some touchups
This commit is contained in:
parent
6c49e36537
commit
2e3958c6dc
11 changed files with 161 additions and 63 deletions
|
@ -47,12 +47,22 @@
|
|||
* The `policy` must have one of:
|
||||
*
|
||||
* - `SCHED_OTHER` (or `SCHED_NORMAL`) for the default policy
|
||||
*
|
||||
* - `SCHED_RR` for real-time round-robin scheduling
|
||||
*
|
||||
* - `SCHED_FIFO` for real-time first-in first-out scheduling
|
||||
*
|
||||
* - `SCHED_BATCH` for "batch" style execution of processes if
|
||||
* supported (Linux), otherwise it's treated as `SCHED_OTHER`
|
||||
* - `SCHED_IDLE` for running very low priority background jobs
|
||||
* if it's supported (Linux), otherwise this is `SCHED_OTHER`
|
||||
*
|
||||
* - `SCHED_IDLE` for running very low priority background jobs if
|
||||
* it's supported (Linux), otherwise this is `SCHED_OTHER`.
|
||||
* Pledging away scheduling privilege is permanent for your
|
||||
* process; if a subsequent attempt is made to restore the
|
||||
* `SCHED_OTHER` policy then this system call will `EPERM` (but on
|
||||
* older kernels like RHEL7 this isn't the case). This policy
|
||||
* isn't available on old Linux kernels like RHEL5, where it'll
|
||||
* raise `EINVAL`.
|
||||
*
|
||||
* The `policy` may optionally bitwise-or any one of:
|
||||
*
|
||||
|
@ -65,7 +75,9 @@
|
|||
* greater than or equal to sched_get_priority_min(policy) and less
|
||||
* than or equal to sched_get_priority_max(policy). Linux allows the
|
||||
* static priority range 1 to 99 for the `SCHED_FIFO` and `SCHED_RR`
|
||||
* policies, and the priority 0 for the remaining policies.
|
||||
* policies, and the priority 0 is used for the remaining policies.
|
||||
* You should still consider calling the function, because on NetBSD
|
||||
* the correct priority might be -1.
|
||||
*
|
||||
* @return the former scheduling policy of the specified process. If
|
||||
* this function fails, then the scheduling policy is not changed,
|
||||
|
|
21
libc/intrin/promises.c
Normal file
21
libc/intrin/promises.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*-*- 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/intrin/promises.internal.h"
|
||||
|
||||
unsigned long __promises;
|
33
libc/intrin/promises.internal.h
Normal file
33
libc/intrin/promises.internal.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_PROMISES_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_PROMISES_H_
|
||||
|
||||
#define PROMISE_DEFAULT 0
|
||||
#define PROMISE_STDIO 1
|
||||
#define PROMISE_RPATH 2
|
||||
#define PROMISE_WPATH 3
|
||||
#define PROMISE_CPATH 4
|
||||
#define PROMISE_DPATH 5
|
||||
#define PROMISE_FLOCK 6
|
||||
#define PROMISE_FATTR 7
|
||||
#define PROMISE_INET 8
|
||||
#define PROMISE_UNIX 9
|
||||
#define PROMISE_DNS 10
|
||||
#define PROMISE_TTY 11
|
||||
#define PROMISE_RECVFD 12
|
||||
#define PROMISE_PROC 13
|
||||
#define PROMISE_THREAD 14
|
||||
#define PROMISE_EXEC 15
|
||||
#define PROMISE_EXECNATIVE 16
|
||||
#define PROMISE_ID 17
|
||||
#define PROMISE_MAX 17
|
||||
|
||||
#define PLEDGED(x) (~__promises & (1L << PROMISE_##x))
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
hidden extern unsigned long __promises;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_PROMISES_H_ */
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
|
@ -47,8 +48,7 @@ static union metatermios __oldtermios;
|
|||
static textstartup void __oldtermios_init() {
|
||||
int e;
|
||||
e = errno;
|
||||
if (!IsOpenbsd() && // avoid pledge(tty)
|
||||
sys_ioctl(0, TCGETS, &__oldtermios) != -1) {
|
||||
if (PLEDGED(TTY) && sys_ioctl(0, TCGETS, &__oldtermios) != -1) {
|
||||
__isrestorable = true;
|
||||
}
|
||||
errno = e;
|
||||
|
@ -60,7 +60,7 @@ const void *const __oldtermios_ctor[] initarray = {
|
|||
|
||||
void __restore_tty(void) {
|
||||
int e;
|
||||
if (__isrestorable && !__isworker && !__nocolor) {
|
||||
if (__isrestorable && PLEDGED(TTY) && !__isworker && !__nocolor) {
|
||||
e = errno;
|
||||
sys_write(0, ANSI_RESTORE, __strlen(ANSI_RESTORE));
|
||||
sys_ioctl(0, TCSETSF, &__oldtermios);
|
||||
|
|
|
@ -51,10 +51,14 @@ relegated void __check_fail(const char *suffix, const char *opstr,
|
|||
__start_fatal(file, line);
|
||||
__stpcpy(hostname, "unknown");
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
kprintf("check failed on %s pid %d\n", hostname, getpid());
|
||||
kprintf("\tCHECK_%^s(%s, %s);\n", suffix, wantstr, gotstr);
|
||||
kprintf("\t\t → %p (%s)\n", want, wantstr);
|
||||
kprintf("\t\t%s %p (%s)\n", opstr, got, gotstr);
|
||||
kprintf("check failed on %s pid %d\n"
|
||||
"\tCHECK_%^s(%s, %s);\n"
|
||||
"\t\t → %p (%s)\n"
|
||||
"\t\t%s %p (%s)\n", //
|
||||
hostname, getpid(), //
|
||||
suffix, wantstr, gotstr, //
|
||||
want, wantstr, //
|
||||
opstr, got, gotstr);
|
||||
if (!isempty(fmt)) {
|
||||
kprintf("\t");
|
||||
va_start(va, fmt);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
@ -296,7 +297,7 @@ static const uint16_t kPledgeLinuxExec[] = {
|
|||
__NR_linux_openat | READONLY, //
|
||||
};
|
||||
|
||||
static const uint16_t kPledgeLinuxExecnative[] = {
|
||||
static const uint16_t kPledgeLinuxExec2[] = {
|
||||
__NR_linux_execve, //
|
||||
__NR_linux_execveat, //
|
||||
};
|
||||
|
@ -306,25 +307,25 @@ static const struct Pledges {
|
|||
const uint16_t *syscalls;
|
||||
const size_t len;
|
||||
} kPledgeLinux[] = {
|
||||
{"default", PLEDGE(kPledgeLinuxDefault)}, //
|
||||
{"stdio", PLEDGE(kPledgeLinuxStdio)}, //
|
||||
{"rpath", PLEDGE(kPledgeLinuxRpath)}, //
|
||||
{"wpath", PLEDGE(kPledgeLinuxWpath)}, //
|
||||
{"cpath", PLEDGE(kPledgeLinuxCpath)}, //
|
||||
{"dpath", PLEDGE(kPledgeLinuxDpath)}, //
|
||||
{"flock", PLEDGE(kPledgeLinuxFlock)}, //
|
||||
{"fattr", PLEDGE(kPledgeLinuxFattr)}, //
|
||||
{"inet", PLEDGE(kPledgeLinuxInet)}, //
|
||||
{"unix", PLEDGE(kPledgeLinuxUnix)}, //
|
||||
{"dns", PLEDGE(kPledgeLinuxDns)}, //
|
||||
{"tty", PLEDGE(kPledgeLinuxTty)}, //
|
||||
{"recvfd", PLEDGE(kPledgeLinuxRecvfd)}, //
|
||||
{"proc", PLEDGE(kPledgeLinuxProc)}, //
|
||||
{"thread", PLEDGE(kPledgeLinuxThread)}, //
|
||||
{"exec", PLEDGE(kPledgeLinuxExec)}, //
|
||||
{"execnative", PLEDGE(kPledgeLinuxExecnative)}, //
|
||||
{"id", PLEDGE(kPledgeLinuxId)}, //
|
||||
{0}, //
|
||||
[PROMISE_DEFAULT] = {"default", PLEDGE(kPledgeLinuxDefault)}, //
|
||||
[PROMISE_STDIO] = {"stdio", PLEDGE(kPledgeLinuxStdio)}, //
|
||||
[PROMISE_RPATH] = {"rpath", PLEDGE(kPledgeLinuxRpath)}, //
|
||||
[PROMISE_WPATH] = {"wpath", PLEDGE(kPledgeLinuxWpath)}, //
|
||||
[PROMISE_CPATH] = {"cpath", PLEDGE(kPledgeLinuxCpath)}, //
|
||||
[PROMISE_DPATH] = {"dpath", PLEDGE(kPledgeLinuxDpath)}, //
|
||||
[PROMISE_FLOCK] = {"flock", PLEDGE(kPledgeLinuxFlock)}, //
|
||||
[PROMISE_FATTR] = {"fattr", PLEDGE(kPledgeLinuxFattr)}, //
|
||||
[PROMISE_INET] = {"inet", PLEDGE(kPledgeLinuxInet)}, //
|
||||
[PROMISE_UNIX] = {"unix", PLEDGE(kPledgeLinuxUnix)}, //
|
||||
[PROMISE_DNS] = {"dns", PLEDGE(kPledgeLinuxDns)}, //
|
||||
[PROMISE_TTY] = {"tty", PLEDGE(kPledgeLinuxTty)}, //
|
||||
[PROMISE_RECVFD] = {"recvfd", PLEDGE(kPledgeLinuxRecvfd)}, //
|
||||
[PROMISE_PROC] = {"proc", PLEDGE(kPledgeLinuxProc)}, //
|
||||
[PROMISE_THREAD] = {"thread", PLEDGE(kPledgeLinuxThread)}, //
|
||||
[PROMISE_EXEC] = {"exec", PLEDGE(kPledgeLinuxExec)}, //
|
||||
[PROMISE_EXECNATIVE] = {"execnative", PLEDGE(kPledgeLinuxExec2)}, //
|
||||
[PROMISE_ID] = {"id", PLEDGE(kPledgeLinuxId)}, //
|
||||
[PROMISE_MAX + 1] = {0}, //
|
||||
};
|
||||
|
||||
static const struct sock_filter kFilterStart[] = {
|
||||
|
@ -949,8 +950,8 @@ static bool AllowFchmodat(struct Filter *f) {
|
|||
return AppendFilter(f, PLEDGE(fragment));
|
||||
}
|
||||
|
||||
static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len,
|
||||
bool needmapexec, bool needmorphing) {
|
||||
static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len, bool needmapexec,
|
||||
bool needmorphing) {
|
||||
int i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
switch (p[i]) {
|
||||
|
@ -1037,39 +1038,42 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len,
|
|||
return true;
|
||||
}
|
||||
|
||||
static const uint16_t *FindPledge(const struct Pledges *p, const char *name,
|
||||
size_t *len) {
|
||||
static int FindPromise(const struct Pledges *p, const char *name, size_t *len) {
|
||||
int i;
|
||||
for (i = 0; p[i].name; ++i) {
|
||||
if (!strcasecmp(name, p[i].name)) {
|
||||
*len = p[i].len;
|
||||
return p[i].syscalls;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sys_pledge_linux(const char *promises, const char *execpromises) {
|
||||
bool ok;
|
||||
int rc = -1;
|
||||
size_t plen;
|
||||
int promise;
|
||||
bool needmapexec;
|
||||
bool needexecnative;
|
||||
bool needmorphing;
|
||||
struct Filter f = {0};
|
||||
const uint16_t *pledge;
|
||||
unsigned long ipromises = -1;
|
||||
char *s, *tok, *state, *start;
|
||||
if (execpromises) return einval();
|
||||
needmapexec = strstr(promises, "exec");
|
||||
needmorphing = strstr(promises, "thread");
|
||||
needexecnative = strstr(promises, "execnative");
|
||||
if ((start = s = strdup(promises)) &&
|
||||
AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) &&
|
||||
if ((start = s = strdup(promises)) && AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) &&
|
||||
(needmapexec || needexecnative || AppendOriginVerification(&f)) &&
|
||||
AppendPledge(&f, kPledgeLinuxDefault, ARRAYLEN(kPledgeLinuxDefault),
|
||||
needmapexec, needmorphing)) {
|
||||
AppendPledge(&f, kPledgeLinuxDefault, ARRAYLEN(kPledgeLinuxDefault), needmapexec,
|
||||
needmorphing)) {
|
||||
for (ok = true; (tok = strtok_r(start, " \t\r\n", &state)); start = 0) {
|
||||
if (!(pledge = FindPledge(kPledgeLinux, tok, &plen))) {
|
||||
if ((promise = FindPromise(kPledgeLinux, tok, &plen)) != -1) {
|
||||
pledge = kPledgeLinux[promise].syscalls;
|
||||
ipromises &= ~(1ULL << promise);
|
||||
} else {
|
||||
ok = false;
|
||||
rc = einval();
|
||||
break;
|
||||
|
@ -1084,12 +1088,29 @@ static int sys_pledge_linux(const char *promises, const char *execpromises) {
|
|||
struct sock_fprog sandbox = {.len = f.n, .filter = f.p};
|
||||
rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox);
|
||||
}
|
||||
if (!rc) {
|
||||
__promises = ipromises;
|
||||
}
|
||||
}
|
||||
free(f.p);
|
||||
free(s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void SetPromises(const char *promises) {
|
||||
int promise;
|
||||
size_t plen;
|
||||
char *tok, *state, *start;
|
||||
unsigned long ipromises = -1;
|
||||
while ((tok = strtok_r(start, " \t\r\n", &state))) {
|
||||
if ((promise = FindPromise(kPledgeLinux, tok, &plen)) != -1) {
|
||||
ipromises &= ~(1ULL << promise);
|
||||
}
|
||||
start = 0;
|
||||
}
|
||||
__promises = ipromises;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts system operations, e.g.
|
||||
*
|
||||
|
@ -1216,6 +1237,9 @@ int pledge(const char *promises, const char *execpromises) {
|
|||
rc = sys_pledge_linux(promises, execpromises);
|
||||
} else {
|
||||
rc = sys_pledge(promises, execpromises);
|
||||
if (!rc) {
|
||||
SetPromises(promises);
|
||||
}
|
||||
}
|
||||
STRACE("pledge(%#s, %#s) → %d% m", promises, execpromises, rc);
|
||||
return rc;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -74,11 +75,8 @@ static textexit void LogStackUse(void) {
|
|||
}
|
||||
|
||||
static textstartup void LogStackUseInit(void) {
|
||||
if (IsOpenbsd()) {
|
||||
// avoid pledge() dependency on wpath
|
||||
return;
|
||||
}
|
||||
if (IsTiny()) return;
|
||||
if (!PLEDGED(WPATH)) return;
|
||||
if (isdirectory("o/" MODE) &&
|
||||
getcwd(stacklog, sizeof(stacklog) - strlen("/o/" MODE "/stack.log"))) {
|
||||
strcat(stacklog, "/o/" MODE "/stack.log");
|
||||
|
|
|
@ -27,7 +27,7 @@ struct FtraceTls { /* 16 */
|
|||
struct cthread_descriptor_t {
|
||||
struct cthread_descriptor_t *self; /* 0x00 */
|
||||
struct FtraceTls ftrace; /* 0x08 */
|
||||
int64_t __pad0; /* 0x10 */
|
||||
void *garbages; /* 0x10 */
|
||||
int64_t __pad1; /* 0x20 */
|
||||
int64_t __pad2; /* 0x28 */
|
||||
struct cthread_descriptor_t *self2; /* 0x30 */
|
||||
|
|
|
@ -117,6 +117,15 @@ TEST(open, testOpenExistingForAppendWriteOnly_seeksToEnd) {
|
|||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(open, testRelativePath_opensRelativeToDirFd) {
|
||||
ASSERT_SYS(0, 0, mkdir("foo", 0755));
|
||||
ASSERT_SYS(0, 3, open("foo", O_RDONLY | O_DIRECTORY));
|
||||
EXPECT_SYS(0, 4, openat(3, "bar", O_WRONLY | O_TRUNC | O_CREAT, 0755));
|
||||
EXPECT_TRUE(fileexists("foo/bar"));
|
||||
EXPECT_SYS(0, 0, close(4));
|
||||
EXPECT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
int CountFds(void) {
|
||||
int i, count;
|
||||
for (count = i = 0; i < g_fds.n; ++i) {
|
||||
|
|
|
@ -34,9 +34,6 @@ TEST(vfork, test) {
|
|||
ASSERT_NE(-1, lseek(fd, 0, SEEK_SET));
|
||||
if (!vfork()) {
|
||||
EXPECT_EQ(5, pread(fd, buf, 5, 0));
|
||||
/*
|
||||
* TODO(jart): DOES PREAD IN CHILD REALLY CHANGE PARENT HANDLE POSITION?
|
||||
*/
|
||||
ASSERT_NE(-1, lseek(fd, 0, SEEK_SET));
|
||||
EXPECT_STREQ("hello", buf);
|
||||
EXPECT_NE(-1, close(fd));
|
||||
|
|
28
third_party/lua/lunix.c
vendored
28
third_party/lua/lunix.c
vendored
|
@ -2585,20 +2585,20 @@ static const luaL_Reg kLuaUnix[] = {
|
|||
{"rmrf", LuaUnixRmrf}, // remove file recursively
|
||||
{"send", LuaUnixSend}, // send tcp to some address
|
||||
{"sendto", LuaUnixSendto}, // send udp to some address
|
||||
{"setfsgid", LuaUnixSetfsgid}, // set/get group id for file system ops
|
||||
{"setfsuid", LuaUnixSetfsuid}, // set/get user id for file system ops
|
||||
{"setgid", LuaUnixSetgid}, // set real group id of process
|
||||
{"setitimer", LuaUnixSetitimer}, // set alarm clock
|
||||
{"setpgid", LuaUnixSetpgid}, // set process group id for pid
|
||||
{"setpgrp", LuaUnixSetpgrp}, // sets process group id
|
||||
{"setresgid", LuaUnixSetresgid}, // sets real/effective/saved gids
|
||||
{"setresuid", LuaUnixSetresuid}, // sets real/effective/saved uids
|
||||
{"setrlimit", LuaUnixSetrlimit}, // prevent cpu memory bombs
|
||||
{"setsid", LuaUnixSetsid}, // create a new session id
|
||||
{"setsockopt", LuaUnixSetsockopt}, // tune socket options
|
||||
{"setuid", LuaUnixSetuid}, // set real user id of process
|
||||
{"shutdown", LuaUnixShutdown}, // make socket half empty or full
|
||||
{"sigaction", LuaUnixSigaction}, // install signal handler
|
||||
{"setfsgid", LuaUnixSetfsgid}, // set/get group id for fs ops
|
||||
{"setfsuid", LuaUnixSetfsuid}, // set/get user id for fs ops
|
||||
{"setgid", LuaUnixSetgid}, // set real group id of process
|
||||
{"setitimer", LuaUnixSetitimer}, // set alarm clock
|
||||
{"setpgid", LuaUnixSetpgid}, // set process group id for pid
|
||||
{"setpgrp", LuaUnixSetpgrp}, // sets process group id
|
||||
{"setresgid", LuaUnixSetresgid}, // sets real/effective/saved gids
|
||||
{"setresuid", LuaUnixSetresuid}, // sets real/effective/saved uids
|
||||
{"setrlimit", LuaUnixSetrlimit}, // prevent cpu memory bombs
|
||||
{"setsid", LuaUnixSetsid}, // create a new session id
|
||||
{"setsockopt", LuaUnixSetsockopt}, // tune socket options
|
||||
{"setuid", LuaUnixSetuid}, // set real user id of process
|
||||
{"shutdown", LuaUnixShutdown}, // make socket half empty or full
|
||||
{"sigaction", LuaUnixSigaction}, // install signal handler
|
||||
{"sigprocmask", LuaUnixSigprocmask}, // change signal mask
|
||||
{"sigsuspend", LuaUnixSigsuspend}, // wait for signal
|
||||
{"siocgifconf", LuaUnixSiocgifconf}, // get list of network interfaces
|
||||
|
|
Loading…
Reference in a new issue