Fix bugs and regressions in the pledge command

This change gets the pledge (formerly pledge.com) command back in tip
top shape for a 3.0.1 cosmos release. It now runs on all platforms, even
though it's mostly a no-op on ones that lack the kernel security stuff.
The binary footprint is now smaller, since it no longer needs to link
malloc. It's also now able to be built as a fat binary.
This commit is contained in:
Justine Tunney 2023-11-01 06:08:58 -07:00
parent b0e3d89942
commit 7b284f6bda
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
18 changed files with 493 additions and 272 deletions

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
@ -37,13 +38,12 @@
* @raise EBADF on OpenBSD if `first` is greater than highest fd
* @raise EINVAL if flags are bad or first is greater than last
* @raise EMFILE if a weird race condition happens on Linux
* @raise ECANCELED if thread was cancelled in masked mode
* @raise EINTR possibly on OpenBSD
* @raise ENOMEM on Linux maybe
*/
int closefrom(int first) {
int rc, err;
(void)err;
int rc;
BLOCK_CANCELATION;
if (first < 0) {
// consistent with openbsd
// freebsd allows this but it's dangerous
@ -58,6 +58,7 @@ int closefrom(int first) {
} else {
rc = enosys();
}
ALLOW_CANCELATION;
STRACE("closefrom(%d) → %d% m", first, rc);
return rc;
}

View file

@ -44,7 +44,7 @@ ssize_t copyfd(int in, int out, size_t n) {
if (dw != dr) {
// POSIX requires atomic IO up to PIPE_BUF
// The minimum permissible PIPE_BUF is 512
abort();
notpossible;
}
}
return i;

View file

@ -25,5 +25,6 @@
bool IsApeLoadable(char buf[8]) {
return READ32LE(buf) == READ32LE("\177ELF") ||
READ64LE(buf) == READ64LE("MZqFpD='") ||
READ64LE(buf) == READ64LE("JTqFpD='");
READ64LE(buf) == READ64LE("jartsr='") ||
READ64LE(buf) == READ64LE("APEDBG='");
}

View file

@ -33,6 +33,9 @@ static int FindPromise(const char *name) {
/**
* Parses the arguments to pledge() into a bitmask.
*
* @param out receives the integral promises mask, which zero is defined
* as the set of all promises, and -1 is defined as the empty set of
* promises, which is equivalent to `promises` being an empty string
* @return 0 on success, or -1 if invalid
*/
int ParsePromises(const char *promises, unsigned long *out,

View file

@ -535,7 +535,10 @@ static const struct thatispacked SyscallName {
};
static const uint16_t kPledgeDefault[] = {
__NR_linux_exit, // thread return / exit()
__NR_linux_exit, // thread return / exit()
#ifdef __NR_linux_arch_prctl //
__NR_linux_arch_prctl, // or else launching musl process crashes (tls)
#endif //
};
// stdio contains all the benign system calls. openbsd makes the

View file

@ -29,6 +29,7 @@ void __stat2cosmo(struct stat *restrict st, const union metastat *ms) {
st->st_uid = ms->linux.st_uid;
st->st_gid = ms->linux.st_gid;
st->st_flags = 0;
st->st_gen = 0;
st->st_rdev = ms->linux.st_rdev;
st->st_size = ms->linux.st_size;
st->st_blksize = ms->linux.st_blksize;

View file

@ -12,7 +12,7 @@ struct sysinfo {
uint64_t bufferram; /* lingering disk pages; see fadvise */
uint64_t totalswap; /* size of emergency memory */
uint64_t freeswap; /* hopefully equal to totalswap */
int16_t procs; /* number of processes */
uint16_t procs; /* number of processes */
int16_t __ignore1; /* padding */
int32_t __ignore2; /* padding */
uint64_t totalhigh; /* wut */

View file

@ -16,27 +16,55 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/struct/sysinfo.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/struct/sysinfo.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/mem/mem.h"
#include "libc/nt/accounting.h"
#include "libc/nt/process.h"
#include "libc/nt/struct/memorystatusex.h"
#include "libc/nt/struct/systeminfo.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/systeminfo.h"
static textwindows uint16_t GetProcessCount(void) {
uint16_t res;
uint32_t have, got, *pids;
uint32_t stack_memory[1000];
have = 0xFFFF * 4;
if (!_weaken(malloc) || !(pids = _weaken(malloc)(have))) {
pids = stack_memory;
have = sizeof(stack_memory);
}
if (EnumProcesses(pids, have, &got)) {
res = got / 4;
} else {
res = 0;
}
if (pids != stack_memory && _weaken(free)) {
_weaken(free)(pids);
}
return res;
}
textwindows int sys_sysinfo_nt(struct sysinfo *info) {
int i;
double load[3];
struct NtMemoryStatusEx memstat;
struct NtSystemInfo sysinfo;
GetSystemInfo(&sysinfo);
BLOCK_SIGNALS;
if (sys_getloadavg_nt(load, 3) != -1) {
for (i = 0; i < 3; ++i) {
info->loads[i] = load[i] * 65536;
}
}
memstat.dwLength = sizeof(struct NtMemoryStatusEx);
if (GlobalMemoryStatusEx(&memstat)) {
info->mem_unit = 1;
info->totalram = memstat.ullTotalPhys;
info->freeram = memstat.ullAvailPhys;
info->procs = sysinfo.dwNumberOfProcessors;
info->uptime = GetTickCount64() / 1000;
return 0;
} else {
return __winerr();
}
info->uptime = GetTickCount64() / 1000;
info->procs = GetProcessCount();
info->mem_unit = 1;
ALLOW_SIGNALS;
return 0;
}

View file

@ -188,56 +188,6 @@ static int unveil_init(void) {
return 0;
}
/**
* Joins paths, e.g.
*
* 0 + 0 0
* "" + "" ""
* "a" + 0 "a"
* "a" + "" "a/"
* 0 + "b" "b"
* "" + "b" "b"
* "." + "b" "./b"
* "b" + "." "b/."
* "a" + "b" "a/b"
* "a/" + "b" "a/b"
* "a" + "b/" "a/b/"
* "a" + "/b" "/b"
*
* @return joined path, which may be `buf`, `path`, or `other`, or null
* if (1) `buf` didn't have enough space, or (2) both `path` and
* `other` were null
*/
static char *JoinPaths(char *buf, size_t size, const char *path,
const char *other) {
size_t pathlen, otherlen;
if (!other) return (char *)path;
if (!path) return (char *)other;
pathlen = strlen(path);
if (!pathlen || *other == '/') {
return (/*unconst*/ char *)other;
}
otherlen = strlen(other);
if (path[pathlen - 1] == '/') {
if (pathlen + otherlen + 1 <= size) {
memmove(buf, path, pathlen);
memmove(buf + pathlen, other, otherlen + 1);
return buf;
} else {
return 0;
}
} else {
if (pathlen + 1 + otherlen + 1 <= size) {
memmove(buf, path, pathlen);
buf[pathlen] = '/';
memmove(buf + pathlen + 1, other, otherlen + 1);
return buf;
} else {
return 0;
}
}
}
int sys_unveil_linux(const char *path, const char *permissions) {
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wframe-larger-than="
@ -302,7 +252,7 @@ int sys_unveil_linux(const char *path, const char *permissions) {
// next = join(dirname(next), link)
strcpy(b.buf2, next);
dir = dirname(b.buf2);
if ((next = JoinPaths(b.buf3, PATH_MAX, dir, b.lbuf))) {
if ((next = __join_paths(b.buf3, PATH_MAX, dir, b.lbuf))) {
// next now points to either: buf3, buf2, lbuf, rodata
strcpy(b.buf4, next);
next = b.buf4;

View file

@ -1,3 +1,7 @@
#ifdef __COSMOPOLITAN__
#undef __COSMOPOLITAN__
#endif
#define __COSMOPOLITAN_MAJOR__ 3
#define __COSMOPOLITAN_MINOR__ 0
#define __COSMOPOLITAN_PATCH__ 0

View file

@ -430,6 +430,9 @@ privileged void klog(const char *b, size_t n) {
: "=a"(rax), "=D"(rdi), "=S"(rsi), "=d"(rdx)
: "0"(__NR_write), "1"(h), "2"(b), "3"(n)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
if (rax < 0) {
__klog_handle = 0;
}
}
#elif defined(__aarch64__)
// this isn't a cancelation point because we don't acknowledge eintr
@ -444,6 +447,9 @@ privileged void klog(const char *b, size_t n) {
: "=r"(res_x0)
: "r"(r0), "r"(r1), "r"(r2), "r"(r8), "r"(r16)
: "memory");
if (res_x0 < 0) {
__klog_handle = 0;
}
#else
#error "unsupported architecture"
#endif

69
libc/str/joinpaths.c Normal file
View 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 2023 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/str/str.h"
/**
* Joins paths, e.g.
*
* 0 + 0 0
* "" + "" ""
* "a" + 0 "a"
* "a" + "" "a/"
* 0 + "b" "b"
* "" + "b" "b"
* "." + "b" "./b"
* "b" + "." "b/."
* "a" + "b" "a/b"
* "a/" + "b" "a/b"
* "a" + "b/" "a/b/"
* "a" + "/b" "/b"
*
* @return joined path, which may be `buf`, `path`, or `other`, or null
* if (1) `buf` didn't have enough space, or (2) both `path` and
* `other` were null
*/
char *__join_paths(char *buf, size_t size, const char *path,
const char *other) {
size_t pathlen, otherlen;
if (!other) return (char *)path;
if (!path) return (char *)other;
pathlen = strlen(path);
if (!pathlen || *other == '/') {
return (/*unconst*/ char *)other;
}
otherlen = strlen(other);
if (path[pathlen - 1] == '/') {
if (pathlen + otherlen + 1 <= size) {
memmove(buf, path, pathlen);
memmove(buf + pathlen, other, otherlen + 1);
return buf;
} else {
return 0;
}
} else {
if (pathlen + 1 + otherlen + 1 <= size) {
memmove(buf, path, pathlen);
buf[pathlen] = '/';
memmove(buf + pathlen + 1, other, otherlen + 1);
return buf;
} else {
return 0;
}
}
}

View file

@ -217,6 +217,7 @@ axdx_t tprecode8to16(char16_t *, size_t, const char *);
axdx_t tprecode16to8(char *, size_t, const char16_t *);
bool wcsstartswith(const wchar_t *, const wchar_t *) strlenesque;
bool wcsendswith(const wchar_t *, const wchar_t *) strlenesque;
char *__join_paths(char *, size_t, const char *, const char *) __wur;
#endif /* _COSMO_SOURCE */
COSMOPOLITAN_C_END_