mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-12 05:59:10 +00:00
Prevent Make from talking to public Internet
This change introduces the nointernet() function which may be called to prevent a process and its descendants from communicating with publicly routable Internet addresses. GNU Make has been modified to always call this function. In the future Landlock Make will have a way to whitelist subnets to override this behavior, or disable it entirely. Support is available for Linux only. Our firewall does not require root access. Calling nointernet() will return control to the caller inside a new process that has a SECCOMP BPF filter installed, which traps network related system calls. Your original process then becomes a permanent ptrace() supervisor that monitors all processes and threads descending from the returned child. Whenever a networking system call happens the kernel will stop the process and wakes up the monitor, which then peeks into the child memory to read the sockaddr_in to determine if it's ok. The downside to doing this is that there can be only one supervisor at a time using ptrace() on a process. So this firewall won't be enabled if you run make under strace or inside gdb. It also makes testing tricky.
This commit is contained in:
parent
8a0a2c0c36
commit
7cf66bc161
48 changed files with 4924 additions and 2046 deletions
|
@ -35,10 +35,11 @@
|
|||
#define WIFCONTINUED(s) ((s) == 0xffff)
|
||||
#define WIFEXITED(s) (!WTERMSIG(s))
|
||||
#define WIFSIGNALED(s) ((0xffff & (s)) - 1u < 0xffu)
|
||||
#define WIFSTOPPED(s) ((short)(((0xffff & (s)) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) (127 & (s))
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
#define WIFSTOPPED(s) \
|
||||
((short)(((0xffff & (unsigned)(s)) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) (127 & (s))
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -115,6 +116,7 @@ int getresuid(uint32_t *, uint32_t *, uint32_t *);
|
|||
int getsid(int) nosideeffect libcesque;
|
||||
int gettid(void) libcesque;
|
||||
int getuid(void) libcesque;
|
||||
int iopl(int);
|
||||
int ioprio_get(int, int);
|
||||
int ioprio_set(int, int, int);
|
||||
int issetugid(void);
|
||||
|
@ -178,6 +180,7 @@ int siginterrupt(int, int);
|
|||
int symlink(const char *, const char *);
|
||||
int symlinkat(const char *, int, const char *);
|
||||
int sync_file_range(int, int64_t, int64_t, unsigned);
|
||||
int sys_ptrace(int, ...);
|
||||
int sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
|
||||
int tgkill(int, int, int);
|
||||
int tkill(int, int);
|
||||
|
@ -194,7 +197,6 @@ int wait(int *);
|
|||
int waitpid(int, int *, int);
|
||||
intptr_t syscall(int, ...);
|
||||
long ptrace(int, ...);
|
||||
size_t GetFileSize(const char *);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
||||
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||
ssize_t getfiledescriptorsize(int);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/pledge.internal.h"
|
||||
#include "libc/calls/struct/bpf.h"
|
||||
|
@ -25,6 +24,7 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
|
@ -517,6 +517,7 @@ static const uint16_t kPledgeStdio[] = {
|
|||
__NR_linux_migrate_pages, //
|
||||
__NR_linux_sync_file_range, //
|
||||
__NR_linux_set_tid_address, //
|
||||
__NR_linux_membarrier, //
|
||||
__NR_linux_nanosleep, //
|
||||
__NR_linux_pipe, //
|
||||
__NR_linux_pipe2, //
|
||||
|
|
|
@ -19,47 +19,15 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/ptrace.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static const char *__ptrace_describe_request(int x) {
|
||||
if (x == -1) return "-1";
|
||||
if (x == PTRACE_TRACEME) return "PTRACE_TRACEME";
|
||||
if (x == PTRACE_PEEKDATA) return "PTRACE_PEEKDATA";
|
||||
if (x == PTRACE_GETFPREGS) return "PTRACE_GETFPREGS";
|
||||
if (x == PTRACE_PEEKTEXT) return "PTRACE_PEEKTEXT";
|
||||
if (x == PTRACE_POKEDATA) return "PTRACE_POKEDATA";
|
||||
if (x == PTRACE_PEEKUSER) return "PTRACE_PEEKUSER";
|
||||
if (x == PTRACE_POKETEXT) return "PTRACE_POKETEXT";
|
||||
if (x == PTRACE_POKEUSER) return "PTRACE_POKEUSER";
|
||||
if (x == PTRACE_GETREGS) return "PTRACE_GETREGS";
|
||||
if (x == PTRACE_GETREGSET) return "PTRACE_GETREGSET";
|
||||
if (x == PTRACE_SETFPREGS) return "PTRACE_SETFPREGS";
|
||||
if (x == PTRACE_SETREGS) return "PTRACE_SETREGS";
|
||||
if (x == PTRACE_SETREGSET) return "PTRACE_SETREGSET";
|
||||
if (x == PTRACE_GETSIGINFO) return "PTRACE_GETSIGINFO";
|
||||
if (x == PTRACE_SETSIGINFO) return "PTRACE_SETSIGINFO";
|
||||
if (x == PTRACE_PEEKSIGINFO) return "PTRACE_PEEKSIGINFO";
|
||||
if (x == PTRACE_GETSIGMASK) return "PTRACE_GETSIGMASK";
|
||||
if (x == PTRACE_SETSIGMASK) return "PTRACE_SETSIGMASK";
|
||||
if (x == PTRACE_SETOPTIONS) return "PTRACE_SETOPTIONS";
|
||||
if (x == PTRACE_GETEVENTMSG) return "PTRACE_GETEVENTMSG";
|
||||
if (x == PTRACE_CONT) return "PTRACE_CONT";
|
||||
if (x == PTRACE_SINGLESTEP) return "PTRACE_SINGLESTEP";
|
||||
if (x == PTRACE_SYSCALL) return "PTRACE_SYSCALL";
|
||||
if (x == PTRACE_LISTEN) return "PTRACE_LISTEN";
|
||||
if (x == PTRACE_KILL) return "PTRACE_KILL";
|
||||
if (x == PTRACE_INTERRUPT) return "PTRACE_INTERRUPT";
|
||||
if (x == PTRACE_ATTACH) return "PTRACE_ATTACH";
|
||||
if (x == PTRACE_SEIZE) return "PTRACE_SEIZE";
|
||||
if (x == PTRACE_SECCOMP_GET_FILTER) return "PTRACE_SECCOMP_GET_FILTER";
|
||||
if (x == PTRACE_DETACH) return "PTRACE_DETACH";
|
||||
return "PTRACE_WUT";
|
||||
}
|
||||
|
||||
/**
|
||||
* Traces process.
|
||||
*
|
||||
* This API is terrible. Consider using sys_ptrace().
|
||||
*
|
||||
* @param request can be PTRACE_xxx
|
||||
* @note de facto linux only atm
|
||||
* @vforksafe
|
||||
|
@ -69,22 +37,21 @@ long ptrace(int request, ...) {
|
|||
int pid;
|
||||
va_list va;
|
||||
bool ispeek;
|
||||
long rc, peek;
|
||||
void *addr, *data;
|
||||
long rc, peek, addr, *data;
|
||||
va_start(va, request);
|
||||
pid = va_arg(va, int);
|
||||
addr = va_arg(va, void *);
|
||||
data = va_arg(va, void *);
|
||||
addr = va_arg(va, long);
|
||||
data = va_arg(va, long *);
|
||||
va_end(va);
|
||||
if (request == -1) {
|
||||
rc = einval(); /* see consts.sh */
|
||||
} else {
|
||||
ispeek = IsLinux() && request - 1u < 3;
|
||||
if (ispeek) data = &peek;
|
||||
rc = sys_ptrace(request, pid, addr, data);
|
||||
rc = __sys_ptrace(request, pid, addr, data);
|
||||
if (rc != -1 && ispeek) rc = peek;
|
||||
}
|
||||
STRACE("ptrace(%s, %d, %p, %p) → %ld% m", __ptrace_describe_request(request),
|
||||
pid, addr, data);
|
||||
STRACE("ptrace(%s, %d, %p, %p) → %p% m", DescribePtrace(request), pid, addr,
|
||||
data, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ 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 │
|
||||
|
@ -17,20 +17,44 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
|
||||
#define IsPeek(request) (IsLinux() && (request)-1u < 3)
|
||||
|
||||
/**
|
||||
* Returns the byte length of file by path.
|
||||
* Traces process.
|
||||
*
|
||||
* @return number of bytes, or -1ul w/ errno
|
||||
* @see getfiledescriptorsize()
|
||||
* @param op can be PTRACE_xxx
|
||||
* @param pid is child process id
|
||||
* @param addr points inside child address space
|
||||
* @param data is address of output word when peeking
|
||||
* @note de facto linux only
|
||||
* @vforksafe
|
||||
*/
|
||||
size_t GetFileSize(const char *pathname) {
|
||||
struct stat st;
|
||||
if (stat(pathname, &st) == -1) return SIZE_MAX;
|
||||
return st.st_size;
|
||||
int sys_ptrace(int op, ...) {
|
||||
va_list va;
|
||||
int rc, pid;
|
||||
long addr, *data;
|
||||
va_start(va, op);
|
||||
pid = va_arg(va, int);
|
||||
addr = va_arg(va, long);
|
||||
data = va_arg(va, long *);
|
||||
va_end(va);
|
||||
rc = __sys_ptrace(op, pid, addr, data);
|
||||
#ifdef SYSDEBUG
|
||||
if (UNLIKELY(__strace > 0)) {
|
||||
if (rc != -1 && IsPeek(op) && data) {
|
||||
STRACE("sys_ptrace(%s, %d, %p, [%p]) → %p% m", DescribePtrace(op), pid,
|
||||
addr, *data, rc);
|
||||
} else {
|
||||
STRACE("sys_ptrace(%s, %d, %p, %p) → %p% m", DescribePtrace(op), pid,
|
||||
addr, data, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
|
@ -104,10 +104,10 @@ i32 sys_uname(void *) hidden;
|
|||
i32 sys_unlinkat(i32, const char *, i32) hidden;
|
||||
i32 sys_unmount(const char *, i32) hidden;
|
||||
i32 sys_unveil(const char *, const char *) hidden;
|
||||
i64 __sys_ptrace(i32, i32, i64, long *) hidden;
|
||||
i64 sys_copy_file_range(i32, long *, i32, long *, u64, u32) hidden;
|
||||
i64 sys_getrandom(void *, u64, u32) hidden;
|
||||
i64 sys_pread(i32, void *, u64, i64, i64) hidden;
|
||||
i64 sys_ptrace(int, i32, void *, void *) hidden;
|
||||
i64 sys_pwrite(i32, const void *, u64, i64, i64) hidden;
|
||||
i64 sys_read(i32, void *, u64) hidden;
|
||||
i64 sys_readlink(const char *, char *, u64) hidden;
|
||||
|
|
|
@ -13,11 +13,6 @@
|
|||
#define DEV_BSIZE 512
|
||||
#define NOGROUP (-1)
|
||||
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -32,9 +33,12 @@
|
|||
* @error ENOENT
|
||||
*/
|
||||
int truncate(const char *path, uint64_t length) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
return sys_truncate(path, length, length);
|
||||
rc = sys_truncate(path, length, length);
|
||||
} else {
|
||||
return sys_truncate_nt(path, length);
|
||||
rc = sys_truncate_nt(path, length);
|
||||
}
|
||||
STRACE("truncate(%#s, %'ld) → %d% m", path, length, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue