Cherry-pick bug fixes and Landlock Make 1.0.2

This commit is contained in:
Justine Tunney 2022-08-10 12:56:45 -07:00
parent c1d99676c4
commit 7e1c78b4f3
13 changed files with 468 additions and 64 deletions

View file

@ -255,12 +255,12 @@ o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS
TAGS: .UNSANDBOXED = 1
TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
@$(RM) $@
@$(COMPILE) -ATAGS -T$@ $(TAGS) $(TAGSFLAGS) -L $< -o $@
@$(TAGS) $(TAGSFLAGS) -L $< -o $@
HTAGS: .UNSANDBOXED = 1
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
@$(RM) $@
@$(COMPILE) -ATAGS -T$@ build/htags -L $< -o $@
@build/htags -L $< -o $@
loc: .UNSANDBOXED = 1
loc: o/$(MODE)/tool/build/summy.com

View file

@ -96,7 +96,7 @@ o/$(MODE)/examples/pylife/pylife.com.dbg: \
o/$(MODE)/examples/pylife/pylife.o \
$(CRT) \
$(APE_NO_MODIFY_SELF)
$(LINK) $(LINKARGS) -o $@
@$(COMPILE) -ALINK.ape $(LINK) $(LINKARGS) -o $@
# # Unwrap the APE .COM binary, that's embedded within the linked file
# # NOTE: This line can be commented out, since it's in build/rules.mk

View file

