mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-23 23:34:53 +00:00
Remove malloc() dependency on pledge() / unveil()
This change also fixes a bug with gettid() being incorrect after fork(). We now implement the ENOENT behavior for getauxval(). The getuid() etc. system calls are now faster too. Plus issetugid() will work on BSDs.
This commit is contained in:
parent
c921dc78f0
commit
3d2cf95af1
33 changed files with 270 additions and 100 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/nexgen32e/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/runtime/sysconf.h"
|
#include "libc/runtime/sysconf.h"
|
||||||
|
@ -299,6 +300,12 @@ int main(int argc, char *argv[]) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// secure the server
|
||||||
|
__enable_threads();
|
||||||
|
unveil("/dev/null", "rw");
|
||||||
|
unveil(0, 0);
|
||||||
|
pledge("stdio inet", 0);
|
||||||
|
|
||||||
// spawn over 9,000 worker threads
|
// spawn over 9,000 worker threads
|
||||||
th = calloc(threads, sizeof(*th));
|
th = calloc(threads, sizeof(*th));
|
||||||
for (i = 0; i < threads; ++i) {
|
for (i = 0; i < threads; ++i) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
╚─────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
#endif
|
#endif
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
|
||||||
STATIC_YOINK("mmap"); // TODO: fix bandaid for MODE=asan
|
STATIC_YOINK("mmap"); // TODO: fix bandaid for MODE=asan
|
||||||
|
|
|
@ -16,7 +16,28 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/_getauxval.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sysv/consts/auxv.h"
|
|
||||||
|
|
||||||
int issetugid(void) { return !!getauxval(AT_SECURE); }
|
/**
|
||||||
|
* Returns auxiliary value, or zero if kernel didn't provide it.
|
||||||
|
*
|
||||||
|
* This function is typically regarded as a libc implementation detail;
|
||||||
|
* thus, the source code is the documentation.
|
||||||
|
*
|
||||||
|
* @param at is `AT_...` search key
|
||||||
|
* @return true if value was found
|
||||||
|
* @see libc/sysv/consts.sh
|
||||||
|
* @see System Five Application Binary Interface § 3.4.3
|
||||||
|
* @error ENOENT when value not found
|
||||||
|
* @asyncsignalsafe
|
||||||
|
*/
|
||||||
|
struct AuxiliaryValue _getauxval(unsigned long at) {
|
||||||
|
unsigned long *ap;
|
||||||
|
for (ap = __auxv; ap[0]; ap += 2) {
|
||||||
|
if (at == ap[0]) {
|
||||||
|
return (struct AuxiliaryValue){ap[1], true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (struct AuxiliaryValue){0, false};
|
||||||
|
}
|
15
libc/calls/_getauxval.internal.h
Normal file
15
libc/calls/_getauxval.internal.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_CALLS__GETAUXVAL_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_CALLS__GETAUXVAL_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
struct AuxiliaryValue {
|
||||||
|
unsigned long value;
|
||||||
|
bool isfound;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AuxiliaryValue _getauxval(unsigned long);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_CALLS__GETAUXVAL_H_ */
|
|
@ -115,6 +115,7 @@ int gettid(void) libcesque;
|
||||||
int getuid(void) libcesque;
|
int getuid(void) libcesque;
|
||||||
int ioprio_get(int, int);
|
int ioprio_get(int, int);
|
||||||
int ioprio_set(int, int, int);
|
int ioprio_set(int, int, int);
|
||||||
|
int issetugid(void);
|
||||||
int kill(int, int);
|
int kill(int, int);
|
||||||
int killpg(int, int);
|
int killpg(int, int);
|
||||||
int link(const char *, const char *) dontthrow;
|
int link(const char *, const char *) dontthrow;
|
||||||
|
|
|
@ -179,6 +179,11 @@ o//libc/calls/getcwd-xnu.greg.o: \
|
||||||
OVERRIDE_CFLAGS += \
|
OVERRIDE_CFLAGS += \
|
||||||
-Os
|
-Os
|
||||||
|
|
||||||
|
o/$(MODE)/libc/calls/pledge.o \
|
||||||
|
o/$(MODE)/libc/calls/unveil.o: \
|
||||||
|
OVERRIDE_CFLAGS += \
|
||||||
|
-DSTACK_FRAME_UNLIMITED
|
||||||
|
|
||||||
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
||||||
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
||||||
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
|
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
|
||||||
|
|
|
@ -16,10 +16,8 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/sysv/consts/auxv.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns auxiliary value, or zero if kernel didn't provide it.
|
* Returns auxiliary value, or zero if kernel didn't provide it.
|
||||||
|
@ -27,9 +25,10 @@
|
||||||
* This function is typically regarded as a libc implementation detail;
|
* This function is typically regarded as a libc implementation detail;
|
||||||
* thus, the source code is the documentation.
|
* thus, the source code is the documentation.
|
||||||
*
|
*
|
||||||
* @return aux val or 0 if not available
|
* @return auxiliary value or 0 if `at` not found
|
||||||
* @see libc/sysv/consts.sh
|
* @see libc/sysv/consts.sh
|
||||||
* @see System Five Application Binary Interface § 3.4.3
|
* @see System Five Application Binary Interface § 3.4.3
|
||||||
|
* @error ENOENT when value not found
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
unsigned long getauxval(unsigned long at) {
|
unsigned long getauxval(unsigned long at) {
|
||||||
|
@ -39,5 +38,6 @@ unsigned long getauxval(unsigned long at) {
|
||||||
return ap[1];
|
return ap[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enoent();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/_getauxval.internal.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
@ -29,13 +30,14 @@
|
||||||
*/
|
*/
|
||||||
int getegid(void) {
|
int getegid(void) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!(rc = getauxval(AT_EGID))) {
|
struct AuxiliaryValue av;
|
||||||
if (!IsWindows()) {
|
if ((av = _getauxval(AT_EGID)).isfound) {
|
||||||
|
rc = av.value;
|
||||||
|
} else if (!IsWindows()) {
|
||||||
rc = sys_getegid();
|
rc = sys_getegid();
|
||||||
} else {
|
} else {
|
||||||
rc = getgid();
|
rc = getgid();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
STRACE("%s() → %d% m", "getegid", rc);
|
STRACE("%s() → %d% m", "getegid", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/_getauxval.internal.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
@ -28,13 +29,14 @@
|
||||||
*/
|
*/
|
||||||
int geteuid(void) {
|
int geteuid(void) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!(rc = getauxval(AT_EUID))) {
|
struct AuxiliaryValue av;
|
||||||
if (!IsWindows()) {
|
if ((av = _getauxval(AT_EUID)).isfound) {
|
||||||
|
rc = av.value;
|
||||||
|
} else if (!IsWindows()) {
|
||||||
rc = sys_geteuid();
|
rc = sys_geteuid();
|
||||||
} else {
|
} else {
|
||||||
rc = getuid();
|
rc = getuid();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
STRACE("%s() → %d% m", "geteuid", rc);
|
STRACE("%s() → %d% m", "geteuid", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/_getauxval.internal.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
@ -53,13 +54,15 @@ static textwindows dontinline uint32_t GetUserNameHash(void) {
|
||||||
*/
|
*/
|
||||||
int getuid(void) {
|
int getuid(void) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!(rc = getauxval(AT_UID))) {
|
struct AuxiliaryValue av;
|
||||||
if (!IsWindows()) {
|
if ((av = _getauxval(AT_UID)).isfound) {
|
||||||
|
rc = av.value;
|
||||||
|
} else if (!IsWindows()) {
|
||||||
rc = sys_getuid();
|
rc = sys_getuid();
|
||||||
} else {
|
} else {
|
||||||
rc = GetUserNameHash();
|
rc = GetUserNameHash();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
STRACE("%s() → %d% m", "getuid", rc);
|
STRACE("%s() → %d% m", "getuid", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -75,13 +78,14 @@ int getuid(void) {
|
||||||
*/
|
*/
|
||||||
int getgid(void) {
|
int getgid(void) {
|
||||||
int rc;
|
int rc;
|
||||||
if (!(rc = getauxval(AT_GID))) {
|
struct AuxiliaryValue av;
|
||||||
if (!IsWindows()) {
|
if ((av = _getauxval(AT_GID)).isfound) {
|
||||||
|
rc = av.value;
|
||||||
|
} else if (!IsWindows()) {
|
||||||
rc = sys_getgid();
|
rc = sys_getgid();
|
||||||
} else {
|
} else {
|
||||||
rc = GetUserNameHash();
|
rc = GetUserNameHash();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
STRACE("%s() → %d% m", "getgid", rc);
|
STRACE("%s() → %d% m", "getgid", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
47
libc/calls/issetugid.c
Normal file
47
libc/calls/issetugid.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*-*- 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 2020 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/_getauxval.internal.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/strace.internal.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/sysv/consts/auxv.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if process is tainted.
|
||||||
|
*
|
||||||
|
* This function returns 1 if process was launched as a result of an
|
||||||
|
* execve() call on a binary that had the setuid or setgid bits set.
|
||||||
|
* FreeBSD defines tainted as including processes that changed their
|
||||||
|
* effective user / group ids at some point.
|
||||||
|
*
|
||||||
|
* @return always successful, 1 if yes, 0 if no
|
||||||
|
*/
|
||||||
|
int issetugid(void) {
|
||||||
|
int rc;
|
||||||
|
if (IsLinux()) {
|
||||||
|
rc = !!_getauxval(AT_SECURE).value;
|
||||||
|
} else if (IsMetal()) {
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
|
rc = sys_issetugid();
|
||||||
|
}
|
||||||
|
STRACE("issetugid() → %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
|
@ -23,20 +23,13 @@
|
||||||
#include "libc/calls/struct/filter.h"
|
#include "libc/calls/struct/filter.h"
|
||||||
#include "libc/calls/struct/seccomp.h"
|
#include "libc/calls/struct/seccomp.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/intrin/promises.internal.h"
|
#include "libc/intrin/promises.internal.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/struct/sockaddr.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/af.h"
|
|
||||||
#include "libc/sysv/consts/audit.h"
|
#include "libc/sysv/consts/audit.h"
|
||||||
#include "libc/sysv/consts/clone.h"
|
|
||||||
#include "libc/sysv/consts/f.h"
|
|
||||||
#include "libc/sysv/consts/map.h"
|
|
||||||
#include "libc/sysv/consts/nrlinux.h"
|
#include "libc/sysv/consts/nrlinux.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/pr.h"
|
#include "libc/sysv/consts/pr.h"
|
||||||
|
@ -71,7 +64,7 @@
|
||||||
|
|
||||||
struct Filter {
|
struct Filter {
|
||||||
size_t n;
|
size_t n;
|
||||||
struct sock_filter *p;
|
struct sock_filter p[700];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint16_t kPledgeLinuxDefault[] = {
|
static const uint16_t kPledgeLinuxDefault[] = {
|
||||||
|
@ -453,14 +446,14 @@ static const struct sock_filter kFilterEnd[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool AppendFilter(struct Filter *f, struct sock_filter *p, size_t n) {
|
static bool AppendFilter(struct Filter *f, struct sock_filter *p, size_t n) {
|
||||||
size_t m;
|
if (f->n + n <= ARRAYLEN(f->p)) {
|
||||||
struct sock_filter *q;
|
memcpy(f->p + f->n, p, n * sizeof(*f->p));
|
||||||
m = f->n + n;
|
f->n += n;
|
||||||
if (!(q = realloc(f->p, m * sizeof(*f->p)))) return false;
|
|
||||||
memcpy(q + f->n, p, n * sizeof(*q));
|
|
||||||
f->p = q;
|
|
||||||
f->n = m;
|
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
enomem();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SYSCALL is only allowed in the .privileged section
|
// SYSCALL is only allowed in the .privileged section
|
||||||
|
@ -625,6 +618,7 @@ static bool AllowSetsockoptRestrict(struct Filter *f) {
|
||||||
/* L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 1, 0),
|
/* L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 1, 0),
|
||||||
/* L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 0, 20 - 5),
|
/* L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 0, 20 - 5),
|
||||||
/* L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])),
|
/* L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])),
|
||||||
|
/* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0f, 13, 0),
|
||||||
/* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x03, 12, 0),
|
/* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x03, 12, 0),
|
||||||
/* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0c, 11, 0),
|
/* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0c, 11, 0),
|
||||||
/* L8*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x13, 10, 0),
|
/* L8*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x13, 10, 0),
|
||||||
|
@ -1176,7 +1170,7 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
asm("ud2"); // list of ordinals exceeds max displacement
|
asm("hlt"); // list of ordinals exceeds max displacement
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1264,7 +1258,7 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) {
|
||||||
if (!AllowPrlimitStdio(f)) return false;
|
if (!AllowPrlimitStdio(f)) return false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
asm("ud2"); // switch forgot to define a special ordinal
|
asm("hlt"); // switch forgot to define a special ordinal
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1275,7 +1269,9 @@ static bool AppendPledge(struct Filter *f, const uint16_t *p, size_t len) {
|
||||||
int sys_pledge_linux(unsigned long ipromises) {
|
int sys_pledge_linux(unsigned long ipromises) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
int i, rc = -1;
|
int i, rc = -1;
|
||||||
struct Filter f = {0};
|
struct Filter f;
|
||||||
|
CheckLargeStackAllocation(&f, sizeof(f));
|
||||||
|
f.n = 0;
|
||||||
ipromises = ~ipromises;
|
ipromises = ~ipromises;
|
||||||
if (AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) &&
|
if (AppendFilter(&f, kFilterStart, ARRAYLEN(kFilterStart)) &&
|
||||||
((ipromises & (1ul << PROMISE_EXEC)) ||
|
((ipromises & (1ul << PROMISE_EXEC)) ||
|
||||||
|
@ -1301,7 +1297,6 @@ int sys_pledge_linux(unsigned long ipromises) {
|
||||||
rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox);
|
rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(f.p);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1320,10 +1315,11 @@ int ParsePromises(const char *promises, unsigned long *out) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int promise;
|
int promise;
|
||||||
unsigned long ipromises;
|
unsigned long ipromises;
|
||||||
char *tok, *state, *start, *freeme;
|
char *tok, *state, *start, buf[256];
|
||||||
if (promises) {
|
if (promises) {
|
||||||
ipromises = -1;
|
ipromises = -1;
|
||||||
freeme = start = strdup(promises);
|
if (memccpy(buf, promises, 0, sizeof(buf))) {
|
||||||
|
start = buf;
|
||||||
while ((tok = strtok_r(start, " \t\r\n", &state))) {
|
while ((tok = strtok_r(start, " \t\r\n", &state))) {
|
||||||
if ((promise = FindPromise(tok)) != -1) {
|
if ((promise = FindPromise(tok)) != -1) {
|
||||||
ipromises &= ~(1ULL << promise);
|
ipromises &= ~(1ULL << promise);
|
||||||
|
@ -1333,7 +1329,9 @@ int ParsePromises(const char *promises, unsigned long *out) {
|
||||||
}
|
}
|
||||||
start = 0;
|
start = 0;
|
||||||
}
|
}
|
||||||
free(freeme);
|
} else {
|
||||||
|
rc = einval();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ipromises = 0;
|
ipromises = 0;
|
||||||
}
|
}
|
||||||
|
@ -1356,6 +1354,18 @@ int ParsePromises(const char *promises, unsigned long *out) {
|
||||||
* OpenBSD just kills the process while logging a helpful message to
|
* OpenBSD just kills the process while logging a helpful message to
|
||||||
* /var/log/messages explaining which promise category you needed.
|
* /var/log/messages explaining which promise category you needed.
|
||||||
*
|
*
|
||||||
|
* Timing is everything with pledge. For example, if you're using
|
||||||
|
* threads, then you may want to enable them explicitly *before* calling
|
||||||
|
* pledge(), since otherwise you'd need "prot_exec":
|
||||||
|
*
|
||||||
|
* __enable_threads();
|
||||||
|
* pledge("...", 0);
|
||||||
|
*
|
||||||
|
* If you want crash reports, then you can avoid needing "rpath" with:
|
||||||
|
*
|
||||||
|
* ShowCrashReports();
|
||||||
|
* pledge("...", 0);
|
||||||
|
*
|
||||||
* By default exit() is allowed. This is useful for processes that
|
* By default exit() is allowed. This is useful for processes that
|
||||||
* perform pure computation and interface with the parent via shared
|
* perform pure computation and interface with the parent via shared
|
||||||
* memory. On Linux we mean sys_exit (_Exit1), not sys_exit_group
|
* memory. On Linux we mean sys_exit (_Exit1), not sys_exit_group
|
||||||
|
@ -1520,7 +1530,7 @@ int pledge(const char *promises, const char *execpromises) {
|
||||||
} else {
|
} else {
|
||||||
rc = sys_pledge(promises, execpromises);
|
rc = sys_pledge(promises, execpromises);
|
||||||
}
|
}
|
||||||
if (!rc) {
|
if (!rc && (IsOpenbsd() || getpid() == gettid())) {
|
||||||
__promises = ipromises;
|
__promises = ipromises;
|
||||||
__execpromises = iexecpromises;
|
__execpromises = iexecpromises;
|
||||||
}
|
}
|
10
libc/calls/pledge.internal.h
Normal file
10
libc/calls/pledge.internal.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_CALLS_PLEDGE_INTERNAL_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_CALLS_PLEDGE_INTERNAL_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
int ParsePromises(const char *, unsigned long *);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_CALLS_PLEDGE_INTERNAL_H_ */
|
|
@ -57,6 +57,7 @@ i32 sys_getresuid(u32 *, u32 *, u32 *);
|
||||||
i32 sys_getsid(int) hidden;
|
i32 sys_getsid(int) hidden;
|
||||||
i32 sys_gettid(void) hidden;
|
i32 sys_gettid(void) hidden;
|
||||||
i32 sys_ioctl(i32, u64, ...) hidden;
|
i32 sys_ioctl(i32, u64, ...) hidden;
|
||||||
|
i32 sys_issetugid(void) hidden;
|
||||||
i32 sys_kill(i32, i32, i32) hidden;
|
i32 sys_kill(i32, i32, i32) hidden;
|
||||||
i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden;
|
i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden;
|
||||||
i32 sys_lseek(i32, i64, i64, i64) hidden;
|
i32 sys_lseek(i32, i64, i64, i64) hidden;
|
||||||
|
|
|
@ -31,10 +31,10 @@
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/nexgen32e/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/str/path.h"
|
#include "libc/str/path.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
|
@ -142,8 +142,19 @@ static int unveil_init(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sys_unveil_linux(const char *path, const char *permissions) {
|
int sys_unveil_linux(const char *path, const char *permissions) {
|
||||||
int rc;
|
int rc;
|
||||||
|
const char *dir;
|
||||||
|
const char *last;
|
||||||
|
const char *next;
|
||||||
|
struct {
|
||||||
|
char lbuf[PATH_MAX];
|
||||||
|
char buf1[PATH_MAX];
|
||||||
|
char buf2[PATH_MAX];
|
||||||
|
char buf3[PATH_MAX];
|
||||||
|
char buf4[PATH_MAX];
|
||||||
|
} b;
|
||||||
|
CheckLargeStackAllocation(&b, sizeof(b));
|
||||||
|
|
||||||
if (!State.fd && (rc = unveil_init()) == -1) return rc;
|
if (!State.fd && (rc = unveil_init()) == -1) return rc;
|
||||||
if ((path && !permissions) || (!path && permissions)) return einval();
|
if ((path && !permissions) || (!path && permissions)) return einval();
|
||||||
|
@ -173,48 +184,34 @@ static int sys_unveil_linux(const char *path, const char *permissions) {
|
||||||
// realpath(path) to the ruleset. however a corner case exists where
|
// realpath(path) to the ruleset. however a corner case exists where
|
||||||
// it isn't valid, e.g. /dev/stdin -> /proc/2834/fd/pipe:[51032], so
|
// it isn't valid, e.g. /dev/stdin -> /proc/2834/fd/pipe:[51032], so
|
||||||
// we'll need to work around this, by adding the path which is valid
|
// we'll need to work around this, by adding the path which is valid
|
||||||
const char *dir;
|
|
||||||
const char *last;
|
|
||||||
const char *next;
|
|
||||||
struct {
|
|
||||||
char lbuf[PATH_MAX];
|
|
||||||
char buf1[PATH_MAX];
|
|
||||||
char buf2[PATH_MAX];
|
|
||||||
char buf3[PATH_MAX];
|
|
||||||
char buf4[PATH_MAX];
|
|
||||||
} * b;
|
|
||||||
if (strlen(path) + 1 > PATH_MAX) return enametoolong();
|
if (strlen(path) + 1 > PATH_MAX) return enametoolong();
|
||||||
if (!(b = malloc(sizeof(*b)))) return -1;
|
|
||||||
last = path;
|
last = path;
|
||||||
next = path;
|
next = path;
|
||||||
for (int i = 0;; ++i) {
|
for (int i = 0;; ++i) {
|
||||||
if (i == 64) {
|
if (i == 64) {
|
||||||
// give up
|
// give up
|
||||||
free(b);
|
|
||||||
return eloop();
|
return eloop();
|
||||||
}
|
}
|
||||||
int err = errno;
|
int err = errno;
|
||||||
if ((rc = sys_readlinkat(AT_FDCWD, next, b->lbuf, PATH_MAX)) != -1) {
|
if ((rc = sys_readlinkat(AT_FDCWD, next, b.lbuf, PATH_MAX)) != -1) {
|
||||||
if (rc < PATH_MAX) {
|
if (rc < PATH_MAX) {
|
||||||
// we need to nul-terminate
|
// we need to nul-terminate
|
||||||
b->lbuf[rc] = 0;
|
b.lbuf[rc] = 0;
|
||||||
// last = next
|
// last = next
|
||||||
strcpy(b->buf1, next);
|
strcpy(b.buf1, next);
|
||||||
last = b->buf1;
|
last = b.buf1;
|
||||||
// next = join(dirname(next), link)
|
// next = join(dirname(next), link)
|
||||||
strcpy(b->buf2, next);
|
strcpy(b.buf2, next);
|
||||||
dir = dirname(b->buf2);
|
dir = dirname(b.buf2);
|
||||||
if ((next = _joinpaths(b->buf3, PATH_MAX, dir, b->lbuf))) {
|
if ((next = _joinpaths(b.buf3, PATH_MAX, dir, b.lbuf))) {
|
||||||
// next now points to either: buf3, buf2, lbuf, rodata
|
// next now points to either: buf3, buf2, lbuf, rodata
|
||||||
strcpy(b->buf4, next);
|
strcpy(b.buf4, next);
|
||||||
next = b->buf4;
|
next = b.buf4;
|
||||||
} else {
|
} else {
|
||||||
free(b);
|
|
||||||
return enametoolong();
|
return enametoolong();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// symbolic link data was too long
|
// symbolic link data was too long
|
||||||
free(b);
|
|
||||||
return enametoolong();
|
return enametoolong();
|
||||||
}
|
}
|
||||||
} else if (errno == EINVAL) {
|
} else if (errno == EINVAL) {
|
||||||
|
@ -229,14 +226,12 @@ static int sys_unveil_linux(const char *path, const char *permissions) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// readlink failed for some other reason
|
// readlink failed for some other reason
|
||||||
free(b);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we can open the path
|
// now we can open the path
|
||||||
rc = sys_open(path, O_PATH | O_NOFOLLOW | O_CLOEXEC, 0);
|
rc = sys_open(path, O_PATH | O_NOFOLLOW | O_CLOEXEC, 0);
|
||||||
free(b);
|
|
||||||
if (rc == -1) return rc;
|
if (rc == -1) return rc;
|
||||||
|
|
||||||
pb.parent_fd = rc;
|
pb.parent_fd = rc;
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/state.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/nexgen32e/gettls.h"
|
#include "libc/nexgen32e/gettls.h"
|
||||||
|
@ -49,10 +50,11 @@
|
||||||
* @return thread id greater than zero or -1 w/ errno
|
* @return thread id greater than zero or -1 w/ errno
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @threadsafe
|
* @threadsafe
|
||||||
|
* @vforksafe
|
||||||
*/
|
*/
|
||||||
int gettid(void) {
|
int gettid(void) {
|
||||||
int tid;
|
int tid;
|
||||||
if (__tls_enabled) {
|
if (__tls_enabled && !__vforked) {
|
||||||
tid = *(int *)(__get_tls() + 0x38);
|
tid = *(int *)(__get_tls() + 0x38);
|
||||||
if (tid > 0) {
|
if (tid > 0) {
|
||||||
return tid;
|
return tid;
|
|
@ -18,5 +18,6 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/promises.internal.h"
|
#include "libc/intrin/promises.internal.h"
|
||||||
|
|
||||||
|
// XXX: should be inherited thread local
|
||||||
unsigned long __promises;
|
unsigned long __promises;
|
||||||
unsigned long __execpromises;
|
unsigned long __execpromises;
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
hidden extern unsigned long __promises;
|
extern unsigned long __promises;
|
||||||
hidden extern unsigned long __execpromises;
|
extern unsigned long __execpromises;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/_getauxval.internal.h"
|
||||||
#include "libc/intrin/pthread.h"
|
#include "libc/intrin/pthread.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/nexgen32e/rdtsc.h"
|
#include "libc/nexgen32e/rdtsc.h"
|
||||||
|
@ -54,7 +55,7 @@ uint64_t rand64(void) {
|
||||||
s = g_rand64.thepool; // normal path
|
s = g_rand64.thepool; // normal path
|
||||||
} else {
|
} else {
|
||||||
if (!g_rand64.thepid) {
|
if (!g_rand64.thepid) {
|
||||||
if (AT_RANDOM && (p = (void *)getauxval(AT_RANDOM))) {
|
if (AT_RANDOM && (p = (void *)_getauxval(AT_RANDOM).value)) {
|
||||||
// linux / freebsd kernel supplied entropy
|
// linux / freebsd kernel supplied entropy
|
||||||
memcpy(&s, p, 16);
|
memcpy(&s, p, 16);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/_getauxval.internal.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
|
@ -54,7 +55,7 @@ static dontinline int __clk_tck_init(void) {
|
||||||
x = -1;
|
x = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
x = getauxval(AT_CLKTCK);
|
x = _getauxval(AT_CLKTCK).value;
|
||||||
}
|
}
|
||||||
if (x < 1) x = 100;
|
if (x < 1) x = 100;
|
||||||
clk_tck = x;
|
clk_tck = x;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/nexgen32e/gettls.h"
|
||||||
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/nt/process.h"
|
#include "libc/nt/process.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
|
|
||||||
|
@ -56,6 +58,9 @@ int fork(void) {
|
||||||
}
|
}
|
||||||
parent = __pid;
|
parent = __pid;
|
||||||
__pid = dx;
|
__pid = dx;
|
||||||
|
if (__tls_enabled) {
|
||||||
|
*(int *)(__get_tls() + 0x38) = IsLinux() ? dx : sys_gettid();
|
||||||
|
}
|
||||||
STRACE("fork() → 0 (child of %d)", parent);
|
STRACE("fork() → 0 (child of %d)", parent);
|
||||||
if (weaken(__onfork)) {
|
if (weaken(__onfork)) {
|
||||||
weaken(__onfork)();
|
weaken(__onfork)();
|
||||||
|
|
|
@ -70,7 +70,6 @@ int setenv(const char *, const char *, int) paramsnonnull();
|
||||||
int unsetenv(const char *);
|
int unsetenv(const char *);
|
||||||
int clearenv(void);
|
int clearenv(void);
|
||||||
void fpreset(void);
|
void fpreset(void);
|
||||||
int issetugid(void);
|
|
||||||
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
|
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
|
||||||
void *mremap(void *, size_t, size_t, int, ...);
|
void *mremap(void *, size_t, size_t, int, ...);
|
||||||
int munmap(void *, uint64_t);
|
int munmap(void *, uint64_t);
|
||||||
|
|
|
@ -128,6 +128,12 @@ extern char ape_stack_align[] __attribute__((__weak__));
|
||||||
(IsTiny() || \
|
(IsTiny() || \
|
||||||
(intptr_t)__builtin_frame_address(0) >= GetStackAddr() + PAGESIZE + (n))
|
(intptr_t)__builtin_frame_address(0) >= GetStackAddr() + PAGESIZE + (n))
|
||||||
|
|
||||||
|
forceinline void CheckLargeStackAllocation(void *p, ssize_t n) {
|
||||||
|
for (; n > 0; n -= 4096) {
|
||||||
|
((char *)p)[n - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* GNU ELF */
|
#endif /* GNU ELF */
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
.include "o/libc/sysv/macros.internal.inc"
|
|
||||||
.scall issetugid,0xfff0fd0fd2147fff,globl
|
|
2
libc/sysv/calls/sys_issetugid.s
Normal file
2
libc/sysv/calls/sys_issetugid.s
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.include "o/libc/sysv/macros.internal.inc"
|
||||||
|
.scall sys_issetugid,0xfff0fd0fd2147fff,globl,hidden
|
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/nexgen32e/vendor.internal.h"
|
||||||
|
|
||||||
const char *__describe_os(void) {
|
const char *__describe_os(void) {
|
||||||
if (IsLinux()) {
|
if (IsLinux()) {
|
||||||
|
|
|
@ -422,7 +422,7 @@ scall __bsd_seteuid 0xfff0b70b720b7fff globl hidden # wrapped via setreuid()
|
||||||
scall __bsd_setegid 0xfff0b60b620b6fff globl hidden # wrapped via setregid()
|
scall __bsd_setegid 0xfff0b60b620b6fff globl hidden # wrapped via setregid()
|
||||||
scall fpathconf 0x0c00c00c020c0fff globl
|
scall fpathconf 0x0c00c00c020c0fff globl
|
||||||
scall fhopen 0x18c10812a20f8fff globl
|
scall fhopen 0x18c10812a20f8fff globl
|
||||||
scall issetugid 0xfff0fd0fd2147fff globl
|
scall sys_issetugid 0xfff0fd0fd2147fff globl hidden
|
||||||
scall minherit 0x1110fa0fa20fafff globl
|
scall minherit 0x1110fa0fa20fafff globl
|
||||||
scall pathconf 0x0bf0bf0bf20bffff globl
|
scall pathconf 0x0bf0bf0bf20bffff globl
|
||||||
scall sysctl 0x0ca0ca0ca20cafff globl
|
scall sysctl 0x0ca0ca0ca20cafff globl
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/ioctl.h"
|
#include "libc/calls/ioctl.h"
|
||||||
|
#include "libc/calls/pledge.internal.h"
|
||||||
#include "libc/calls/struct/bpf.h"
|
#include "libc/calls/struct/bpf.h"
|
||||||
#include "libc/calls/struct/filter.h"
|
#include "libc/calls/struct/filter.h"
|
||||||
#include "libc/calls/struct/flock.h"
|
#include "libc/calls/struct/flock.h"
|
||||||
|
@ -562,6 +563,28 @@ TEST(pledge, threadWithLocks_canCodeMorph) {
|
||||||
EXPECT_EQ(0, WEXITSTATUS(ws));
|
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(pledge, everything) {
|
||||||
|
int ws, pid;
|
||||||
|
if (!fork()) {
|
||||||
|
// contains 548 bpf instructions [2022-07-24]
|
||||||
|
ASSERT_SYS(0, 0,
|
||||||
|
pledge("stdio rpath wpath cpath dpath "
|
||||||
|
"flock fattr inet unix dns tty "
|
||||||
|
"recvfd sendfd proc exec id "
|
||||||
|
"unveil settime prot_exec "
|
||||||
|
"vminfo tmppath",
|
||||||
|
"stdio rpath wpath cpath dpath "
|
||||||
|
"flock fattr inet unix dns tty "
|
||||||
|
"recvfd sendfd proc exec id "
|
||||||
|
"unveil settime prot_exec "
|
||||||
|
"vminfo tmppath"));
|
||||||
|
_Exit(0);
|
||||||
|
}
|
||||||
|
EXPECT_NE(-1, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(0, WEXITSTATUS(ws));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(pledge, execWithoutRpath) {
|
TEST(pledge, execWithoutRpath) {
|
||||||
int ws, pid;
|
int ws, pid;
|
||||||
ASSERT_SYS(0, 0, touch("foo", 0644));
|
ASSERT_SYS(0, 0, touch("foo", 0644));
|
|
@ -63,6 +63,8 @@ o/$(MODE)/test/libc/calls/%.com.dbg: \
|
||||||
o/$(MODE)/test/libc/calls/life-nomod.com.zip.o \
|
o/$(MODE)/test/libc/calls/life-nomod.com.zip.o \
|
||||||
o/$(MODE)/test/libc/calls/life-classic.com.zip.o \
|
o/$(MODE)/test/libc/calls/life-classic.com.zip.o \
|
||||||
o/$(MODE)/test/libc/calls/tiny64.elf.zip.o \
|
o/$(MODE)/test/libc/calls/tiny64.elf.zip.o \
|
||||||
|
o/$(MODE)/test/libc/mem/prog/life.elf.zip.o \
|
||||||
|
o/$(MODE)/test/libc/mem/prog/sock.elf.zip.o \
|
||||||
o/$(MODE)/third_party/python/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt.zip.o \
|
o/$(MODE)/third_party/python/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt.zip.o \
|
||||||
o/$(MODE)/test/libc/calls/calls.pkg \
|
o/$(MODE)/test/libc/calls/calls.pkg \
|
||||||
$(LIBC_TESTMAIN) \
|
$(LIBC_TESTMAIN) \
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "libc/sysv/consts/msync.h"
|
#include "libc/sysv/consts/msync.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/ok.h"
|
#include "libc/sysv/consts/ok.h"
|
||||||
|
#include "libc/sysv/consts/pr.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/consts/rusage.h"
|
#include "libc/sysv/consts/rusage.h"
|
||||||
#include "libc/sysv/consts/sa.h"
|
#include "libc/sysv/consts/sa.h"
|
||||||
|
@ -499,6 +500,11 @@ static struct sigaction_linux *CoerceSigactionToLinux(
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int OpPrctl(struct Machine *m, int op, int64_t a, int64_t b, int64_t c,
|
||||||
|
int64_t d) {
|
||||||
|
return einval();
|
||||||
|
}
|
||||||
|
|
||||||
static int OpArchPrctl(struct Machine *m, int code, int64_t addr) {
|
static int OpArchPrctl(struct Machine *m, int code, int64_t addr) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case ARCH_SET_GS:
|
case ARCH_SET_GS:
|
||||||
|
@ -1503,6 +1509,7 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
|
||||||
SYSCALL(0x0A0, setrlimit(di, P(si)));
|
SYSCALL(0x0A0, setrlimit(di, P(si)));
|
||||||
SYSCALL(0x084, utime(PNN(di), PNN(si)));
|
SYSCALL(0x084, utime(PNN(di), PNN(si)));
|
||||||
SYSCALL(0x0EB, utimes(P(di), P(si)));
|
SYSCALL(0x0EB, utimes(P(di), P(si)));
|
||||||
|
SYSCALL(0x09D, OpPrctl(m, di, si, dx, r0, r8));
|
||||||
SYSCALL(0x09E, OpArchPrctl(m, di, si));
|
SYSCALL(0x09E, OpArchPrctl(m, di, si));
|
||||||
SYSCALL(0x0BA, OpGetTid(m));
|
SYSCALL(0x0BA, OpGetTid(m));
|
||||||
SYSCALL(0x0CB, sched_setaffinity(di, si, P(dx)));
|
SYSCALL(0x0CB, sched_setaffinity(di, si, P(dx)));
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
|
|
||||||
noasan int main(int argc, char *argv[]) {
|
noasan int main(int argc, char *argv[]) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR);
|
Elf64_Ehdr *ehdr;
|
||||||
|
ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR);
|
||||||
if (isatty(1)) exit(1);
|
if (isatty(1)) exit(1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
write(1, ((char *)ehdr) + i++, 1);
|
write(1, ((char *)ehdr) + i++, 1);
|
||||||
|
|
|
@ -1426,7 +1426,7 @@ static void PickDefaults(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RenounceSpecialPrivileges(void) {
|
static void RenounceSpecialPrivileges(void) {
|
||||||
if (getauxval(AT_SECURE)) {
|
if (issetugid()) {
|
||||||
setegid(getgid());
|
setegid(getgid());
|
||||||
seteuid(getuid());
|
seteuid(getuid());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue