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;