@ -24,7 +24,8 @@
*/
int64_t _timespec_tomicros(struct timespec x) {
int64_t us;
if (!__builtin_add_overflow(x.tv_sec, x.tv_nsec / 1000, &us)) {
if (!__builtin_mul_overflow(x.tv_sec, 1000000ul, &us) &&
!__builtin_add_overflow(us, x.tv_nsec / 1000, &us)) {
return us;
} else {
return INT64_MAX;

View file

@ -23,9 +23,10 @@
* Converts timespec interval to milliseconds.
*/
int64_t _timespec_tomillis(struct timespec x) {
int64_t us;
if (!__builtin_add_overflow(x.tv_sec, x.tv_nsec / 1000000, &us)) {
return us;
int64_t ms;
if (!__builtin_mul_overflow(x.tv_sec, 1000ul, &ms) &&
!__builtin_add_overflow(ms, x.tv_nsec / 1000000, &ms)) {
return ms;
} else {
return INT64_MAX;
}

View file

@ -47,8 +47,9 @@
#define Eperm 1
#define Sigabrt 6
#define Enosys 38
#define Einval 22
#define Sigsys 31
#define Enosys 38
#define Sig_Setmask 2
#define Sa_Siginfo 4
#define Sa_Restorer 0x04000000
@ -84,6 +85,356 @@ struct Filter {
struct sock_filter p[700];
};
static const struct thatispacked SyscallName {
uint16_t n;
const char *const s;
} kSyscallName[] = {
{__NR_linux_exit, "exit"}, //
{__NR_linux_exit_group, "exit_group"}, //
{__NR_linux_read, "read"}, //
{__NR_linux_write, "write"}, //
{__NR_linux_open, "open"}, //
{__NR_linux_close, "close"}, //
{__NR_linux_stat, "stat"}, //
{__NR_linux_fstat, "fstat"}, //
{__NR_linux_lstat, "lstat"}, //
{__NR_linux_poll, "poll"}, //
{__NR_linux_ppoll, "ppoll"}, //
{__NR_linux_brk, "brk"}, //
{__NR_linux_sigreturn, "sigreturn"}, //
{__NR_linux_lseek, "lseek"}, //
{__NR_linux_mmap, "mmap"}, //
{__NR_linux_msync, "msync"}, //
{__NR_linux_mprotect, "mprotect"}, //
{__NR_linux_munmap, "munmap"}, //
{__NR_linux_sigaction, "sigaction"}, //
{__NR_linux_sigprocmask, "sigprocmask"}, //
{__NR_linux_ioctl, "ioctl"}, //
{__NR_linux_pread, "pread"}, //
{__NR_linux_pwrite, "pwrite"}, //
{__NR_linux_readv, "readv"}, //
{__NR_linux_writev, "writev"}, //
{__NR_linux_access, "access"}, //
{__NR_linux_pipe, "pipe"}, //
{__NR_linux_select, "select"}, //
{__NR_linux_pselect6, "pselect6"}, //
{__NR_linux_sched_yield, "sched_yield"}, //
{__NR_linux_mremap, "mremap"}, //
{__NR_linux_mincore, "mincore"}, //
{__NR_linux_madvise, "madvise"}, //
{__NR_linux_shmget, "shmget"}, //
{__NR_linux_shmat, "shmat"}, //
{__NR_linux_shmctl, "shmctl"}, //
{__NR_linux_dup, "dup"}, //
{__NR_linux_dup2, "dup2"}, //
{__NR_linux_pause, "pause"}, //
{__NR_linux_nanosleep, "nanosleep"}, //
{__NR_linux_getitimer, "getitimer"}, //
{__NR_linux_setitimer, "setitimer"}, //
{__NR_linux_alarm, "alarm"}, //
{__NR_linux_getpid, "getpid"}, //
{__NR_linux_sendfile, "sendfile"}, //
{__NR_linux_socket, "socket"}, //
{__NR_linux_connect, "connect"}, //
{__NR_linux_accept, "accept"}, //
{__NR_linux_sendto, "sendto"}, //
{__NR_linux_recvfrom, "recvfrom"}, //
{__NR_linux_sendmsg, "sendmsg"}, //
{__NR_linux_recvmsg, "recvmsg"}, //
{__NR_linux_shutdown, "shutdown"}, //
{__NR_linux_bind, "bind"}, //
{__NR_linux_listen, "listen"}, //
{__NR_linux_getsockname, "getsockname"}, //
{__NR_linux_getpeername, "getpeername"}, //
{__NR_linux_socketpair, "socketpair"}, //
{__NR_linux_setsockopt, "setsockopt"}, //
{__NR_linux_getsockopt, "getsockopt"}, //
{__NR_linux_fork, "fork"}, //
{__NR_linux_vfork, "vfork"}, //
{__NR_linux_execve, "execve"}, //
{__NR_linux_wait4, "wait4"}, //
{__NR_linux_kill, "kill"}, //
{__NR_linux_clone, "clone"}, //
{__NR_linux_tkill, "tkill"}, //
{__NR_linux_futex, "futex"}, //
{__NR_linux_set_robust_list, "set_robust_list"}, //
{__NR_linux_get_robust_list, "get_robust_list"}, //
{__NR_linux_uname, "uname"}, //
{__NR_linux_semget, "semget"}, //
{__NR_linux_semop, "semop"}, //
{__NR_linux_semctl, "semctl"}, //
{__NR_linux_shmdt, "shmdt"}, //
{__NR_linux_msgget, "msgget"}, //
{__NR_linux_msgsnd, "msgsnd"}, //
{__NR_linux_msgrcv, "msgrcv"}, //
{__NR_linux_msgctl, "msgctl"}, //
{__NR_linux_fcntl, "fcntl"}, //
{__NR_linux_flock, "flock"}, //
{__NR_linux_fsync, "fsync"}, //
{__NR_linux_fdatasync, "fdatasync"}, //
{__NR_linux_truncate, "truncate"}, //
{__NR_linux_ftruncate, "ftruncate"}, //
{__NR_linux_getcwd, "getcwd"}, //
{__NR_linux_chdir, "chdir"}, //
{__NR_linux_fchdir, "fchdir"}, //
{__NR_linux_rename, "rename"}, //
{__NR_linux_mkdir, "mkdir"}, //
{__NR_linux_rmdir, "rmdir"}, //
{__NR_linux_creat, "creat"}, //
{__NR_linux_link, "link"}, //
{__NR_linux_unlink, "unlink"}, //
{__NR_linux_symlink, "symlink"}, //
{__NR_linux_readlink, "readlink"}, //
{__NR_linux_chmod, "chmod"}, //
{__NR_linux_fchmod, "fchmod"}, //
{__NR_linux_chown, "chown"}, //
{__NR_linux_fchown, "fchown"}, //
{__NR_linux_lchown, "lchown"}, //
{__NR_linux_umask, "umask"}, //
{__NR_linux_gettimeofday, "gettimeofday"}, //
{__NR_linux_getrlimit, "getrlimit"}, //
{__NR_linux_getrusage, "getrusage"}, //
{__NR_linux_sysinfo, "sysinfo"}, //
{__NR_linux_times, "times"}, //
{__NR_linux_ptrace, "ptrace"}, //
{__NR_linux_syslog, "syslog"}, //
{__NR_linux_getuid, "getuid"}, //
{__NR_linux_getgid, "getgid"}, //
{__NR_linux_getppid, "getppid"}, //
{__NR_linux_getpgrp, "getpgrp"}, //
{__NR_linux_setsid, "setsid"}, //
{__NR_linux_getsid, "getsid"}, //
{__NR_linux_getpgid, "getpgid"}, //
{__NR_linux_setpgid, "setpgid"}, //
{__NR_linux_geteuid, "geteuid"}, //
{__NR_linux_getegid, "getegid"}, //
{__NR_linux_getgroups, "getgroups"}, //
{__NR_linux_setgroups, "setgroups"}, //
{__NR_linux_setreuid, "setreuid"}, //
{__NR_linux_setregid, "setregid"}, //
{__NR_linux_setuid, "setuid"}, //
{__NR_linux_setgid, "setgid"}, //
{__NR_linux_setresuid, "setresuid"}, //
{__NR_linux_setresgid, "setresgid"}, //
{__NR_linux_getresuid, "getresuid"}, //
{__NR_linux_getresgid, "getresgid"}, //
{__NR_linux_sigpending, "sigpending"}, //
{__NR_linux_sigsuspend, "sigsuspend"}, //
{__NR_linux_sigaltstack, "sigaltstack"}, //
{__NR_linux_mknod, "mknod"}, //
{__NR_linux_mknodat, "mknodat"}, //
{__NR_linux_statfs, "statfs"}, //
{__NR_linux_fstatfs, "fstatfs"}, //
{__NR_linux_getpriority, "getpriority"}, //
{__NR_linux_setpriority, "setpriority"}, //
{__NR_linux_mlock, "mlock"}, //
{__NR_linux_munlock, "munlock"}, //
{__NR_linux_mlockall, "mlockall"}, //
{__NR_linux_munlockall, "munlockall"}, //
{__NR_linux_setrlimit, "setrlimit"}, //
{__NR_linux_chroot, "chroot"}, //
{__NR_linux_sync, "sync"}, //
{__NR_linux_acct, "acct"}, //
{__NR_linux_settimeofday, "settimeofday"}, //
{__NR_linux_mount, "mount"}, //
{__NR_linux_reboot, "reboot"}, //
{__NR_linux_quotactl, "quotactl"}, //
{__NR_linux_setfsuid, "setfsuid"}, //
{__NR_linux_setfsgid, "setfsgid"}, //
{__NR_linux_capget, "capget"}, //
{__NR_linux_capset, "capset"}, //
{__NR_linux_sigtimedwait, "sigtimedwait"}, //
{__NR_linux_rt_sigqueueinfo, "rt_sigqueueinfo"}, //
{__NR_linux_personality, "personality"}, //
{__NR_linux_ustat, "ustat"}, //
{__NR_linux_sysfs, "sysfs"}, //
{__NR_linux_sched_setparam, "sched_setparam"}, //
{__NR_linux_sched_getparam, "sched_getparam"}, //
{__NR_linux_sched_setscheduler, "sched_setscheduler"}, //
{__NR_linux_sched_getscheduler, "sched_getscheduler"}, //
{__NR_linux_sched_get_priority_max, "sched_get_priority_max"}, //
{__NR_linux_sched_get_priority_min, "sched_get_priority_min"}, //
{__NR_linux_sched_rr_get_interval, "sched_rr_get_interval"}, //
{__NR_linux_vhangup, "vhangup"}, //
{__NR_linux_modify_ldt, "modify_ldt"}, //
{__NR_linux_pivot_root, "pivot_root"}, //
{__NR_linux__sysctl, "_sysctl"}, //
{__NR_linux_prctl, "prctl"}, //
{__NR_linux_arch_prctl, "arch_prctl"}, //
{__NR_linux_adjtimex, "adjtimex"}, //
{__NR_linux_umount2, "umount2"}, //
{__NR_linux_swapon, "swapon"}, //
{__NR_linux_swapoff, "swapoff"}, //
{__NR_linux_sethostname, "sethostname"}, //
{__NR_linux_setdomainname, "setdomainname"}, //
{__NR_linux_iopl, "iopl"}, //
{__NR_linux_ioperm, "ioperm"}, //
{__NR_linux_init_module, "init_module"}, //
{__NR_linux_delete_module, "delete_module"}, //
{__NR_linux_gettid, "gettid"}, //
{__NR_linux_readahead, "readahead"}, //
{__NR_linux_setxattr, "setxattr"}, //
{__NR_linux_fsetxattr, "fsetxattr"}, //
{__NR_linux_getxattr, "getxattr"}, //
{__NR_linux_fgetxattr, "fgetxattr"}, //
{__NR_linux_listxattr, "listxattr"}, //
{__NR_linux_flistxattr, "flistxattr"}, //
{__NR_linux_removexattr, "removexattr"}, //
{__NR_linux_fremovexattr, "fremovexattr"}, //
{__NR_linux_lsetxattr, "lsetxattr"}, //
{__NR_linux_lgetxattr, "lgetxattr"}, //
{__NR_linux_llistxattr, "llistxattr"}, //
{__NR_linux_lremovexattr, "lremovexattr"}, //
{__NR_linux_sched_setaffinity, "sched_setaffinity"}, //
{__NR_linux_sched_getaffinity, "sched_getaffinity"}, //
{__NR_linux_io_setup, "io_setup"}, //
{__NR_linux_io_destroy, "io_destroy"}, //
{__NR_linux_io_getevents, "io_getevents"}, //
{__NR_linux_io_submit, "io_submit"}, //
{__NR_linux_io_cancel, "io_cancel"}, //
{__NR_linux_lookup_dcookie, "lookup_dcookie"}, //
{__NR_linux_epoll_create, "epoll_create"}, //
{__NR_linux_epoll_wait, "epoll_wait"}, //
{__NR_linux_epoll_ctl, "epoll_ctl"}, //
{__NR_linux_getdents, "getdents"}, //
{__NR_linux_set_tid_address, "set_tid_address"}, //
{__NR_linux_restart_syscall, "restart_syscall"}, //
{__NR_linux_semtimedop, "semtimedop"}, //
{__NR_linux_fadvise, "fadvise"}, //
{__NR_linux_timer_create, "timer_create"}, //
{__NR_linux_timer_settime, "timer_settime"}, //
{__NR_linux_timer_gettime, "timer_gettime"}, //
{__NR_linux_timer_getoverrun, "timer_getoverrun"}, //
{__NR_linux_timer_delete, "timer_delete"}, //
{__NR_linux_clock_settime, "clock_settime"}, //
{__NR_linux_clock_gettime, "clock_gettime"}, //
{__NR_linux_clock_getres, "clock_getres"}, //
{__NR_linux_clock_nanosleep, "clock_nanosleep"}, //
{__NR_linux_tgkill, "tgkill"}, //
{__NR_linux_mbind, "mbind"}, //
{__NR_linux_set_mempolicy, "set_mempolicy"}, //
{__NR_linux_get_mempolicy, "get_mempolicy"}, //
{__NR_linux_mq_open, "mq_open"}, //
{__NR_linux_mq_unlink, "mq_unlink"}, //
{__NR_linux_mq_timedsend, "mq_timedsend"}, //
{__NR_linux_mq_timedreceive, "mq_timedreceive"}, //
{__NR_linux_mq_notify, "mq_notify"}, //
{__NR_linux_mq_getsetattr, "mq_getsetattr"}, //
{__NR_linux_kexec_load, "kexec_load"}, //
{__NR_linux_waitid, "waitid"}, //
{__NR_linux_add_key, "add_key"}, //
{__NR_linux_request_key, "request_key"}, //
{__NR_linux_keyctl, "keyctl"}, //
{__NR_linux_ioprio_set, "ioprio_set"}, //
{__NR_linux_ioprio_get, "ioprio_get"}, //
{__NR_linux_inotify_init, "inotify_init"}, //
{__NR_linux_inotify_add_watch, "inotify_add_watch"}, //
{__NR_linux_inotify_rm_watch, "inotify_rm_watch"}, //
{__NR_linux_openat, "openat"}, //
{__NR_linux_mkdirat, "mkdirat"}, //
{__NR_linux_fchownat, "fchownat"}, //
{__NR_linux_utime, "utime"}, //
{__NR_linux_utimes, "utimes"}, //
{__NR_linux_futimesat, "futimesat"}, //
{__NR_linux_fstatat, "fstatat"}, //
{__NR_linux_unlinkat, "unlinkat"}, //
{__NR_linux_renameat, "renameat"}, //
{__NR_linux_linkat, "linkat"}, //
{__NR_linux_symlinkat, "symlinkat"}, //
{__NR_linux_readlinkat, "readlinkat"}, //
{__NR_linux_fchmodat, "fchmodat"}, //
{__NR_linux_faccessat, "faccessat"}, //
{__NR_linux_unshare, "unshare"}, //
{__NR_linux_splice, "splice"}, //
{__NR_linux_tee, "tee"}, //
{__NR_linux_sync_file_range, "sync_file_range"}, //
{__NR_linux_vmsplice, "vmsplice"}, //
{__NR_linux_migrate_pages, "migrate_pages"}, //
{__NR_linux_move_pages, "move_pages"}, //
{__NR_linux_preadv, "preadv"}, //
{__NR_linux_pwritev, "pwritev"}, //
{__NR_linux_utimensat, "utimensat"}, //
{__NR_linux_fallocate, "fallocate"}, //
{__NR_linux_accept4, "accept4"}, //
{__NR_linux_dup3, "dup3"}, //
{__NR_linux_pipe2, "pipe2"}, //
{__NR_linux_epoll_pwait, "epoll_pwait"}, //
{__NR_linux_epoll_create1, "epoll_create1"}, //
{__NR_linux_perf_event_open, "perf_event_open"}, //
{__NR_linux_inotify_init1, "inotify_init1"}, //
{__NR_linux_rt_tgsigqueueinfo, "rt_tgsigqueueinfo"}, //
{__NR_linux_signalfd, "signalfd"}, //
{__NR_linux_signalfd4, "signalfd4"}, //
{__NR_linux_eventfd, "eventfd"}, //
{__NR_linux_eventfd2, "eventfd2"}, //
{__NR_linux_timerfd_create, "timerfd_create"}, //
{__NR_linux_timerfd_settime, "timerfd_settime"}, //
{__NR_linux_timerfd_gettime, "timerfd_gettime"}, //
{__NR_linux_recvmmsg, "recvmmsg"}, //
{__NR_linux_fanotify_init, "fanotify_init"}, //
{__NR_linux_fanotify_mark, "fanotify_mark"}, //
{__NR_linux_prlimit, "prlimit"}, //
{__NR_linux_name_to_handle_at, "name_to_handle_at"}, //
{__NR_linux_open_by_handle_at, "open_by_handle_at"}, //
{__NR_linux_clock_adjtime, "clock_adjtime"}, //
{__NR_linux_syncfs, "syncfs"}, //
{__NR_linux_sendmmsg, "sendmmsg"}, //
{__NR_linux_setns, "setns"}, //
{__NR_linux_getcpu, "getcpu"}, //
{__NR_linux_process_vm_readv, "process_vm_readv"}, //
{__NR_linux_process_vm_writev, "process_vm_writev"}, //
{__NR_linux_kcmp, "kcmp"}, //
{__NR_linux_finit_module, "finit_module"}, //
{__NR_linux_sched_setattr, "sched_setattr"}, //
{__NR_linux_sched_getattr, "sched_getattr"}, //
{__NR_linux_renameat2, "renameat2"}, //
{__NR_linux_seccomp, "seccomp"}, //
{__NR_linux_getrandom, "getrandom"}, //
{__NR_linux_memfd_create, "memfd_create"}, //
{__NR_linux_kexec_file_load, "kexec_file_load"}, //
{__NR_linux_bpf, "bpf"}, //
{__NR_linux_execveat, "execveat"}, //
{__NR_linux_userfaultfd, "userfaultfd"}, //
{__NR_linux_membarrier, "membarrier"}, //
{__NR_linux_mlock2, "mlock2"}, //
{__NR_linux_copy_file_range, "copy_file_range"}, //
{__NR_linux_preadv2, "preadv2"}, //
{__NR_linux_pwritev2, "pwritev2"}, //
{__NR_linux_pkey_mprotect, "pkey_mprotect"}, //
{__NR_linux_pkey_alloc, "pkey_alloc"}, //
{__NR_linux_pkey_free, "pkey_free"}, //
{__NR_linux_statx, "statx"}, //
{__NR_linux_io_pgetevents, "io_pgetevents"}, //
{__NR_linux_rseq, "rseq"}, //
{__NR_linux_pidfd_send_signal, "pidfd_send_signal"}, //
{__NR_linux_io_uring_setup, "io_uring_setup"}, //
{__NR_linux_io_uring_enter, "io_uring_enter"}, //
{__NR_linux_io_uring_register, "io_uring_register"}, //
{__NR_linux_open_tree, "open_tree"}, //
{__NR_linux_move_mount, "move_mount"}, //
{__NR_linux_fsopen, "fsopen"}, //
{__NR_linux_fsconfig, "fsconfig"}, //
{__NR_linux_fsmount, "fsmount"}, //
{__NR_linux_fspick, "fspick"}, //
{__NR_linux_pidfd_open, "pidfd_open"}, //
{__NR_linux_clone3, "clone3"}, //
{__NR_linux_close_range, "close_range"}, //
{__NR_linux_openat2, "openat2"}, //
{__NR_linux_pidfd_getfd, "pidfd_getfd"}, //
{__NR_linux_faccessat2, "faccessat2"}, //
{__NR_linux_process_madvise, "process_madvise"}, //
{__NR_linux_epoll_pwait2, "epoll_pwait2"}, //
{__NR_linux_mount_setattr, "mount_setattr"}, //
{__NR_linux_quotactl_fd, "quotactl_fd"}, //
{__NR_linux_landlock_create_ruleset, "landlock_create_ruleset"}, //
{__NR_linux_landlock_add_rule, "landlock_add_rule"}, //
{__NR_linux_landlock_restrict_self, "landlock_restrict_self"}, //
{__NR_linux_memfd_secret, "memfd_secret"}, //
{__NR_linux_process_mrelease, "process_mrelease"}, //
{__NR_linux_futex_waitv, "futex_waitv"}, //
{__NR_linux_set_mempolicy_home_node, "set_mempolicy_home_node"}, //
};
static const uint16_t kPledgeDefault[] = {
__NR_linux_exit, // thread return / exit()
};
@ -584,6 +935,16 @@ static privileged void KillThisThread(void) {
: "rcx", "r11", "memory");
}
static privileged const char *GetSyscallName(uint16_t n) {
int i;
for (i = 0; i < ARRAYLEN(kSyscallName); ++i) {
if (kSyscallName[i].n == n) {
return kSyscallName[i].s;
}
}
return "unknown";
}
static privileged int HasSyscall(struct Pledges *p, uint16_t n) {
int i;
for (i = 0; i < p->len; ++i) {
@ -606,23 +967,16 @@ static privileged void OnSigSys(int sig, siginfo_t *si, ucontext_t *ctx) {
FixCpy(ord, si->si_syscall, 12);
HexCpy(rip, ctx->uc_mcontext.rip);
for (found = i = 0; i < ARRAYLEN(kPledge); ++i) {
switch (HasSyscall(kPledge + i, si->si_syscall)) {
case 1:
Log("error: should pledge ", kPledge[i].name, //
" (ord=", ord, " rip=", rip, ")\n", 0);
if (HasSyscall(kPledge + i, si->si_syscall)) {
Log("error: pledge ", kPledge[i].name, " for ",
GetSyscallName(si->si_syscall), " (ord=", ord, " rip=", rip, ")\n",
0);
found = true;
break;
case 2:
Log("error: maybe pledge ", kPledge[i].name, //
" (ord=", ord, " rip=", rip, ")\n", 0);
found = true;
break;
default:
break;
}
}
if (!found) {
Log("error: bad syscall (ord=", ord, " rip=", rip, ")\n", 0);
Log("error: bad syscall (", GetSyscallName(si->si_syscall), " ord=", ord,
" rip=", rip, ")\n", 0);
}
switch (mode) {
case kPledgeModeKillProcess:
@ -1554,8 +1908,8 @@ static privileged void AppendPledge(struct Filter *f, //
privileged int sys_pledge_linux(unsigned long ipromises, //
enum PledgeMode mode, //
bool want_msyscall) { //
int i, rc = -1;
struct Filter f;
int i, e, rc = -1;
struct sock_filter sf[1] = {BPF_STMT(BPF_RET | BPF_K, 0)};
CheckLargeStackAllocation(&f, sizeof(f));
f.n = 0;
@ -1610,10 +1964,24 @@ privileged int sys_pledge_linux(unsigned long ipromises, //
AppendFilter(&f, PLEDGE(sf));
}
// drop privileges
//
// PR_SET_SECCOMP (Linux 2.6.23+) will refuse to work if
// PR_SET_NO_NEW_PRIVS (Linux 3.5+) wasn't called so we punt the error
// detection to the seccomp system call below.
Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
// register our seccomp filter with the kernel
if ((rc = Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) != -1) {
struct sock_fprog sandbox = {.len = f.n, .filter = f.p};
rc = Prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox, 0, 0);
// the EINVAL error could mean a lot of things. it could mean the bpf
// code is broken. it could also mean we're running on RHEL5 which
// doesn't have SECCOMP support. since we don't consider lack of
// system support for security to be an error, we distinguish these
// two cases by running a simpler SECCOMP operation.
if (rc == -Einval && Prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == -Einval) {
rc = 0; // -Enosys
}
return rc;

View file

@ -28,14 +28,20 @@
#include "libc/sysv/errfuns.h"
/**
* Restricts system operations, e.g.
* Permits system operations, e.g.
*
* pledge("stdio rfile tty", 0);
* if (pledge("stdio rfile tty", 0)) {
* perror("pledge");
* exit(1);
* }
*
* Pledging causes most system calls to become unavailable. Your system
* call policy is enforced by the kernel (which means it can propagate
* across execve() if permitted). Root access is not required. Support
* is limited to Linux and OpenBSD.
* is limited to Linux 2.6.23+ (c. RHEL6) and OpenBSD. If your kernel
* isn't supported, then pledge() will return 0 and do nothing rather
* than raising ENOSYS. We don't consider lack of system support to be
* an error, because the specified operations will be permitted.
*
* The promises you give pledge() define which system calls are allowed.
* Error messages are logged when sandbox violations occur that well you
@ -213,14 +219,13 @@
* be weakened to have execute permissions too.
*
* @return 0 on success, or -1 w/ errno
* @raise ENOSYS if host os isn't Linux or OpenBSD
* @raise EINVAL if `execpromises` on Linux isn't a subset of `promises`
* @raise EINVAL if `promises` allows exec and `execpromises` is null
* @threadsafe
* @vforksafe
*/
int pledge(const char *promises, const char *execpromises) {
int rc;
int e, rc;
unsigned long ipromises, iexecpromises;
if (!ParsePromises(promises, &ipromises) &&
!ParsePromises(execpromises, &iexecpromises)) {
@ -239,7 +244,12 @@ int pledge(const char *promises, const char *execpromises) {
if (rc > -4096u) errno = -rc, rc = -1;
}
} else {
e = errno;
rc = sys_pledge(promises, execpromises);
if (rc && errno == ENOSYS) {
errno = e;
rc = 0;
}
}
if (!rc && !__vforked &&
(IsOpenbsd() || (IsLinux() && getpid() == gettid()))) {

View file

@ -343,12 +343,17 @@ int sys_unveil_linux(const char *path, const char *permissions) {
* @threadsafe
*/
int unveil(const char *path, const char *permissions) {
int rc;
int e, rc;
e = errno;
if (IsLinux()) {
rc = sys_unveil_linux(path, permissions);
} else {
rc = sys_unveil(path, permissions);
}
if (rc == -1 && errno == ENOSYS) {
errno = e;
rc = 0;
}
STRACE("unveil(%#s, %#s) → %d% m", path, permissions, rc);
return rc;
}

View file

@ -38,10 +38,11 @@
* @raise EINVAL if template didn't end with XXXXXX
*/
char *mkdtemp(char *template) {
int i, j, n, x;
unsigned x;
int i, j, n;
if ((n = strlen(template)) >= 6 && !memcmp(template + n - 6, "XXXXXX", 6)) {
x = rand64();
for (i = 0; i < 10; ++i) {
x = rand64();
for (j = 0; j < 6; ++j) {
template[n - 6 + j] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % 36];
x /= 36;

View file

@ -16,31 +16,60 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.internal.h"
#include "libc/errno.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/stdio/temp.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
/**
* Creates a temporary file.
* Opens stream backed by anonymous file.
*
* We use $TMPDIR or /tmp to create a temporary file securely, which
* will be unlink()'d before this function returns. The file content
* will be released from disk once fclose() is called.
*
* @see mkostempsm(), kTmpPath
* @asyncsignalsafe
* @threadsafe
* @vforksafe
*/
FILE *tmpfile(void) {
int fd;
char *tmp, *sep, tpl[PATH_MAX];
tmp = firstnonnull(getenv("TMPDIR"), kTmpPath);
sep = !isempty(tmp) && !endswith(tmp, "/") ? "/" : "";
if ((snprintf)(tpl, PATH_MAX, "%s%stmp.%s.XXXXXX", tmp, sep,
firstnonnull(program_invocation_short_name, "unknown")) <=
PATH_MAX) {
if ((fd = mkostemps(tpl, 0, 0)) != -1) {
return fdopen(fd, "w+");
FILE *f;
unsigned x;
int fd, i, j, e;
char path[PATH_MAX], *p;
p = path;
p = stpcpy(p, kTmpPath);
p = stpcpy(p, "tmp.");
if (program_invocation_short_name &&
strlen(program_invocation_short_name) < 128) {
p = stpcpy(p, program_invocation_short_name);
*p++ = '.';
}
for (i = 0; i < 10; ++i) {
x = rand64();
for (j = 0; j < 6; ++j) {
p[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % 36];
x /= 36;
}
p[j] = 0;
e = errno;
if ((fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0600)) != -1) {
unlink(path);
if ((f = fdopen(fd, "w+"))) {
return f;
} else {
close(fd);
return 0;
}
} else if (errno == EEXIST) {
errno = e;
} else {
break;
}
}
return NULL;
return 0;
}

View file

@ -98,7 +98,7 @@ TEST(pledge, testLogMessage_inSoftyMode) {
read(fds[0], msg, sizeof(msg));
close(fds[0]);
if (IsLinux()) {
ASSERT_STARTSWITH("error: maybe pledge inet", msg);
ASSERT_STARTSWITH("error: pledge inet for socket", msg);
}
}
@ -116,7 +116,7 @@ TEST(pledge, testLogMessage_onKillProcess) {
read(fds[0], msg, sizeof(msg));
close(fds[0]);
if (IsLinux()) {
ASSERT_STARTSWITH("error: maybe pledge inet", msg);
ASSERT_STARTSWITH("error: pledge inet for socket", msg);
}
}

View file

@ -16,25 +16,15 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/stdio/temp.h"
#include "libc/testlib/testlib.h"
char testlib_enable_tmp_setup_teardown;
TEST(tmpfile, test) {
FILE *f;
mkdir("doge", 0755);
setenv("TMPDIR", "doge", true);
ASSERT_NE(NULL, (f = tmpfile()));
FILE *f = tmpfile();
EXPECT_NE(-1, fputc('t', f));
EXPECT_NE(-1, fflush(f));
rewind(f);
EXPECT_EQ('t', fgetc(f));
EXPECT_NE(-1, fclose(f));
EXPECT_EQ(-1, rmdir("doge"));
EXPECT_EQ(ENOTEMPTY, errno);
}

View file

@ -1 +0,0 @@
2021-03-27

View file

@ -179,7 +179,7 @@ o/$(MODE)/third_party/quickjs/unicode_gen.com.dbg: \
$(THIRD_PARTY_QUICKJS_OBJS): \
OVERRIDE_CPPFLAGS += \
-DCONFIG_BIGNUM \
-DCONFIG_VERSION=\"$(shell cat third_party/quickjs/VERSION)\"
-DCONFIG_VERSION=\"2021-03-27\"
o/tiny/third_party/quickjs/call.o: \
OVERRIDE_CFLAGS += \