diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/csource/akaros_common.go | 7 | ||||
| -rw-r--r-- | pkg/csource/freebsd_common.go | 7 | ||||
| -rw-r--r-- | pkg/csource/linux_common.go | 52 | ||||
| -rw-r--r-- | pkg/csource/netbsd_common.go | 7 | ||||
| -rw-r--r-- | pkg/host/host_akaros.go | 2 | ||||
| -rw-r--r-- | pkg/host/host_freebsd.go | 2 | ||||
| -rw-r--r-- | pkg/host/host_fuchsia.go | 2 | ||||
| -rw-r--r-- | pkg/host/host_linux.go | 47 | ||||
| -rw-r--r-- | pkg/host/host_linux_test.go | 4 | ||||
| -rw-r--r-- | pkg/host/host_netbsd.go | 2 | ||||
| -rw-r--r-- | pkg/host/host_windows.go | 2 |
11 files changed, 90 insertions, 44 deletions
diff --git a/pkg/csource/akaros_common.go b/pkg/csource/akaros_common.go index 5fc46dc29..c0984ed99 100644 --- a/pkg/csource/akaros_common.go +++ b/pkg/csource/akaros_common.go @@ -109,9 +109,10 @@ const int kRetryStatus = 69; const int kErrorStatus = 68; #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ - defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ - defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) || \ + defined(__NR_syz_init_net_socket) NORETURN PRINTF static void fail(const char* msg, ...) { int e = errno; diff --git a/pkg/csource/freebsd_common.go b/pkg/csource/freebsd_common.go index 8265e7013..1e6597bbc 100644 --- a/pkg/csource/freebsd_common.go +++ b/pkg/csource/freebsd_common.go @@ -100,9 +100,10 @@ const int kRetryStatus = 69; const int kErrorStatus = 68; #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ - defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ - defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) || \ + defined(__NR_syz_init_net_socket) NORETURN PRINTF static void fail(const char* msg, ...) { int e = errno; diff --git a/pkg/csource/linux_common.go b/pkg/csource/linux_common.go index 5b630e4fe..ee92f9fe5 100644 --- a/pkg/csource/linux_common.go +++ b/pkg/csource/linux_common.go @@ -113,11 +113,19 @@ var commonHeaderLinux = ` #include <sys/ioctl.h> #include <sys/stat.h> #endif +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_init_net_socket) +#include <fcntl.h> +#include <sched.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#endif #if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ defined(SYZ_USE_TMP_DIR) || defined(SYZ_HANDLE_SEGV) || defined(SYZ_TUN_ENABLE) || \ defined(SYZ_SANDBOX_NAMESPACE) || defined(SYZ_SANDBOX_SETUID) || \ - defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || defined(__NR_syz_kvm_setup_cpu) + defined(SYZ_SANDBOX_NONE) || defined(SYZ_FAULT_INJECTION) || \ + defined(__NR_syz_kvm_setup_cpu) || defined(__NR_syz_init_net_socket) __attribute__((noreturn)) static void doexit(int status) { volatile unsigned i; @@ -193,9 +201,10 @@ const int kRetryStatus = 69; const int kErrorStatus = 68; #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ - defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ - defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) || \ + defined(__NR_syz_init_net_socket) NORETURN PRINTF static void fail(const char* msg, ...) { int e = errno; @@ -797,6 +806,32 @@ static uintptr_t syz_fuseblk_mount(uintptr_t a0, uintptr_t a1, uintptr_t a2, uin } #endif +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_init_net_socket) +#if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(SYZ_SANDBOX_NAMESPACE) +const int kInitNetNsFd = 253; +static uintptr_t syz_init_net_socket(uintptr_t domain, uintptr_t type, uintptr_t proto) +{ + int netns = open("/proc/self/ns/net", O_RDONLY); + if (netns == -1) + return netns; + if (setns(kInitNetNsFd, 0)) + return -1; + int sock = syscall(__NR_socket, domain, type, proto); + int err = errno; + if (setns(netns, 0)) + fail("setns(netns) failed"); + close(netns); + errno = err; + return sock; +} +#else +static uintptr_t syz_init_net_socket(uintptr_t domain, uintptr_t type, uintptr_t proto) +{ + return syscall(__NR_socket, domain, type, proto); +} +#endif +#endif + #if defined(SYZ_EXECUTOR) || defined(__NR_syz_kvm_setup_cpu) #if defined(__x86_64__) @@ -1771,6 +1806,15 @@ static void sandbox_common() setpgrp(); setsid(); +#if defined(SYZ_EXECUTOR) || defined(__NR_syz_init_net_socket) + int netns = open("/proc/self/ns/net", O_RDONLY); + if (netns == -1) + fail("open(/proc/self/ns/net) failed"); + if (dup2(netns, kInitNetNsFd) < 0) + fail("dup2(netns, kInitNetNsFd) failed"); + close(netns); +#endif + struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = 128 << 20; setrlimit(RLIMIT_AS, &rlim); diff --git a/pkg/csource/netbsd_common.go b/pkg/csource/netbsd_common.go index 9d3885d46..3714f29da 100644 --- a/pkg/csource/netbsd_common.go +++ b/pkg/csource/netbsd_common.go @@ -100,9 +100,10 @@ const int kRetryStatus = 69; const int kErrorStatus = 68; #endif -#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ - defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ - defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) +#if defined(SYZ_EXECUTOR) || (defined(SYZ_REPEAT) && defined(SYZ_WAIT_REPEAT)) || \ + defined(SYZ_USE_TMP_DIR) || defined(SYZ_TUN_ENABLE) || defined(SYZ_SANDBOX_NAMESPACE) || \ + defined(SYZ_SANDBOX_NONE) || defined(SYZ_SANDBOX_SETUID) || defined(__NR_syz_kvm_setup_cpu) || \ + defined(__NR_syz_init_net_socket) NORETURN PRINTF static void fail(const char* msg, ...) { int e = errno; diff --git a/pkg/host/host_akaros.go b/pkg/host/host_akaros.go index 6c3fbb6d3..91ee49a7d 100644 --- a/pkg/host/host_akaros.go +++ b/pkg/host/host_akaros.go @@ -10,7 +10,7 @@ import ( ) // DetectSupportedSyscalls returns list on supported syscalls on host. -func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error) { +func DetectSupportedSyscalls(target *prog.Target, sandbox string) (map[*prog.Syscall]bool, error) { supported := make(map[*prog.Syscall]bool) for _, c := range target.Syscalls { supported[c] = true diff --git a/pkg/host/host_freebsd.go b/pkg/host/host_freebsd.go index d2745e376..39e8655c4 100644 --- a/pkg/host/host_freebsd.go +++ b/pkg/host/host_freebsd.go @@ -8,7 +8,7 @@ import ( ) // DetectSupportedSyscalls returns list on supported syscalls on host. -func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error) { +func DetectSupportedSyscalls(target *prog.Target, sandbox string) (map[*prog.Syscall]bool, error) { supported := make(map[*prog.Syscall]bool) for _, c := range target.Syscalls { supported[c] = true diff --git a/pkg/host/host_fuchsia.go b/pkg/host/host_fuchsia.go index 37cf8b847..b145961df 100644 --- a/pkg/host/host_fuchsia.go +++ b/pkg/host/host_fuchsia.go @@ -10,7 +10,7 @@ import ( ) // DetectSupportedSyscalls returns list on supported syscalls on host. -func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error) { +func DetectSupportedSyscalls(target *prog.Target, sandbox string) (map[*prog.Syscall]bool, error) { supported := make(map[*prog.Syscall]bool) for _, c := range target.Syscalls { supported[c] = true diff --git a/pkg/host/host_linux.go b/pkg/host/host_linux.go index fd3dc5bb8..57ce3e79e 100644 --- a/pkg/host/host_linux.go +++ b/pkg/host/host_linux.go @@ -17,7 +17,7 @@ import ( ) // DetectSupportedSyscalls returns list on supported syscalls on host. -func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error) { +func DetectSupportedSyscalls(target *prog.Target, sandbox string) (map[*prog.Syscall]bool, error) { // There are 3 possible strategies: // 1. Executes all syscalls with presumably invalid arguments and check for ENOprog. // But not all syscalls are safe to execute. For example, pause will hang, @@ -31,23 +31,20 @@ func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error kallsyms, _ := ioutil.ReadFile("/proc/kallsyms") supported := make(map[*prog.Syscall]bool) for _, c := range target.Syscalls { - if isSupported(kallsyms, c) { + if isSupported(sandbox, kallsyms, c) { supported[c] = true } } return supported, nil } -func isSupported(kallsyms []byte, c *prog.Syscall) bool { +func isSupported(sandbox string, kallsyms []byte, c *prog.Syscall) bool { if strings.HasPrefix(c.CallName, "syz_") { - return isSupportedSyzkall(c) + return isSupportedSyzkall(sandbox, c) } if strings.HasPrefix(c.Name, "socket$") { return isSupportedSocket(c) } - if strings.HasPrefix(c.Name, "open$") { - return isSupportedOpen(c) - } if strings.HasPrefix(c.Name, "openat$") { return isSupportedOpenAt(c) } @@ -69,7 +66,7 @@ var kallsymsMap = map[string]string{ "umount2": "umount", } -func isSupportedSyzkall(c *prog.Syscall) bool { +func isSupportedSyzkall(sandbox string, c *prog.Syscall) bool { switch c.CallName { case "syz_open_dev": if _, ok := c.Args[0].(*prog.ConstType); ok { @@ -81,7 +78,7 @@ func isSupportedSyzkall(c *prog.Syscall) bool { if !ok { panic("first open arg is not a pointer to string const") } - if syscall.Getuid() != 0 { + if syscall.Getuid() != 0 || sandbox == "setuid" { return false } var check func(dev string) bool @@ -102,15 +99,21 @@ func isSupportedSyzkall(c *prog.Syscall) bool { case "syz_open_pts": return true case "syz_fuse_mount": + if syscall.Getuid() != 0 || sandbox == "setuid" { + return false + } return osutil.IsExist("/dev/fuse") case "syz_fuseblk_mount": - return osutil.IsExist("/dev/fuse") && syscall.Getuid() == 0 + if syscall.Getuid() != 0 || sandbox == "setuid" { + return false + } + return osutil.IsExist("/dev/fuse") case "syz_emit_ethernet", "syz_extract_tcp_res": fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0) if err == nil { syscall.Close(fd) } - return err == nil && syscall.Getuid() == 0 + return err == nil case "syz_kvm_setup_cpu": switch c.Name { case "syz_kvm_setup_cpu$x86": @@ -118,6 +121,15 @@ func isSupportedSyzkall(c *prog.Syscall) bool { case "syz_kvm_setup_cpu$arm64": return runtime.GOARCH == "arm64" } + case "syz_init_net_socket": + // Unfortunately this only works with sandbox none at the moment. + // The problem is that setns of a network namespace requires CAP_SYS_ADMIN + // in the target namespace, and we've lost all privs in the init namespace + // during creation of a user namespace. + if syscall.Getuid() != 0 || sandbox != "none" { + return false + } + return isSupportedSocket(c) } panic("unknown syzkall: " + c.Name) } @@ -125,7 +137,6 @@ func isSupportedSyzkall(c *prog.Syscall) bool { func isSupportedSocket(c *prog.Syscall) bool { af, ok := c.Args[0].(*prog.ConstType) if !ok { - println(c.Name) panic("socket family is not const") } fd, err := syscall.Socket(int(af.Val), 0, 0) @@ -135,18 +146,6 @@ func isSupportedSocket(c *prog.Syscall) bool { return err != syscall.ENOSYS && err != syscall.EAFNOSUPPORT } -func isSupportedOpen(c *prog.Syscall) bool { - fname, ok := extractStringConst(c.Args[0]) - if !ok { - return true - } - fd, err := syscall.Open(fname, syscall.O_RDONLY, 0) - if fd != -1 { - syscall.Close(fd) - } - return err == nil -} - func isSupportedOpenAt(c *prog.Syscall) bool { fname, ok := extractStringConst(c.Args[1]) if !ok { diff --git a/pkg/host/host_linux_test.go b/pkg/host/host_linux_test.go index e32fe09cc..9deda69bc 100644 --- a/pkg/host/host_linux_test.go +++ b/pkg/host/host_linux_test.go @@ -21,7 +21,7 @@ func TestLog(t *testing.T) { t.Fatal(err) } // Dump for manual inspection. - supp, err := DetectSupportedSyscalls(target) + supp, err := DetectSupportedSyscalls(target, "none") if err != nil { t.Skipf("skipping: %v", err) } @@ -54,7 +54,7 @@ func TestSupportedSyscalls(t *testing.T) { if err != nil { t.Fatal(err) } - supp, err := DetectSupportedSyscalls(target) + supp, err := DetectSupportedSyscalls(target, "none") if err != nil { t.Skipf("skipping: %v", err) } diff --git a/pkg/host/host_netbsd.go b/pkg/host/host_netbsd.go index d2745e376..39e8655c4 100644 --- a/pkg/host/host_netbsd.go +++ b/pkg/host/host_netbsd.go @@ -8,7 +8,7 @@ import ( ) // DetectSupportedSyscalls returns list on supported syscalls on host. -func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error) { +func DetectSupportedSyscalls(target *prog.Target, sandbox string) (map[*prog.Syscall]bool, error) { supported := make(map[*prog.Syscall]bool) for _, c := range target.Syscalls { supported[c] = true diff --git a/pkg/host/host_windows.go b/pkg/host/host_windows.go index d2745e376..39e8655c4 100644 --- a/pkg/host/host_windows.go +++ b/pkg/host/host_windows.go @@ -8,7 +8,7 @@ import ( ) // DetectSupportedSyscalls returns list on supported syscalls on host. -func DetectSupportedSyscalls(target *prog.Target) (map[*prog.Syscall]bool, error) { +func DetectSupportedSyscalls(target *prog.Target, sandbox string) (map[*prog.Syscall]bool, error) { supported := make(map[*prog.Syscall]bool) for _, c := range target.Syscalls { supported[c] = true |
