diff --git a/build/bootstrap/ar.com b/build/bootstrap/ar.com index d841f225c..4acd9ca56 100755 Binary files a/build/bootstrap/ar.com and b/build/bootstrap/ar.com differ diff --git a/build/rules.mk b/build/rules.mk index 421ff45e8..fb8d8a5cc 100644 --- a/build/rules.mk +++ b/build/rules.mk @@ -25,7 +25,6 @@ o/%.o: o/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $( o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $< o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $< o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $< -o/%.zip.o: o/% ; @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@ o/$(MODE)/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $< @@ -45,7 +44,6 @@ o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncab o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $< o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS) -o/$(MODE)/%.zip.o: % ; @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-gcc.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $< o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< @@ -100,9 +98,36 @@ o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/as @$(COMPILE) -wACP -T$@ o/$(MODE)/tool/build/cp.com $< $@ @$(COMPILE) -wAASSIMILATE -T$@ o/$(MODE)/tool/build/assimilate.com $@ +################################################################################ +# elf zip files +# +# zipobj.com lets us do fast incremental linking of compressed data. +# it's nice because if we link a hundred binaries that use the time zone +# database, then that database only needs to be DEFLATE'd once. + +o/%.zip.o: o/% + @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< + +o/$(MODE)/%.zip.o: % + @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< + +o/$(MODE)/%.zip.o: % + @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< + +# an issue with sandboxing arises when creating directory entries in the +# zip file. we need the trailing slash (e.g. o//foo/.zip.o) but Landlock +# Make avoids sandboxing directory names that have a trailing slash (so +# they can be used to watch for deleted files, without creating overly +# broad unveiling). such rules need to be written more explicitly. +o/$(MODE)%/.zip.o: % + @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $< + ################################################################################ # strict header checking -# these rules are unsandboxed since they're kind of a sandboxing test themselves +# +# these rules are unsandboxed since they're already a sandboxing test, +# and it would be too costly in terms of make latency to have every +# header file depend on $(HDRS) and $(INCS). o/%.h.ok: .UNSANDBOXED = 1 o/%.h.ok: %.h diff --git a/libc/time/time.mk b/libc/time/time.mk index af8f83040..840d3a4ca 100644 --- a/libc/time/time.mk +++ b/libc/time/time.mk @@ -66,6 +66,9 @@ o/$(MODE)/libc/time/now.o: private \ OVERRIDE_CFLAGS += \ -O3 +o/$(MODE)/usr/share/zoneinfo/.zip.o: \ + usr/share/zoneinfo + LIBC_TIME_LIBS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x))) LIBC_TIME_SRCS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_SRCS)) LIBC_TIME_HDRS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_HDRS)) diff --git a/net/https/https.mk b/net/https/https.mk index ce45d668e..68162f68a 100644 --- a/net/https/https.mk +++ b/net/https/https.mk @@ -48,6 +48,9 @@ $(NET_HTTPS_A).pkg: \ $(NET_HTTPS_A_OBJS) \ $(foreach x,$(NET_HTTPS_A_DIRECTDEPS),$($(x)_A).pkg) +o/$(MODE)/usr/share/ssl/root/.zip.o: \ + usr/share/ssl/root + NET_HTTPS_LIBS = $(foreach x,$(NET_HTTPS_ARTIFACTS),$($(x))) NET_HTTPS_SRCS = $(foreach x,$(NET_HTTPS_ARTIFACTS),$($(x)_SRCS)) NET_HTTPS_HDRS = $(foreach x,$(NET_HTTPS_ARTIFACTS),$($(x)_HDRS)) diff --git a/third_party/make/commands.c b/third_party/make/commands.c index 48f98daed..eb361b212 100644 --- a/third_party/make/commands.c +++ b/third_party/make/commands.c @@ -531,7 +531,10 @@ fatal_error_signal (int sig) (void) remote_kill (c->pid, sig); for (c = children; c != 0; c = c->next) - delete_child_targets (c); + { + delete_child_targets (c); + delete_tmpdir (c); + } /* Clean up the children. We don't just use the call below because we don't want to print the "Waiting for children" message. */ diff --git a/third_party/make/filedef.h b/third_party/make/filedef.h index 2034fbb88..5bdf90058 100644 --- a/third_party/make/filedef.h +++ b/third_party/make/filedef.h @@ -63,6 +63,8 @@ struct file FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */ FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating has been performed. */ + FILE_TIMESTAMP touched; /* Set if file was created in order for + Landlock LSM to sandbox it. */ unsigned int considered; /* equal to 'considered' if file has been considered on current scan of goal chain */ int command_flags; /* Flags OR'd in for cmds; see commands.h. */ diff --git a/third_party/make/job.c b/third_party/make/job.c index b44a32bdf..3dba95454 100644 --- a/third_party/make/job.c +++ b/third_party/make/job.c @@ -512,6 +512,18 @@ new_tmpdir (const char *tmp, struct file *file) return tmpdir; } +bool +get_file_timestamp (struct file *file) +{ + int e; + struct stat st; + EINTRLOOP (e, stat (file->name, &st)); + if (e == 0) + return FILE_TIMESTAMP_STAT_MODTIME (file->name, st); + else + return NONEXISTENT_MTIME; +} + void delete_tmpdir (struct child *c) { @@ -782,8 +794,16 @@ reap_children (int block, int err) delete_on_error = f != 0 && f->is_target; } if (exit_sig != 0 || delete_on_error) - delete_child_targets (c); - delete_tmpdir (c); + { + delete_child_targets (c); + delete_tmpdir (c); + } + else if (c->file->touched && + c->file->touched != get_file_timestamp (c->file)) + /* If file was created just so it could be sandboxed, then + delete that file even if .DELETE_ON_ERROR isn't used, + but only if the command hasn't modified it. */ + unlink (c->file->name); } else { @@ -831,8 +851,11 @@ reap_children (int block, int err) } if (c->file->update_status != us_success) - /* We failed to start the commands. */ - delete_child_targets (c); + { + /* We failed to start the commands. */ + delete_child_targets (c); + delete_tmpdir (c); + } } else { @@ -2273,20 +2296,25 @@ child_execute_job (struct childbase *child, if (!c->file->phony && strlen(c->file->name) < PATH_MAX) { - int fd, rc, err = errno; - strcpy (outpathbuf, c->file->name); - if (makedirs (dirname (outpathbuf), 0777) == -1) - errno = err; - fd = open (c->file->name, O_RDWR | O_CREAT, 0777); - if (fd != -1) - close (fd); - else if (errno == EEXIST) - errno = err; - else + int fd, rc, err; + if (c->file->last_mtime == NONEXISTENT_MTIME) { - OSS (error, NILF, "%s: touch target failed %s", - c->file->name, strerror (errno)); - _Exit (127); + strcpy (outpathbuf, c->file->name); + err = errno; + if (makedirs (dirname (outpathbuf), 0777) == -1) + errno = err; + fd = open (c->file->name, O_RDWR | O_CREAT, 0777); + if (fd != -1) + close (fd); + else if (errno == EEXIST) + errno = err; + else + { + OSS (error, NILF, "%s: touch target failed %s", + c->file->name, strerror (errno)); + _Exit (127); + } + c->file->touched = get_file_timestamp (c->file); } DB (DB_JOBS, (_("Unveiling %s with permissions %s\n"), c->file->name, "rwx")); @@ -2298,11 +2326,26 @@ child_execute_job (struct childbase *child, } } - /* unveil target prerequisites */ + /* + * unveil target prerequisites + * + * directories get special treatment: + * + * - libc/nt + * shall unveil everything beneath dir + * + * - libc/nt/ + * no sandboxing due to trailing slash + * intended to be timestamp check only + */ for (d = c->file->deps; d; d = d->next) { + size_t n; + n = strlen (d->file->name); + if (n && d->file->name[n - 1] == '/') + continue; RETURN_ON_ERROR (Unveil (d->file->name, "rx")); - if (endswith (d->file->name, ".com")) + if (n > 4 && READ32LE(d->file->name + n - 4) == READ32LE(".com")) { s = xstrcat (d->file->name, ".dbg"); RETURN_ON_ERROR (Unveil (s, "rx")); diff --git a/third_party/make/job.h b/third_party/make/job.h index f52846e25..6992485aa 100644 --- a/third_party/make/job.h +++ b/third_party/make/job.h @@ -85,3 +85,5 @@ void unblock_all_sigs (void); extern unsigned int job_slots_used; extern unsigned int jobserver_tokens; + +void delete_tmpdir (struct child *); diff --git a/third_party/make/main.c b/third_party/make/main.c index db4179e69..114d95ca8 100644 --- a/third_party/make/main.c +++ b/third_party/make/main.c @@ -45,7 +45,7 @@ this program. If not, see . */ #include "third_party/make/getopt.h" // clang-format off -STATIC_STACK_SIZE(0x200000); // 2mb stack +STATIC_STACK_SIZE(0x00800000); // 8mb stack #define HAVE_WAIT_NOHANG @@ -1034,6 +1034,7 @@ main (int argc, char **argv, char **envp) FATAL_SIG (SIGTERM); FATAL_SIG (SIGXCPU); FATAL_SIG (SIGXFSZ); + FATAL_SIG (SIGPIPE); /* [jart] handle case of piped into less */ #undef FATAL_SIG diff --git a/third_party/mbedtls/test/test.mk b/third_party/mbedtls/test/test.mk index 177828317..464f5a55c 100644 --- a/third_party/mbedtls/test/test.mk +++ b/third_party/mbedtls/test/test.mk @@ -1365,3 +1365,18 @@ o/$(MODE)/third_party/mbedtls/test/secp384r1_test.com.dbg: \ @$(APELINK) o/$(MODE)/third_party/mbedtls/test/test_suite_asn1parse.com.runs: private QUOTA = -M512m + +# these need to be explictly defined because landlock make won't sandbox +# prerequisites with a trailing slash. +o/$(MODE)/third_party/mbedtls/test/data/.zip.o: \ + third_party/mbedtls/test/data +o/$(MODE)/third_party/mbedtls/test/data/dir-maxpath/.zip.o: \ + third_party/mbedtls/test/data/dir-maxpath +o/$(MODE)/third_party/mbedtls/test/data/dir1/.zip.o: \ + third_party/mbedtls/test/data/dir1 +o/$(MODE)/third_party/mbedtls/test/data/dir2/.zip.o: \ + third_party/mbedtls/test/data/dir2 +o/$(MODE)/third_party/mbedtls/test/data/dir3/.zip.o: \ + third_party/mbedtls/test/data/dir3 +o/$(MODE)/third_party/mbedtls/test/data/dir4/.zip.o: \ + third_party/mbedtls/test/data/dir4 diff --git a/third_party/python/python.mk b/third_party/python/python.mk index ac62f039b..910fdfca6 100644 --- a/third_party/python/python.mk +++ b/third_party/python/python.mk @@ -4490,6 +4490,29 @@ o/$(MODE)/third_party/python/hello.com.dbg: \ $(THIRD_PARTY_PYTHON_HELLO_OBJS): private PYFLAGS += -C2 -m +# these need to be explictly defined because landlock make won't sandbox +# prerequisites with a trailing slash. +o/$(MODE)/third_party/python/Lib/pydoc_data/.zip.o: \ + third_party/python/Lib/pydoc_data +o/$(MODE)/third_party/python/Lib/test/xmltestdata/.zip.o: \ + third_party/python/Lib/test/xmltestdata +o/$(MODE)/third_party/python/Lib/test/sndhdrdata/.zip.o: \ + third_party/python/Lib/test/sndhdrdata +o/$(MODE)/third_party/python/Lib/test/imghdrdata/.zip.o: \ + third_party/python/Lib/test/imghdrdata +o/$(MODE)/third_party/python/Lib/test/decimaltestdata/.zip.o: \ + third_party/python/Lib/test/decimaltestdata +o/$(MODE)/third_party/python/Lib/test/dtracedata/.zip.o: \ + third_party/python/Lib/test/dtracedata +o/$(MODE)/third_party/python/Lib/test/cjkencodings/.zip.o: \ + third_party/python/Lib/test/cjkencodings +o/$(MODE)/third_party/python/Modules/.zip.o: \ + third_party/python/Modules +o/$(MODE)/third_party/python/Objects/.zip.o: \ + third_party/python/Objects +o/$(MODE)/third_party/python/Lib/test/.zip.o: \ + third_party/python/Lib/test + ################################################################################ .PHONY: o/$(MODE)/third_party/python diff --git a/tool/build/ar.c b/tool/build/ar.c index a27840501..8c32db94f 100644 --- a/tool/build/ar.c +++ b/tool/build/ar.c @@ -16,10 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/mem/arraylist2.internal.h" #include "libc/assert.h" -#include "libc/intrin/bits.h" -#include "libc/intrin/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/stat.h" @@ -27,10 +24,13 @@ #include "libc/errno.h" #include "libc/fmt/conv.h" #include "libc/fmt/itoa.h" +#include "libc/intrin/bits.h" #include "libc/intrin/kprintf.h" +#include "libc/intrin/safemacros.internal.h" #include "libc/log/check.h" #include "libc/log/log.h" #include "libc/macros.internal.h" +#include "libc/mem/arraylist2.internal.h" #include "libc/mem/io.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" @@ -233,12 +233,12 @@ int main(int argc, char *argv[]) { for (i = 0;; ++i) { TryAgain: if (!(arg = getargs_next(&ga))) break; + if (endswith(arg, "/")) goto TryAgain; + if (endswith(arg, ".pkg")) goto TryAgain; + CHECK_NE(-1, stat(arg, st), "%s", arg); + if (!st->st_size || S_ISDIR(st->st_mode)) goto TryAgain; CHECK_NE(-1, (fd = open(arg, O_RDONLY)), "%s", arg); - CHECK_NE(-1, fstat(fd, st)); CHECK_LT(st->st_size, 0x7ffff000); - if (!st->st_size || S_ISDIR(st->st_mode) || endswith(arg, ".pkg")) { - goto TryAgain; - } AppendArg(&args, xstrdup(arg)); AppendInt(&names, filenames.i); AppendInt(&sizes, st->st_size); diff --git a/tool/build/package.c b/tool/build/package.c index 8c3b5f176..391a0cbbf 100644 --- a/tool/build/package.c +++ b/tool/build/package.c @@ -16,17 +16,17 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/mem/alg.h" -#include "libc/mem/arraylist.internal.h" -#include "libc/intrin/bswap.h" -#include "libc/intrin/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" #include "libc/elf/elf.h" #include "libc/elf/struct/shdr.h" #include "libc/elf/struct/sym.h" +#include "libc/intrin/bswap.h" +#include "libc/intrin/safemacros.internal.h" #include "libc/log/check.h" #include "libc/log/log.h" +#include "libc/mem/alg.h" +#include "libc/mem/arraylist.internal.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -134,8 +134,10 @@ struct Package *LoadPackage(const char *path) { CHECK(fileexists(path), "%s: %s: %s\n", "error", path, "not found"); CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path); CHECK_NE(-1, fstat(fd, &st)); - CHECK_NE(MAP_FAILED, (pkg = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fd, 0))); + CHECK_NE(MAP_FAILED, + (pkg = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, + fd, 0)), + "path=%s", path); CHECK_NE(-1, close(fd)); CHECK_EQ(PACKAGE_MAGIC, pkg->magic, "corrupt package: %`'s", path); pkg->strings.p = (char *)((intptr_t)pkg->strings.p + (intptr_t)pkg); diff --git a/tool/net/net.mk b/tool/net/net.mk index 47ed64f39..464ceabfe 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -286,6 +286,15 @@ o/$(MODE)/tool/net/redbean-original.com.dbg: \ $(APE_NO_MODIFY_SELF) @$(APELINK) +o/$(MODE)/tool/net/demo/.lua/.zip.o: \ + tool/net/demo/.lua +o/$(MODE)/tool/net/demo/.zip.o: \ + tool/net/demo +o/$(MODE)/tool/net/.zip.o: \ + tool/net +o/$(MODE)/tool/.zip.o: \ + tool + .PHONY: o/$(MODE)/tool/net o/$(MODE)/tool/net: \ $(TOOL_NET_BINS) \