diff options
Diffstat (limited to 'pkg/host/syscalls_linux.go')
| -rw-r--r-- | pkg/host/syscalls_linux.go | 173 |
1 files changed, 104 insertions, 69 deletions
diff --git a/pkg/host/syscalls_linux.go b/pkg/host/syscalls_linux.go index f0230bb6a..f1c8f03c8 100644 --- a/pkg/host/syscalls_linux.go +++ b/pkg/host/syscalls_linux.go @@ -167,77 +167,112 @@ var ( lsmDisabled map[string]bool ) -// The function is lengthy as it handles all pseudo-syscalls, -// but it does not seem to cause comprehension problems as there is no shared state. -// Splitting this per-syscall will only increase code size. -func isSupportedSyzkall(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { - switch c.CallName { - case "syz_open_dev": - return isSupportedSyzOpenDev(sandbox, c) - case "syz_open_procfs": - return true, "" - case "syz_open_pts": - return true, "" - case "syz_emit_ethernet", "syz_extract_tcp_res": - reason := checkNetInjection() - return reason == "", reason - case "syz_emit_vhci": - reason := checkVhciInjection() - return reason == "", reason - case "syz_usb_connect", "syz_usb_connect_ath9k", "syz_usb_disconnect", - "syz_usb_control_io", "syz_usb_ep_write", "syz_usb_ep_read": - reason := checkUSBEmulation() - return reason == "", reason - case "syz_kvm_setup_cpu": - switch c.Name { - case "syz_kvm_setup_cpu$x86": - if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" { - return true, "" - } - case "syz_kvm_setup_cpu$arm64": - if runtime.GOARCH == "arm64" { - return true, "" - } - } - return false, "unsupported arch" - 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 ok, reason := onlySandboxNone(sandbox); !ok { - return false, reason - } - return isSupportedSocket(c) - case "syz_genetlink_get_family_id": - fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_GENERIC) - if fd == -1 { - return false, fmt.Sprintf("socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC) failed: %v", err) - } - syscall.Close(fd) - return true, "" - case "syz_mount_image": - if ok, reason := onlySandboxNone(sandbox); !ok { - return ok, reason - } - fstype, ok := extractStringConst(c.Args[0].Type) - if !ok { - panic("syz_mount_image arg is not string") +func isSyzUsbSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + reason := checkUSBEmulation() + return reason == "", reason +} + +func alwaysSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + return true, "" +} + +func isNetInjectionSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + reason := checkNetInjection() + return reason == "", reason +} + +func isVhciInjectionSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + reason := checkVhciInjection() + return reason == "", reason +} + +func isSyzKvmSetupCPUSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + switch c.Name { + case "syz_kvm_setup_cpu$x86": + if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" { + return true, "" } - return isSupportedFilesystem(fstype) - case "syz_read_part_table": - return onlySandboxNone(sandbox) - case "syz_execute_func": - return true, "" - case "syz_io_uring_submit", "syz_io_uring_complete", "syz_io_uring_setup", "syz_memcpy_off": - // syz_memcpy_off is only used for io_uring descriptions, thus, enable it - // only if io_uring syscalls are enabled. - ioUringSyscallName := "io_uring_setup" - ioUringSyscall := target.SyscallMap[ioUringSyscallName] - if ioUringSyscall == nil { - return false, fmt.Sprintf("sys_%v is not present in the target", ioUringSyscallName) + case "syz_kvm_setup_cpu$arm64": + if runtime.GOARCH == "arm64" { + return true, "" } - return isSupportedSyscall(ioUringSyscall, target) + } + return false, "unsupported arch" +} + +func isSyzOpenDevSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + return isSupportedSyzOpenDev(sandbox, c) +} + +func isSyzInitNetSocketSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + if ok, reason := onlySandboxNone(sandbox); !ok { + return false, reason + } + return isSupportedSocket(c) +} + +func isSyzGenetlinkGetFamilyIDSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_GENERIC) + if fd == -1 { + return false, fmt.Sprintf("socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC) failed: %v", err) + } + syscall.Close(fd) + return true, "" +} +func isSyzMountImageSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + if ok, reason := onlySandboxNone(sandbox); !ok { + return ok, reason + } + fstype, ok := extractStringConst(c.Args[0].Type) + if !ok { + panic("syz_mount_image arg is not string") + } + return isSupportedFilesystem(fstype) +} + +func isSyzReadPartTableSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + return onlySandboxNone(sandbox) +} + +func isSyzIoUringSupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + ioUringSyscallName := "io_uring_setup" + ioUringSyscall := target.SyscallMap[ioUringSyscallName] + if ioUringSyscall == nil { + return false, fmt.Sprintf("sys_%v is not present in the target", ioUringSyscallName) + } + return isSupportedSyscall(ioUringSyscall, target) +} + +var syzkallSupport = map[string]func(*prog.Syscall, *prog.Target, string) (bool, string){ + "syz_open_dev": isSyzOpenDevSupported, + "syz_open_procfs": alwaysSupported, + "syz_open_pts": alwaysSupported, + "syz_execute_func": alwaysSupported, + "syz_emit_ethernet": isNetInjectionSupported, + "syz_extract_tcp_res": isNetInjectionSupported, + "syz_usb_connect": isSyzUsbSupported, + "syz_usb_connect_ath9k": isSyzUsbSupported, + "syz_usb_disconnect": isSyzUsbSupported, + "syz_usb_control_io": isSyzUsbSupported, + "syz_usb_ep_write": isSyzUsbSupported, + "syz_usb_ep_read": isSyzUsbSupported, + "syz_kvm_setup_cpu": isSyzKvmSetupCPUSupported, + "syz_emit_vhci": isVhciInjectionSupported, + "syz_init_net_socket": isSyzInitNetSocketSupported, + "syz_genetlink_get_family_id": isSyzGenetlinkGetFamilyIDSupported, + "syz_mount_image": isSyzMountImageSupported, + "syz_read_part_table": isSyzReadPartTableSupported, + "syz_io_uring_submit": isSyzIoUringSupported, + "syz_io_uring_complete": isSyzIoUringSupported, + "syz_io_uring_setup": isSyzIoUringSupported, + // syz_memcpy_off is only used for io_uring descriptions, thus, enable it + // only if io_uring syscalls are enabled. + "syz_memcpy_off": isSyzIoUringSupported, +} + +func isSupportedSyzkall(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + if isSupported, ok := syzkallSupport[c.CallName]; ok { + return isSupported(c, target, sandbox) } panic("unknown syzkall: " + c.Name) } |
