From 13c1c45075cb2a12e0624d392da9382cca040e4b Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 7 Aug 2022 05:59:53 -0700 Subject: [PATCH] Make some last minute improvements to make.com --- Makefile | 6 ++- libc/calls/calls.h | 1 + libc/calls/chdir.c | 1 + libc/calls/pivot_root.c | 33 +++++++++++++ libc/calls/syscall-sysv.internal.h | 2 + libc/calls/unmount.c | 11 +++-- libc/runtime/isdynamicexecutable.c | 78 ++++++++++++++++++++++++++++++ libc/runtime/runtime.h | 1 + libc/stdio/mkdtemp.c | 8 ++- libc/sysv/calls/pivot_root.s | 2 - libc/sysv/calls/sys_pivot_root.s | 2 + libc/sysv/syscalls.sh | 2 +- third_party/make/job.c | 33 +++++++------ third_party/make/main.c | 1 + third_party/make/make.mk | 3 +- tool/build/pledge.c | 17 ------- 16 files changed, 158 insertions(+), 43 deletions(-) create mode 100644 libc/calls/pivot_root.c create mode 100644 libc/runtime/isdynamicexecutable.c delete mode 100644 libc/sysv/calls/pivot_root.s create mode 100644 libc/sysv/calls/sys_pivot_root.s diff --git a/Makefile b/Makefile index 37b7f5fac..9956c6589 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ # build/config.mk SHELL = build/bootstrap/cocmd.com -HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win7 win10 xnu +HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win10 xnu MAKEFLAGS += --no-builtin-rules .SUFFIXES: @@ -365,7 +365,9 @@ o/cosmopolitan.h: \ o/cosmopolitan.html: \ o/$(MODE)/third_party/chibicc/chibicc.com.dbg \ - $(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) + $(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \ + $(SRCS) \ + $(HDRS) $(file >$@.args,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS)))) o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \ -fno-common -include libc/integral/normalize.inc -o $@ \ diff --git a/libc/calls/calls.h b/libc/calls/calls.h index 293bf1edc..478f985ec 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -142,6 +142,7 @@ int pause(void); int personality(uint64_t); int pipe(int[hasatleast 2]); int pipe2(int[hasatleast 2], int); +int pivot_root(const char *, const char *); int pledge(const char *, const char *); int posix_fadvise(int, uint64_t, uint64_t, int); int posix_madvise(void *, uint64_t, int); diff --git a/libc/calls/chdir.c b/libc/calls/chdir.c index 8afec0deb..3a65fd719 100644 --- a/libc/calls/chdir.c +++ b/libc/calls/chdir.c @@ -28,6 +28,7 @@ * * This does *not* update the `PWD` environment variable. * + * @return 0 on success, or -1 w/ errno * @asyncsignalsafe * @see fchdir() */ diff --git a/libc/calls/pivot_root.c b/libc/calls/pivot_root.c new file mode 100644 index 000000000..7c81a18e4 --- /dev/null +++ b/libc/calls/pivot_root.c @@ -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/strace.internal.h" +#include "libc/calls/syscall-sysv.internal.h" + +/** + * Changes root mount. + * + * @raise ENOSYS on non-Linux + */ +int pivot_root(const char *new_root, const char *put_old) { + int rc; + rc = sys_pivot_root(new_root, put_old); + STRACE("pivot_root(%#s, %#s) → %d% m", new_root, put_old, rc); + return rc; +} diff --git a/libc/calls/syscall-sysv.internal.h b/libc/calls/syscall-sysv.internal.h index 4fd97ef72..771613f61 100644 --- a/libc/calls/syscall-sysv.internal.h +++ b/libc/calls/syscall-sysv.internal.h @@ -68,6 +68,7 @@ i32 sys_mincore(void *, u64, unsigned char *) hidden; i32 sys_mkdirat(i32, const char *, u32) hidden; i32 sys_mkfifo(const char *, u32) hidden; i32 sys_mknod(const char *, u32, u64) hidden; +i32 sys_unmount(const char *, i32) hidden; i32 sys_mprotect(void *, u64, i32) hidden; i32 sys_msync(void *, u64, i32) hidden; i32 sys_munmap(void *, u64) hidden; @@ -76,6 +77,7 @@ i32 sys_openat(i32, const char *, i32, u32) hidden; i32 sys_pause(void) hidden; i32 sys_pipe(i32[hasatleast 2]) hidden; i32 sys_pipe2(i32[hasatleast 2], u32) hidden; +i32 sys_pivot_root(const char *, const char *) hidden; i32 sys_pledge(const char *, const char *) hidden; i32 sys_posix_openpt(i32) hidden; i32 sys_renameat(i32, const char *, i32, const char *) hidden; diff --git a/libc/calls/unmount.c b/libc/calls/unmount.c index 46eee4447..ca4278f62 100644 --- a/libc/calls/unmount.c +++ b/libc/calls/unmount.c @@ -17,8 +17,8 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/mount.h" - -int sys_unmount(const char *, int); +#include "libc/calls/strace.internal.h" +#include "libc/calls/syscall-sysv.internal.h" /** * Unmounts file system. @@ -30,12 +30,15 @@ int sys_unmount(const char *, int); * The following flags may also be used, but could be set to zero at * runtime if the underlying kernel doesn't support them. * - * - `MNT_DETACH` + * - `MNT_DETACH`: lazily unmount; Linux-only * - `MNT_EXPIRE` * - `UMOUNT_NOFOLLOW` * - `MNT_BYFSID` * */ int unmount(const char *target, int flags) { - return sys_unmount(target, flags); + int rc; + rc = sys_unmount(target, flags); + STRACE("unmount(%#s, %#x) → %d% m", target, flags, rc); + return rc; } diff --git a/libc/runtime/isdynamicexecutable.c b/libc/runtime/isdynamicexecutable.c new file mode 100644 index 000000000..4005c729f --- /dev/null +++ b/libc/runtime/isdynamicexecutable.c @@ -0,0 +1,78 @@ +/*-*- 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/bits/bits.h" +#include "libc/calls/calls.h" +#include "libc/calls/struct/stat.h" +#include "libc/elf/def.h" +#include "libc/elf/elf.h" +#include "libc/elf/struct/ehdr.h" +#include "libc/elf/struct/phdr.h" +#include "libc/errno.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/prot.h" + +/** + * Returns true if ELF executable uses dynamic loading magic. + */ +bool IsDynamicExecutable(const char *prog) { + bool res; + Elf64_Ehdr *e; + Elf64_Phdr *p; + struct stat st; + int i, fd, err; + fd = -1; + err = errno; + e = MAP_FAILED; + if ((fd = open(prog, O_RDONLY)) == -1) { + res = false; + goto Finish; + } + if (fstat(fd, &st) == -1 || st.st_size < 64) { + res = false; + goto Finish; + } + if ((e = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + res = false; + goto Finish; + } + if (READ32LE(e->e_ident) != READ32LE(ELFMAG)) { + res = false; + goto Finish; + } + if (e->e_type == ET_DYN) { + res = true; + goto Finish; + } + for (i = 0; i < e->e_phnum; ++i) { + p = GetElfSegmentHeaderAddress(e, st.st_size, i); + if (p->p_type == PT_INTERP || p->p_type == PT_DYNAMIC) { + res = true; + goto Finish; + } + } + res = false; + goto Finish; +Finish: + if (e != MAP_FAILED) munmap(e, st.st_size); + if (fd != -1) close(fd); + errno = err; + return res; +} diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index 6760ff9bc..94f4f60c4 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -120,6 +120,7 @@ unsigned char *GetInstructionLengths(void); void __print_maps(void); void __warn_if_powersave(void); const char *__describe_os(void); +bool IsDynamicExecutable(const char *); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/stdio/mkdtemp.c b/libc/stdio/mkdtemp.c index 02edbaa1f..6a9639420 100644 --- a/libc/stdio/mkdtemp.c +++ b/libc/stdio/mkdtemp.c @@ -24,7 +24,13 @@ #include "libc/sysv/errfuns.h" /** - * Creates temporary directory. + * Creates temporary directory, e.g. + * + * char path[PATH_MAX]; + * snprintf(path, sizeof(path), "%s%s.XXXXXX", + * kTmpPath, program_invocation_short_name); + * printf("%s\n", mkdtemp(path)); + * rmdir(path); * * @param template must end with XXXXXX which is replaced with * nondeterministic base36 random data diff --git a/libc/sysv/calls/pivot_root.s b/libc/sysv/calls/pivot_root.s deleted file mode 100644 index a87e514e0..000000000 --- a/libc/sysv/calls/pivot_root.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall pivot_root,0xfffffffffffff09b,globl diff --git a/libc/sysv/calls/sys_pivot_root.s b/libc/sysv/calls/sys_pivot_root.s new file mode 100644 index 000000000..f9f832ee5 --- /dev/null +++ b/libc/sysv/calls/sys_pivot_root.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_pivot_root,0xfffffffffffff09b,globl,hidden diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index 5390c14ca..55f7ee433 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -209,7 +209,7 @@ scall cpuset_setaffinity 0xffffff1e8fffffff globl scall sys_sched_rr_get_interval 0xffffff14effff094 globl hidden scall vhangup 0xfffffffffffff099 globl scall modify_ldt 0xfffffffffffff09a globl -scall pivot_root 0xfffffffffffff09b globl +scall sys_pivot_root 0xfffffffffffff09b globl hidden scall _sysctl 0xfffffffffffff09c globl #scall prctl 0xfffffffffffff09d globl # wrapped manually scall sys_arch_prctl 0xfff0a50a5ffff09e globl hidden # sysarch() on bsd diff --git a/third_party/make/job.c b/third_party/make/job.c index 8b84fc2a2..a435abf6f 100644 --- a/third_party/make/job.c +++ b/third_party/make/job.c @@ -38,6 +38,15 @@ this program. If not, see . */ #include "libc/intrin/kprintf.h" #include "libc/bits/safemacros.internal.h" #include "libc/runtime/runtime.h" +#include "libc/elf/def.h" +#include "libc/intrin/kprintf.h" +#include "libc/elf/struct/phdr.h" +#include "libc/elf/def.h" +#include "libc/elf/elf.h" +#include "libc/calls/calls.h" +#include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/map.h" +#include "libc/intrin/kprintf.h" #include "third_party/make/dep.h" #define GOTO_SLOW \ @@ -234,6 +243,7 @@ is_bourne_compatible_shell (const char *path) /* List of known POSIX (or POSIX-ish) shells. */ static const char *unix_shells[] = { "build/bootstrap/cocmd.com", + "false", "dash", "sh", "bash", @@ -1587,20 +1597,6 @@ start_waiting_jobs (void) } -bool IsDynamicExecutable(const char *prog) -{ - int fd; - Elf64_Ehdr e; - struct stat st; - if ((fd = open(prog, O_RDONLY)) == -1) - return false; - if (read(fd, &e, sizeof(e)) != sizeof(e)) - return false; - close(fd); - return e.e_type == ET_DYN && - READ32LE(e.e_ident) == READ32LE(ELFMAG); -} - bool GetPermPrefix (const char *path, char out_perm[5], const char **out_path) { int c, n; @@ -1709,6 +1705,7 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv) char outpathbuf[PATH_MAX]; const struct variable *var; c = (struct child *)child; + errno = 0; if (!lookup_variable_in_set (STRING_SIZE_TUPLE(".UNSANDBOXED"), c->file->variables->set)) { @@ -1717,9 +1714,11 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv) if (argv[0][0] == '/' && IsDynamicExecutable (argv[0])) { - /* make it easier to run dynamic system executables */ + /* weaken sandbox if user is using dynamic shared lolbjects */ + Unveil ("/bin", "rx"); Unveil ("/lib", "rx"); Unveil ("/lib64", "rx"); + Unveil ("/usr/bin", "rx"); Unveil ("/usr/lib", "rx"); Unveil ("/usr/lib64", "rx"); Unveil ("/usr/local/lib", "rx"); @@ -1729,6 +1728,9 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv) Unveil ("/etc/ld.so.cache", "r"); Unveil ("/etc/ld.so.conf.d", "r"); Unveil ("/etc/ld.so.preload", "r"); + Unveil ("/usr/include", "r"); + Unveil ("/usr/share/locale", "r"); + Unveil ("/usr/share/locale-langpack", "r"); } else /* permit launching actually portable executables */ @@ -1751,6 +1753,7 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv) Unveil ("/dev/stderr", "rw"); /* unveil cosmopolitan build specific */ + Unveil ("/tmp", "rwc"); Unveil ("o/tmp", "rwcx"); Unveil ("libc/integral", "r"); Unveil ("libc/disclaimer.inc", "r"); diff --git a/third_party/make/main.c b/third_party/make/main.c index 3603dbe00..db78c19d0 100644 --- a/third_party/make/main.c +++ b/third_party/make/main.c @@ -29,6 +29,7 @@ this program. If not, see . */ #include "libc/sysv/consts/sig.h" #include "libc/log/log.h" #include "libc/log/log.h" +#include "libc/log/log.h" #include "third_party/make/getopt.h" STATIC_STACK_SIZE(0x200000); // 2mb stack diff --git a/third_party/make/make.mk b/third_party/make/make.mk index 162f20a31..e610324ac 100644 --- a/third_party/make/make.mk +++ b/third_party/make/make.mk @@ -112,6 +112,7 @@ THIRD_PARTY_MAKE_OBJS = \ THIRD_PARTY_MAKE_DIRECTDEPS = \ LIBC_CALLS \ + LIBC_ELF \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ @@ -123,9 +124,9 @@ THIRD_PARTY_MAKE_DIRECTDEPS = \ LIBC_SYSV \ LIBC_SYSV_CALLS \ LIBC_TIME \ - LIBC_X \ LIBC_TINYMATH \ LIBC_UNICODE \ + LIBC_X \ THIRD_PARTY_COMPILER_RT \ THIRD_PARTY_MUSL \ THIRD_PARTY_GDTOA diff --git a/tool/build/pledge.c b/tool/build/pledge.c index 48c7b0997..576024f97 100644 --- a/tool/build/pledge.c +++ b/tool/build/pledge.c @@ -334,23 +334,6 @@ bool PathExists(const char *path) { } } -bool IsDynamicExecutable(const char *prog) { - int fd; - Elf64_Ehdr e; - struct stat st; - if ((fd = open(prog, O_RDONLY)) == -1) { - kprintf("open(%#s, O_RDONLY) failed: %m\n", prog); - exit(13); - } - if (read(fd, &e, sizeof(e)) != sizeof(e)) { - kprintf("%s: read(64) failed: %m\n", prog); - exit(16); - } - close(fd); - return e.e_type == ET_DYN && // - READ32LE(e.e_ident) == READ32LE(ELFMAG); -} - void Unveil(const char *path, const char *perm) { if (unveil(path, perm) == -1) { kprintf("error: unveil(%#s, %#s) failed: %m\n", path, perm);