diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2022-01-12 13:54:32 +0000 |
|---|---|---|
| committer | Aleksandr Nogikh <wp32pw@gmail.com> | 2022-01-13 17:03:14 +0100 |
| commit | f635b41d90ee4c01636d9b7f67091aa2ce2c2f20 (patch) | |
| tree | 51a479e96f86fa7b3cca4aff90f9067da6182b33 | |
| parent | 40c93acdacf984554ac152f1b7f06ba400fde8b0 (diff) | |
all: explicitly list pseudo syscall dependencies
Pseudo syscalls can (and most of the time) do invoke normal system
calls. However, when there's a risk that those calls might not be
present, syzkaller needs to take preventive actions - prepend the
corresponding defines. Otherwise syz-executor or C reproducers might
not compile on the host machine.
List those dependencies in sys/targets, check them during machine check
and add the corresponding defines during C source generation.
| -rw-r--r-- | pkg/csource/csource.go | 7 | ||||
| -rw-r--r-- | pkg/host/syscalls_linux.go | 21 | ||||
| -rw-r--r-- | sys/targets/targets.go | 3 |
3 files changed, 25 insertions, 6 deletions
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go index 6dd8bdcd6..1ba433f45 100644 --- a/pkg/csource/csource.go +++ b/pkg/csource/csource.go @@ -73,6 +73,13 @@ func (ctx *context) generateSource() ([]byte, error) { for _, c := range append(mmapProg.Calls, ctx.p.Calls...) { ctx.calls[c.Meta.CallName] = c.Meta.NR + for _, dep := range ctx.sysTarget.PseudoSyscallDeps[c.Meta.CallName] { + depCall := ctx.target.SyscallMap[dep] + if depCall == nil { + panic(dep + " is specified in PseudoSyscallDeps, but not present") + } + ctx.calls[depCall.CallName] = depCall.NR + } } varsBuf := new(bytes.Buffer) diff --git a/pkg/host/syscalls_linux.go b/pkg/host/syscalls_linux.go index 1d305b4e0..f43f1ada3 100644 --- a/pkg/host/syscalls_linux.go +++ b/pkg/host/syscalls_linux.go @@ -71,6 +71,14 @@ func isSupportedSyscall(c *prog.Syscall, target *prog.Target) (bool, string) { return isSupportedTrial(c) } +func isSupportedSyscallName(name string, target *prog.Target) (bool, string) { + syscall := target.SyscallMap[name] + if syscall == nil { + return false, fmt.Sprintf("sys_%v is not present in the target", name) + } + return isSupportedSyscall(syscall, target) +} + func parseKallsyms(kallsyms []byte, arch string) map[string]bool { set := make(map[string]bool) var re *regexp.Regexp @@ -245,12 +253,7 @@ func isSyzReadPartTableSupported(c *prog.Syscall, target *prog.Target, sandbox s } 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) + return isSupportedSyscallName("io_uring_setup", target) } func isSyzMemcpySupported(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { @@ -316,6 +319,12 @@ var syzkallSupport = map[string]func(*prog.Syscall, *prog.Target, string) (bool, } func isSupportedSyzkall(c *prog.Syscall, target *prog.Target, sandbox string) (bool, string) { + sysTarget := targets.Get(target.OS, target.Arch) + for _, depCall := range sysTarget.PseudoSyscallDeps[c.CallName] { + if ok, reason := isSupportedSyscallName(depCall, target); !ok { + return ok, reason + } + } if isSupported, ok := syzkallSupport[c.CallName]; ok { return isSupported(c, target, sandbox) } diff --git a/sys/targets/targets.go b/sys/targets/targets.go index 65b258ccb..a5946cf16 100644 --- a/sys/targets/targets.go +++ b/sys/targets/targets.go @@ -76,6 +76,9 @@ type osCommon struct { KernelObject string // Name of cpp(1) executable. CPP string + // Syscalls on which pseudo syscalls depend. Syzkaller will make sure that __NR* or SYS* definitions + // for those syscalls are enabled. + PseudoSyscallDeps map[string][]string // Common CFLAGS for this OS. cflags []string } |
