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: .UNSANDBOXED = 1
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
@$(RM) $@ @$(RM) $@
@$(COMPILE) -ATAGS -T$@ $(TAGS) $(TAGSFLAGS) -L $< -o $@ @$(TAGS) $(TAGSFLAGS) -L $< -o $@
HTAGS: .UNSANDBOXED = 1 HTAGS: .UNSANDBOXED = 1
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS) HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
@$(RM) $@ @$(RM) $@
@$(COMPILE) -ATAGS -T$@ build/htags -L $< -o $@ @build/htags -L $< -o $@
loc: .UNSANDBOXED = 1 loc: .UNSANDBOXED = 1
loc: o/$(MODE)/tool/build/summy.com 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 \ o/$(MODE)/examples/pylife/pylife.o \
$(CRT) \ $(CRT) \
$(APE_NO_MODIFY_SELF) $(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 # # 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 # # 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 _timespec_tomicros(struct timespec x) {
int64_t us; 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; return us;
} else { } else {
return INT64_MAX; return INT64_MAX;

View file

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

View file

@ -47,8 +47,9 @@
#define Eperm 1 #define Eperm 1
#define Sigabrt 6 #define Sigabrt 6
#define Enosys 38 #define Einval 22
#define Sigsys 31 #define Sigsys 31
#define Enosys 38
#define Sig_Setmask 2 #define Sig_Setmask 2
#define Sa_Siginfo 4 #define Sa_Siginfo 4
#define Sa_Restorer 0x04000000 #define Sa_Restorer 0x04000000
@ -84,6 +85,356 @@ struct Filter {
struct sock_filter p[700]; 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[] = { static const uint16_t kPledgeDefault[] = {
__NR_linux_exit, // thread return / exit() __NR_linux_exit, // thread return / exit()
}; };
@ -584,6 +935,16 @@ static privileged void KillThisThread(void) {
: "rcx", "r11", "memory"); : "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) { static privileged int HasSyscall(struct Pledges *p, uint16_t n) {
int i; int i;
for (i = 0; i < p->len; ++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); FixCpy(ord, si->si_syscall, 12);
HexCpy(rip, ctx->uc_mcontext.rip); HexCpy(rip, ctx->uc_mcontext.rip);
for (found = i = 0; i < ARRAYLEN(kPledge); ++i) { for (found = i = 0; i < ARRAYLEN(kPledge); ++i) {
switch (HasSyscall(kPledge + i, si->si_syscall)) { if (HasSyscall(kPledge + i, si->si_syscall)) {
case 1: Log("error: pledge ", kPledge[i].name, " for ",
Log("error: should pledge ", kPledge[i].name, // GetSyscallName(si->si_syscall), " (ord=", ord, " rip=", rip, ")\n",
" (ord=", ord, " rip=", rip, ")\n", 0); 0);
found = true; 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) { 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) { switch (mode) {
case kPledgeModeKillProcess: case kPledgeModeKillProcess:
@ -1554,8 +1908,8 @@ static privileged void AppendPledge(struct Filter *f, //
privileged int sys_pledge_linux(unsigned long ipromises, // privileged int sys_pledge_linux(unsigned long ipromises, //
enum PledgeMode mode, // enum PledgeMode mode, //
bool want_msyscall) { // bool want_msyscall) { //
int i, rc = -1;
struct Filter f; struct Filter f;
int i, e, rc = -1;
struct sock_filter sf[1] = {BPF_STMT(BPF_RET | BPF_K, 0)}; struct sock_filter sf[1] = {BPF_STMT(BPF_RET | BPF_K, 0)};
CheckLargeStackAllocation(&f, sizeof(f)); CheckLargeStackAllocation(&f, sizeof(f));
f.n = 0; f.n = 0;
@ -1610,10 +1964,24 @@ privileged int sys_pledge_linux(unsigned long ipromises, //
AppendFilter(&f, PLEDGE(sf)); 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 // 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};
struct sock_fprog sandbox = {.len = f.n, .filter = f.p}; rc = Prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox, 0, 0);
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; return rc;

View file

@ -28,14 +28,20 @@
#include "libc/sysv/errfuns.h" #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 * Pledging causes most system calls to become unavailable. Your system
* call policy is enforced by the kernel (which means it can propagate * call policy is enforced by the kernel (which means it can propagate
* across execve() if permitted). Root access is not required. Support * 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. * The promises you give pledge() define which system calls are allowed.
* Error messages are logged when sandbox violations occur that well you * Error messages are logged when sandbox violations occur that well you
@ -213,14 +219,13 @@
* be weakened to have execute permissions too. * be weakened to have execute permissions too.
* *
* @return 0 on success, or -1 w/ errno * @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 `execpromises` on Linux isn't a subset of `promises`
* @raise EINVAL if `promises` allows exec and `execpromises` is null * @raise EINVAL if `promises` allows exec and `execpromises` is null
* @threadsafe * @threadsafe
* @vforksafe * @vforksafe
*/ */
int pledge(const char *promises, const char *execpromises) { int pledge(const char *promises, const char *execpromises) {
int rc; int e, rc;
unsigned long ipromises, iexecpromises; unsigned long ipromises, iexecpromises;
if (!ParsePromises(promises, &ipromises) && if (!ParsePromises(promises, &ipromises) &&
!ParsePromises(execpromises, &iexecpromises)) { !ParsePromises(execpromises, &iexecpromises)) {
@ -239,7 +244,12 @@ int pledge(const char *promises, const char *execpromises) {
if (rc > -4096u) errno = -rc, rc = -1; if (rc > -4096u) errno = -rc, rc = -1;
} }
} else { } else {
e = errno;
rc = sys_pledge(promises, execpromises); rc = sys_pledge(promises, execpromises);
if (rc && errno == ENOSYS) {
errno = e;
rc = 0;
}
} }
if (!rc && !__vforked && if (!rc && !__vforked &&
(IsOpenbsd() || (IsLinux() && getpid() == gettid()))) { (IsOpenbsd() || (IsLinux() && getpid() == gettid()))) {

View file

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

View file

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

View file

@ -16,31 +16,60 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/fmt/fmt.h" #include "libc/errno.h"
#include "libc/macros.internal.h" #include "libc/rand/rand.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/stdio/temp.h" #include "libc/stdio/temp.h"
#include "libc/str/str.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 * @see mkostempsm(), kTmpPath
* @asyncsignalsafe
* @threadsafe
* @vforksafe
*/ */
FILE *tmpfile(void) { FILE *tmpfile(void) {
int fd; FILE *f;
char *tmp, *sep, tpl[PATH_MAX]; unsigned x;
tmp = firstnonnull(getenv("TMPDIR"), kTmpPath); int fd, i, j, e;
sep = !isempty(tmp) && !endswith(tmp, "/") ? "/" : ""; char path[PATH_MAX], *p;
if ((snprintf)(tpl, PATH_MAX, "%s%stmp.%s.XXXXXX", tmp, sep, p = path;
firstnonnull(program_invocation_short_name, "unknown")) <= p = stpcpy(p, kTmpPath);
PATH_MAX) { p = stpcpy(p, "tmp.");
if ((fd = mkostemps(tpl, 0, 0)) != -1) { if (program_invocation_short_name &&
return fdopen(fd, "w+"); 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)); read(fds[0], msg, sizeof(msg));
close(fds[0]); close(fds[0]);
if (IsLinux()) { 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)); read(fds[0], msg, sizeof(msg));
close(fds[0]); close(fds[0]);
if (IsLinux()) { 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. 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/stdio.h"
#include "libc/stdio/temp.h" #include "libc/stdio/temp.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
char testlib_enable_tmp_setup_teardown;
TEST(tmpfile, test) { TEST(tmpfile, test) {
FILE *f; FILE *f = tmpfile();
mkdir("doge", 0755);
setenv("TMPDIR", "doge", true);
ASSERT_NE(NULL, (f = tmpfile()));
EXPECT_NE(-1, fputc('t', f)); EXPECT_NE(-1, fputc('t', f));
EXPECT_NE(-1, fflush(f)); EXPECT_NE(-1, fflush(f));
rewind(f); rewind(f);
EXPECT_EQ('t', fgetc(f)); EXPECT_EQ('t', fgetc(f));
EXPECT_NE(-1, fclose(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): \ $(THIRD_PARTY_QUICKJS_OBJS): \
OVERRIDE_CPPFLAGS += \ OVERRIDE_CPPFLAGS += \
-DCONFIG_BIGNUM \ -DCONFIG_BIGNUM \
-DCONFIG_VERSION=\"$(shell cat third_party/quickjs/VERSION)\" -DCONFIG_VERSION=\"2021-03-27\"
o/tiny/third_party/quickjs/call.o: \ o/tiny/third_party/quickjs/call.o: \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \