mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-09-10 18:53:48 +00:00
Fix bugs and add security features to redbean
- Fix a regression with the previous change that broke redbean - Add chroot(), resource limit, seccomp, and other stuff to redbean - Write lots and lots of documentation - Iron out more system call issues
This commit is contained in:
parent
f1dfa4bdfa
commit
7166679620
182 changed files with 1855 additions and 918 deletions
|
@ -155,7 +155,7 @@ int pipe(int[hasatleast 2]);
|
|||
int pipe2(int[hasatleast 2], int);
|
||||
int posix_fadvise(int, uint64_t, uint64_t, int);
|
||||
int posix_madvise(void *, uint64_t, int);
|
||||
int prctl();
|
||||
int prctl(int, ...);
|
||||
int raise(int);
|
||||
int reboot(int);
|
||||
int remove(const char *);
|
||||
|
@ -232,6 +232,7 @@ uint32_t umask(uint32_t);
|
|||
void rewinddir(DIR *);
|
||||
void sync(void);
|
||||
int getloadavg(double *, int);
|
||||
int seccomp(unsigned, unsigned, void *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » formatting ─╬─│┼
|
||||
|
|
|
@ -83,6 +83,9 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: \
|
|||
-O3
|
||||
|
||||
# TODO(jart): make va_arg optimize well in default mode
|
||||
o//libc/calls/open.o \
|
||||
o//libc/calls/openat.o \
|
||||
o//libc/calls/prctl.o \
|
||||
o//libc/calls/ioctl.o \
|
||||
o//libc/calls/ioctl_default.o \
|
||||
o//libc/calls/ioctl_fioclex-nt.o \
|
||||
|
|
|
@ -76,5 +76,5 @@ textwindows int sys_chdir_nt(const char *path) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return __fix_enotdir(-1, path16);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
*/
|
||||
int chdir(const char *path) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) {
|
||||
if (!path || (IsAsan() && !__asan_is_valid(path, 1))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_chdir(path);
|
||||
|
|
33
libc/calls/chroot.c
Normal file
33
libc/calls/chroot.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
||||
/**
|
||||
* Changes root directory.
|
||||
*
|
||||
* @raise ENOSYS on Windows
|
||||
*/
|
||||
int chroot(const char *path) {
|
||||
int rc;
|
||||
rc = sys_chroot(path);
|
||||
STRACE("chroot(%s) → %d% m", path, rc);
|
||||
return rc;
|
||||
}
|
|
@ -22,7 +22,6 @@
|
|||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
|
@ -32,6 +31,9 @@
|
|||
* support Windows NT and Address Sanitizer. That memory tracking can be
|
||||
* bypassed by calling this function. However the caller is responsible
|
||||
* for passing the magic memory handle on Windows NT to CloseHandle().
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
|
||||
int64_t off) {
|
||||
|
|
|
@ -24,5 +24,5 @@
|
|||
int sys_faccessat_nt(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
return ntaccesscheck(path16, mode);
|
||||
return __fix_enotdir(ntaccesscheck(path16, mode), path16);
|
||||
}
|
||||
|
|
63
libc/calls/fixenotdir.c
Normal file
63
libc/calls/fixenotdir.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*-*- 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/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
static textwindows bool SubpathExistsThatsNotDirectory(char16_t *path) {
|
||||
int e;
|
||||
char16_t *p;
|
||||
uint32_t attrs;
|
||||
e = errno;
|
||||
while ((p = strrchr16(path, '\\'))) {
|
||||
*p = u'\0';
|
||||
if ((attrs = GetFileAttributes(path)) != -1u) {
|
||||
if (attrs & kNtFileAttributeDirectory) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
errno = e;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// WIN32 doesn't distinguish between ENOTDIR and ENOENT. UNIX strictly
|
||||
// requires that a directory component *exists* but is not a directory
|
||||
// whereas WIN32 will return ENOTDIR if a dir label simply isn't found
|
||||
//
|
||||
// - ENOTDIR: A component used as a directory in pathname is not, in
|
||||
// fact, a directory. -or- pathname is relative and dirfd is a file
|
||||
// descriptor referring to a file other than a directory.
|
||||
//
|
||||
// - ENOENT: A directory component in pathname does not exist or is a
|
||||
// dangling symbolic link.
|
||||
//
|
||||
textwindows int64_t __fix_enotdir(int64_t rc, char16_t *path) {
|
||||
if (rc == -1 && errno == kNtErrorPathNotFound) {
|
||||
if (!SubpathExistsThatsNotDirectory(path)) {
|
||||
errno = kNtErrorFileNotFound;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
|
@ -36,10 +37,16 @@ int getrlimit(int resource, struct rlimit *rlim) {
|
|||
char buf[64];
|
||||
if (resource == 127) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) {
|
||||
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_getrlimit(resource, rlim);
|
||||
} else if (resource == RLIMIT_AS) {
|
||||
rlim->rlim_cur = __virtualmax;
|
||||
rlim->rlim_max = __virtualmax;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("getrlimit(%s, [%s]) → %d% m", __strace_rlimit_name(resource),
|
||||
__strace_rlimit(buf, sizeof(buf), rc, rlim), rc);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction-xnu.internal.h"
|
||||
#include "libc/calls/struct/siginfo-xnu.internal.h"
|
||||
|
@ -133,6 +134,7 @@ i32 __sys_pipe2(i32[hasatleast 2], u32) hidden;
|
|||
i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden;
|
||||
i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden;
|
||||
i32 sys_chdir(const char *) hidden;
|
||||
i32 sys_chroot(const char *) hidden;
|
||||
i32 sys_clock_gettime(i32, struct timespec *) hidden;
|
||||
i32 sys_close(i32) hidden;
|
||||
i32 sys_dup(i32) hidden;
|
||||
|
@ -310,6 +312,7 @@ int sys_sync_nt(void) hidden;
|
|||
int sys_sysinfo_nt(struct sysinfo *) hidden;
|
||||
int sys_truncate_nt(const char *, u64) hidden;
|
||||
int sys_unlinkat_nt(int, const char *, int) hidden;
|
||||
int sys_setrlimit_nt(int, const struct rlimit *) hidden;
|
||||
int sys_utimensat_nt(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_utimes_nt(const char *, const struct timeval[2]) hidden;
|
||||
ssize_t sys_open_nt(int, const char *, u32, i32) dontdiscard hidden;
|
||||
|
@ -322,6 +325,7 @@ int ioctl_tiocgwinsz_nt(struct Fd *, struct winsize *) hidden;
|
|||
│ cosmopolitan § syscalls » windows nt » support ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
int64_t __fix_enotdir(int64_t, char16_t *) hidden;
|
||||
bool _check_interrupts(bool, struct Fd *) hidden;
|
||||
void _check_sigchld(void) hidden;
|
||||
void _check_sigalrm(void) hidden;
|
||||
|
|
10
libc/calls/issandboxed.h
Normal file
10
libc/calls/issandboxed.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_ISSANDBOXED_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_ISSANDBOXED_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern bool __issandboxed;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_ISSANDBOXED_INTERNAL_H_ */
|
|
@ -17,50 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static textwindows bool SubpathExistsThatsNotDirectory(char16_t *path) {
|
||||
int e;
|
||||
char16_t *p;
|
||||
uint32_t attrs;
|
||||
e = errno;
|
||||
while ((p = strrchr16(path, '\\'))) {
|
||||
*p = u'\0';
|
||||
if ((attrs = GetFileAttributes(path)) != -1u) {
|
||||
if (attrs & kNtFileAttributeDirectory) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
errno = e;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
|
||||
int e;
|
||||
char16_t *p, path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if (CreateDirectory(path16, 0)) return 0;
|
||||
|
||||
// WIN32 doesn't distinguish between ENOTDIR and ENOENT
|
||||
//
|
||||
// - ENOTDIR: A component used as a directory in pathname is not, in
|
||||
// fact, a directory. -or- pathname is relative and dirfd is a file
|
||||
// descriptor referring to a file other than a directory.
|
||||
//
|
||||
// - ENOENT: A directory component in pathname does not exist or is a
|
||||
// dangling symbolic link.
|
||||
if (errno == ENOTDIR) {
|
||||
if (!SubpathExistsThatsNotDirectory(path16)) {
|
||||
errno = ENOENT;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return __fix_enotdir(-1, path16);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,16 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
/**
|
||||
* Unmaps memory directly with system.
|
||||
*
|
||||
* This function bypasses memtrack. Therefore it won't work on Windows,
|
||||
* but it works on everything else including bare metal.
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
*/
|
||||
int sys_munmap(void *p, size_t n) {
|
||||
int rc;
|
||||
if (!IsMetal()) {
|
||||
|
|
|
@ -42,7 +42,9 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
|||
uint32_t perm, share, disp, attr;
|
||||
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
|
||||
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -1) return -1;
|
||||
return CreateFile(path16, perm, share, &kNtIsInheritable, disp, attr, 0);
|
||||
return __fix_enotdir(
|
||||
CreateFile(path16, perm, share, &kNtIsInheritable, disp, attr, 0),
|
||||
path16);
|
||||
}
|
||||
|
||||
static textwindows ssize_t sys_open_nt_console(int dirfd,
|
||||
|
|
|
@ -87,11 +87,13 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
|||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("poll(%p, %'lu, %'d) → %d% lm", fds, nfds, timeout_ms, rc);
|
||||
} else {
|
||||
char flagbuf[2][64];
|
||||
kprintf(STRACE_PROLOGUE "poll({");
|
||||
for (i = 0; i < MIN(5, nfds); ++i) {
|
||||
kprintf("%s{%d,%s,%s}", i ? ", " : "", fds[i].fd,
|
||||
DescribePollFlags(fds[i].events),
|
||||
DescribePollFlags(fds[i].revents));
|
||||
kprintf(
|
||||
"%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
|
||||
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
|
||||
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
|
||||
}
|
||||
kprintf("%s}, %'zu, %'d) → %d% lm%n", i == 5 ? "..." : "", nfds,
|
||||
timeout_ms, rc);
|
||||
|
|
52
libc/calls/prctl.c
Normal file
52
libc/calls/prctl.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Tunes process on Linux.
|
||||
*
|
||||
* @raise ENOSYS on non-Linux.
|
||||
*/
|
||||
int prctl(int operation, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
intptr_t a, b;
|
||||
register intptr_t c asm("r10");
|
||||
register intptr_t d asm("r8");
|
||||
va_start(va, operation);
|
||||
a = va_arg(va, intptr_t);
|
||||
b = va_arg(va, intptr_t);
|
||||
c = va_arg(va, intptr_t);
|
||||
d = va_arg(va, intptr_t);
|
||||
va_end(va);
|
||||
if (IsLinux()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(157), "D"(operation), "S"(a), "d"(b), "r"(c), "r"(d)
|
||||
: "rcx", "r11", "memory");
|
||||
if (rc > -4096u) errno = -rc, rc = -1;
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("seccomp(%d, %p, %p, %p, %p) → %d% m", operation, a, b, c, d, rc);
|
||||
return rc;
|
||||
}
|
|
@ -56,7 +56,7 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
|||
rc = ebadf();
|
||||
}
|
||||
assert(rc == -1 || (size_t)rc <= size);
|
||||
STRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd,
|
||||
MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, offset, rc);
|
||||
DATATRACE("pread(%d, [%#.*hhs%s], %'zu, %'zd) → %'zd% m", fd,
|
||||
MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, offset, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
|||
assert(wrote <= size);
|
||||
}
|
||||
}
|
||||
STRACE("pwrite(%d, %#.*hhs%s, %'zu, %'zd) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
||||
buf, rc > 40 ? "..." : "", size, offset, rc);
|
||||
DATATRACE("pwrite(%d, %#.*hhs%s, %'zu, %'zd) → %'zd% m", fd,
|
||||
MAX(0, MIN(40, rc)), buf, rc > 40 ? "..." : "", size, offset, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ ssize_t read(int fd, void *buf, size_t size) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("read(%d, [%#.*hhs%s], %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)), buf,
|
||||
rc > 40 ? "..." : "", size, rc);
|
||||
DATATRACE("read(%d, [%#.*hhs%s], %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
||||
buf, rc > 40 ? "..." : "", size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -40,7 +41,9 @@
|
|||
* @restartable
|
||||
*/
|
||||
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
int i;
|
||||
ssize_t rc, rem;
|
||||
|
||||
if (fd >= 0 && iovlen >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
|
@ -63,6 +66,27 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
} else {
|
||||
rem = rc != -1 ? rc : 0;
|
||||
kprintf(STRACE_PROLOGUE "readv(%d, [{", fd);
|
||||
for (i = 0; i < MIN(5, iovlen); ++i) {
|
||||
kprintf("%s{%#.*hhs%s, %'zu}", i ? ", " : "",
|
||||
MAX(0, MIN(40, MIN(rem, iov[i].iov_len))), iov[i].iov_base,
|
||||
MAX(0, MIN(40, MIN(rem, iov[i].iov_len))) < iov[i].iov_len
|
||||
? "..."
|
||||
: "",
|
||||
iov[i].iov_len);
|
||||
rem -= iov[i].iov_len;
|
||||
}
|
||||
kprintf("%s}], %d) → %'ld% m%n", iovlen > 5 ? "..." : "", iovlen, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
69
libc/calls/seccomp.c
Normal file
69
libc/calls/seccomp.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/issandboxed.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/pr.h"
|
||||
#include "libc/sysv/consts/seccomp.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Tunes Linux security policy.
|
||||
*
|
||||
* This system call was first introduced in Linux 3.17. We polyfill
|
||||
* automatically features like SECCOMP_SET_MODE_STRICT, for kernels
|
||||
* dating back to 2.6.23, whenever possible.
|
||||
*
|
||||
* @raise ENOSYS on non-Linux.
|
||||
*/
|
||||
int seccomp(unsigned operation, unsigned flags, void *args) {
|
||||
int rc;
|
||||
if (IsLinux()) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(317), "D"(operation), "S"(flags), "d"(args)
|
||||
: "rcx", "r11", "memory");
|
||||
if (rc == -ENOSYS) {
|
||||
if (operation == SECCOMP_SET_MODE_STRICT) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(157), "D"(PR_SET_SECCOMP), "S"(SECCOMP_MODE_STRICT)
|
||||
: "rcx", "r11", "memory");
|
||||
} else if (operation == SECCOMP_SET_MODE_FILTER && !flags) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(157), "D"(PR_SET_SECCOMP), "S"(SECCOMP_MODE_FILTER),
|
||||
"d"(args)
|
||||
: "rcx", "r11", "memory");
|
||||
}
|
||||
}
|
||||
if (rc > -4096u) {
|
||||
errno = -rc;
|
||||
rc = -1;
|
||||
}
|
||||
} else {
|
||||
rc = enosys();
|
||||
}
|
||||
STRACE("seccomp(%s, %#x, %p) → %d% m",
|
||||
DescribeSeccompOperationFlags(operation), flags, args, rc);
|
||||
return rc;
|
||||
}
|
|
@ -16,17 +16,39 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets resource limit for current process.
|
||||
*
|
||||
* @param resource can be RLIMIT_{CPU,FSIZE,DATA,STACK,CORE,RSS,etc.}
|
||||
* The following resources are recommended:
|
||||
*
|
||||
* - `RLIMIT_AS` limits the size of the virtual address space. This will
|
||||
* work on all platforms. It's emulated on XNU and Windows which means
|
||||
* it won't propagate across execve() currently.
|
||||
*
|
||||
* - `RLIMIT_CPU` causes `SIGXCPU` to be sent to the process when the
|
||||
* soft limit on CPU time is exceeded, and the process is destroyed
|
||||
* when the hard limit is exceeded. It works everywhere but Windows
|
||||
* where it should be possible to poll getrusage() with setitimer()
|
||||
*
|
||||
* - `RLIMIT_FSIZE` causes `SIGXFSZ` to sent to the process when the
|
||||
* soft limit on file size is exceeded and the process is destroyed
|
||||
* when the hard limit is exceeded. It works everywhere but Windows
|
||||
*
|
||||
* - `RLIMIT_NPROC` limits the number of simultaneous processes and it
|
||||
* should work on all platforms except Windows.
|
||||
*
|
||||
* - `RLIMIT_NOFILE` limits the number of open file descriptors and it
|
||||
* should work on all platforms except Windows (TODO)
|
||||
*
|
||||
* @param rlim specifies new resource limit
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see libc/sysv/consts.sh
|
||||
|
@ -37,10 +59,19 @@ int setrlimit(int resource, const struct rlimit *rlim) {
|
|||
char buf[64];
|
||||
if (resource == 127) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim))) {
|
||||
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_setrlimit(resource, rlim);
|
||||
if (IsXnu() && !rc && resource == RLIMIT_AS) {
|
||||
// TODO(jart): What's up with XNU and NetBSD?
|
||||
__virtualmax = rlim->rlim_cur;
|
||||
}
|
||||
} else if (resource == RLIMIT_AS) {
|
||||
__virtualmax = rlim->rlim_cur;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("setrlimit(%s, %s) → %d% m", __strace_rlimit_name(resource),
|
||||
__strace_rlimit(buf, sizeof(buf), 0, rlim), rc);
|
||||
|
|
|
@ -24,6 +24,10 @@ void __stat2cosmo(struct stat *restrict st, const union metastat *ms) {
|
|||
if (st) {
|
||||
if (IsLinux()) {
|
||||
st->st_birthtim = st->st_ctim;
|
||||
if (st->st_atim.tv_sec < st->st_ctim.tv_sec)
|
||||
st->st_birthtim = st->st_atim;
|
||||
if (st->st_mtim.tv_sec < st->st_ctim.tv_sec)
|
||||
st->st_birthtim = st->st_mtim;
|
||||
} else if (IsXnu()) {
|
||||
st->st_dev = ms->xnu.st_dev;
|
||||
st->st_ino = ms->xnu.st_ino;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define _NT_RLIMIT_PWSS_MB 1000 /* nocommit */
|
||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
|
||||
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
|
||||
|
@ -25,6 +26,12 @@ COSMOPOLITAN_C_START_
|
|||
#define STRACE(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
#define DATATRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DATATRACE(FMT, ...) (void)0
|
||||
#endif
|
||||
|
||||
#if defined(SYSDEBUG) && _POLLTRACE
|
||||
#define POLLTRACE(FMT, ...) STRACE(FMT, ##__VA_ARGS__)
|
||||
#else
|
||||
|
|
54
libc/calls/struct/seccomp.h
Normal file
54
libc/calls/struct/seccomp.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SECCOMP_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SECCOMP_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct seccomp_data {
|
||||
int32_t nr;
|
||||
uint32_t arch;
|
||||
uint64_t instruction_pointer;
|
||||
uint64_t args[6];
|
||||
};
|
||||
|
||||
struct seccomp_notif_sizes {
|
||||
uint16_t seccomp_notif;
|
||||
uint16_t seccomp_notif_resp;
|
||||
uint16_t seccomp_data;
|
||||
};
|
||||
|
||||
struct seccomp_notif {
|
||||
uint64_t id;
|
||||
uint32_t pid;
|
||||
uint32_t flags;
|
||||
struct seccomp_data data;
|
||||
};
|
||||
|
||||
struct seccomp_notif_resp {
|
||||
uint64_t id;
|
||||
int64_t val;
|
||||
int32_t error;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct seccomp_notif_addfd {
|
||||
uint64_t id;
|
||||
uint32_t flags;
|
||||
uint32_t srcfd;
|
||||
uint32_t newfd;
|
||||
uint32_t newfd_flags;
|
||||
};
|
||||
|
||||
#define SECCOMP_IOC_MAGIC '!'
|
||||
#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
|
||||
#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
|
||||
#define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type)
|
||||
#define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
|
||||
|
||||
#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
|
||||
#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp)
|
||||
#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64)
|
||||
#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, struct seccomp_notif_addfd)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SECCOMP_H_ */
|
28
libc/calls/virtualmax.c
Normal file
28
libc/calls/virtualmax.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Maximum amount of virtual memory in bytes.
|
||||
*
|
||||
* mmap() will return ENOMEM once this is reached.
|
||||
*
|
||||
* By default no limit is imposed.
|
||||
*/
|
||||
size_t __virtualmax;
|
|
@ -51,6 +51,8 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
|
|||
__sig_raise(SIGPIPE, SI_KERNEL);
|
||||
return epipe();
|
||||
}
|
||||
// kNtErrorInvalidHandle → EBADF (consts.sh)
|
||||
// kNtErrorNotEnoughQuota → EDQUOT (consts.sh; SetProcessWorkingSetSize)
|
||||
return __winerr();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ ssize_t write(int fd, const void *buf, size_t size) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("write(%d, %#.*hhs%s, %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)), buf,
|
||||
rc > 40 ? "..." : "", size, rc);
|
||||
DATATRACE("write(%d, %#.*hhs%s, %'zu) → %'zd% m", fd, MAX(0, MIN(40, rc)),
|
||||
buf, rc > 40 ? "..." : "", size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -44,7 +46,9 @@
|
|||
* @restartable
|
||||
*/
|
||||
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
int i;
|
||||
ssize_t rc, rem;
|
||||
|
||||
if (fd >= 0 && iovlen >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
|
@ -67,6 +71,27 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
|
||||
#if defined(SYSDEBUG) && _DATATRACE
|
||||
if (__strace > 0) {
|
||||
if (rc == -1 && errno == EFAULT) {
|
||||
STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
} else {
|
||||
rem = rc != -1 ? rc : 0;
|
||||
kprintf(STRACE_PROLOGUE "writev(%d, {", fd);
|
||||
for (i = 0; i < MIN(5, iovlen); ++i) {
|
||||
kprintf("%s{%#.*hhs%s, %'zu}", i ? ", " : "",
|
||||
MAX(0, MIN(40, MIN(rem, iov[i].iov_len))), iov[i].iov_base,
|
||||
MAX(0, MIN(40, MIN(rem, iov[i].iov_len))) < iov[i].iov_len
|
||||
? "..."
|
||||
: "",
|
||||
iov[i].iov_len);
|
||||
rem -= iov[i].iov_len;
|
||||
}
|
||||
kprintf("%s}, %d) → %'ld% m%n", iovlen > 5 ? "..." : "", iovlen, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue