mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Avoid sandboxing directory prerequisites
Landlock Make will no longer sandbox prerequisites that end with a trailing slash. This means you can use use directory prerequisites for detecting deleted files when using using globbing, without the effect of unveiling the entire directory. When you do want make to unveil directories, you can omit the trailing slash.
This commit is contained in:
parent
2827df688a
commit
8835b82a7c
14 changed files with 168 additions and 37 deletions
Binary file not shown.
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
5
third_party/make/commands.c
vendored
5
third_party/make/commands.c
vendored
|
@ -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. */
|
||||
|
|
2
third_party/make/filedef.h
vendored
2
third_party/make/filedef.h
vendored
|
@ -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. */
|
||||
|
|
81
third_party/make/job.c
vendored
81
third_party/make/job.c
vendored
|
@ -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"));
|
||||
|
|
2
third_party/make/job.h
vendored
2
third_party/make/job.h
vendored
|
@ -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 *);
|
||||
|
|
3
third_party/make/main.c
vendored
3
third_party/make/main.c
vendored
|
@ -45,7 +45,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#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
|
||||
|
||||
|
|
15
third_party/mbedtls/test/test.mk
vendored
15
third_party/mbedtls/test/test.mk
vendored
|
@ -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
|
||||
|
|
23
third_party/python/python.mk
vendored
23
third_party/python/python.mk
vendored
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) \
|
||||
|
|
Loading…
Reference in a new issue