Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whitelist syscalls #87

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <stdlib.h>
#include <string.h>
*/
import "C"

Check failure on line 27 in main.go

View check run for this annotation

Cirrus CI / Go Lint New

main.go#L27

could not import C (cgo preprocessing failed) (typecheck)

Check failure on line 27 in main.go

View check run for this annotation

Cirrus CI / Go Lint

main.go#L27

could not import C (cgo preprocessing failed) (typecheck)

Check failure on line 27 in main.go

View check run for this annotation

Cirrus CI / Go Lint Mandatory

main.go#L27

could not import C (cgo preprocessing failed) (typecheck)

import (
"bytes"
Expand Down Expand Up @@ -54,6 +54,7 @@
"github.com/u-root/u-root/pkg/strace"
"golang.org/x/sys/unix"
"gopkg.in/hlandau/easyconfig.v1"
libseccomp "github.com/seccomp/libseccomp-golang"

Check failure on line 57 in main.go

View check run for this annotation

Cirrus CI / Go Lint New

main.go#L57

could not import github.com/seccomp/libseccomp-golang (-: # github.com/seccomp/libseccomp-golang # [pkg-config --cflags -- libseccomp] Package libseccomp was not found in the pkg-config search path. Perhaps you should add the directory containing `libseccomp.pc' to the PKG_CONFIG_PATH environment variable Package 'libseccomp', required by 'virtual:world', not found) (typecheck)

Check failure on line 57 in main.go

View check run for this annotation

Cirrus CI / Go Lint

main.go#L57

could not import github.com/seccomp/libseccomp-golang (-: # github.com/seccomp/libseccomp-golang # [pkg-config --cflags -- libseccomp] Package libseccomp was not found in the pkg-config search path. Perhaps you should add the directory containing `libseccomp.pc' to the PKG_CONFIG_PATH environment variable Package 'libseccomp', required by 'virtual:world', not found) (typecheck)

Check failure on line 57 in main.go

View check run for this annotation

Cirrus CI / Go Lint Mandatory

main.go#L57

could not import github.com/seccomp/libseccomp-golang (-: # github.com/seccomp/libseccomp-golang # [pkg-config --cflags -- libseccomp] Package libseccomp was not found in the pkg-config search path. Perhaps you should add the directory containing `libseccomp.pc' to the PKG_CONFIG_PATH environment variable Package 'libseccomp', required by 'virtual:world', not found) (typecheck)
)

var (
Expand Down Expand Up @@ -137,6 +138,11 @@
cfg.Proxypass = password
}

err := applySyscallWhitelist()
if err != nil {
panic(err)
}

// Start the program with tracing and handle the CONNECT system call events.
if err := strace.Trace(program, func(t strace.Task, record *strace.TraceRecord) error {
if record.Event == strace.SyscallEnter && record.Syscall.Sysno == unix.SYS_CONNECT {
Expand Down Expand Up @@ -607,3 +613,95 @@
}{username, password})
}
}

func applySyscallWhitelist() error {
syscalls := []string{
"read", "write", "open", "close", "stat", "fstat", "lstat", "poll", "lseek", "mmap",
"mprotect", "munmap", "brk", "rt_sigaction", "rt_sigprocmask", "rt_sigreturn", "ioctl",
"pread64", "pwrite64", "readv", "writev", "access", "pipe", "select", "sched_yield",
"mremap", "msync", "mincore", "madvise", "shmget", "shmat", "shmctl", "dup", "dup2", "pause",
"nanosleep", "getitimer", "alarm", "setitimer", "getpid", "sendfile", "socket", //"connect",
"accept", "sendto", "recvfrom", "sendmsg", "recvmsg", "shutdown", "bind", "listen",
"getsockname", "getpeername", "socketpair", "setsockopt", "getsockopt", "clone", "fork",
"vfork", "execve", "exit", "wait4", "kill", "uname", "semget", "semop", "semctl", "shmdt",
"msgget", "msgsnd", "msgrcv", "msgctl", "fcntl", "flock", "fsync", "fdatasync", "truncate",
"ftruncate", "getdents", "getcwd", "chdir", "fchdir", "rename", "mkdir", "rmdir", "creat",
"link", "unlink", "symlink", "readlink", "chmod", "fchmod", "chown", "fchown", "lchown",
"umask", "gettimeofday", "getrlimit", "getrusage", "sysinfo", "times", "ptrace", "getuid",
"syslog", "getgid", "setuid", "setgid", "geteuid", "getegid", "setpgid", "getppid", "getpgrp",
"setsid", "setreuid", "setregid", "getgroups", "setgroups", "setresuid", "getresuid",
"setresgid", "getresgid", "getpgid", "setfsuid", "setfsgid", "getsid", "capget", "capset",
"rt_sigpending", "rt_sigtimedwait", "rt_sigqueueinfo", "rt_sigsuspend", "sigaltstack",
"utime", "mknod", "uselib", "personality", "ustat", "statfs", "fstatfs", "sysfs", "getpriority",
"setpriority", "sched_setparam", "sched_getparam", "sched_setscheduler", "sched_getscheduler",
"sched_get_priority_max", "sched_get_priority_min", "sched_rr_get_interval", "mlock", "munlock",
"mlockall", "munlockall", "vhangup", "modify_ldt", "pivot_root", "_sysctl", "prctl", "arch_prctl",
"adjtimex", "setrlimit", "chroot", "sync", "acct", "settimeofday", "mount", "umount2", "swapon",
"swapoff", "reboot", "sethostname", "setdomainname", "iopl", "ioperm", "create_module", "init_module",
"delete_module", "get_kernel_syms", "query_module", "quotactl", "nfsservctl", "getpmsg",
"putpmsg", "afs_syscall", "tuxcall", "security", "gettid", "readahead", "setxattr", "lsetxattr",
"fsetxattr", "getxattr", "lgetxattr", "fgetxattr", "listxattr", "llistxattr", "flistxattr",
"removexattr", "lremovexattr", "fremovexattr", "tkill", "time", "futex", "sched_setaffinity",
"sched_getaffinity", "set_thread_area", "io_setup", "io_destroy", "io_getevents", "io_submit",
"io_cancel", "get_thread_area", "lookup_dcookie", "epoll_create", "epoll_ctl_old", "epoll_wait_old",
"remap_file_pages", "getdents64", "set_tid_address", "restart_syscall", "semtimedop", "fadvise64",
"timer_create", "timer_settime", "timer_gettime", "timer_getoverrun", "timer_delete",
"clock_settime", "clock_gettime", "clock_getres", "clock_nanosleep", "exit_group", "epoll_wait",
"epoll_ctl", "tgkill", "utimes", "vserver", "mbind", "set_mempolicy", "get_mempolicy", "mq_open",
"mq_unlink", "mq_timedsend", "mq_timedreceive", "mq_notify", "mq_getsetattr", "kexec_load",
"waitid", "add_key", "request_key", "keyctl", "ioprio_set", "ioprio_get", "inotify_init",
"inotify_add_watch", "inotify_rm_watch", "migrate_pages", "openat", "mkdirat", "mknodat",
"fchownat", "futimesat", "newfstatat", "unlinkat", "renameat", "linkat", "symlinkat", "readlinkat",
"fchmodat", "faccessat", "pselect6", "ppoll", "unshare", "set_robust_list", "get_robust_list",
"splice", "tee", "sync_file_range", "vmsplice", "move_pages", "utimensat", "epoll_pwait",
"signalfd", "timerfd_create", "eventfd", "fallocate", "timerfd_settime", "timerfd_gettime",
"accept4", "signalfd4", "eventfd2", "epoll_create1", "dup3", "pipe2", "inotify_init1", "preadv",
"pwritev", "rt_tgsigqueueinfo", "perf_event_open", "recvmmsg", "fanotify_init", "fanotify_mark",
"prlimit64", "name_to_handle_at", "open_by_handle_at", "clock_adjtime", "syncfs", "sendmmsg",
"setns", "getcpu", "process_vm_readv", "process_vm_writev", "kcmp", "finit_module", "sched_setattr",
"sched_getattr", "renameat2", "seccomp", "getrandom", "memfd_create", "kexec_file_load", "bpf",
"execveat", "userfaultfd", "membarrier", "mlock2", "copy_file_range", "preadv2", "pwritev2",
"pkey_mprotect", "pkey_alloc", "pkey_free", "statx", "io_pgetevents", "rseq", "pidfd_send_signal",
"io_uring_setup", "io_uring_enter", "io_uring_register", "open_tree", "move_mount", "fsopen",
"fsconfig", "fsmount", "fspick", "pidfd_open", "clone3", "close_range", "openat2", "pidfd_getfd",
"faccessat2", "process_madvise", "epoll_pwait2", "mount_setattr", "quotactl_fd", "landlock_create_ruleset",
"landlock_add_rule", "landlock_restrict_self", "memfd_secret", "process_mrelease", "futex_waitv",
"set_mempolicy_home_node", "cachestat", "fchmodat2", "map_shadow_stack", "futex_wake",
"futex_wait", "futex_requeue",
}

filter, err := libseccomp.NewFilter(libseccomp.ActErrno.SetReturnCode(int16(syscall.EPERM)))
if err != nil {
return fmt.Errorf("error creating seccomp filter: %w", err)
}

// Add the rules for each syscall
for _, syscallName := range syscalls {
syscallID, err := libseccomp.GetSyscallFromName(syscallName)
if err != nil {
return fmt.Errorf("error retrieving syscall ID for %s: %w", syscallName, err)
}
err = filter.AddRule(syscallID, libseccomp.ActAllow)
if err != nil {
return fmt.Errorf("error adding allow rule for %s: %w", syscallName, err)
}
}

// Add trace rule for the connect syscall
connectSyscall, err := libseccomp.GetSyscallFromName("connect")
if err != nil {
return fmt.Errorf("error retrieving syscall ID for connect: %w", err)
}
err = filter.AddRule(connectSyscall, libseccomp.ActTrace)
if err != nil {
return fmt.Errorf("error adding trace rule for connect: %w", err)
}

// Load the filter
err = filter.Load()
if err != nil {
return fmt.Errorf("error loading seccomp filter: %w", err)
}

return nil
}