mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-30 23:00:29 +00:00
f914e0a305
Update #538
221 lines
7.4 KiB
Go
221 lines
7.4 KiB
Go
// Copyright 2017 syzkaller project authors. All rights reserved.
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
package linux
|
|
|
|
import (
|
|
"runtime"
|
|
|
|
"github.com/google/syzkaller/prog"
|
|
"github.com/google/syzkaller/sys/linux/gen"
|
|
"github.com/google/syzkaller/sys/targets"
|
|
)
|
|
|
|
func init() {
|
|
prog.RegisterTarget(gen.Target_amd64, initTarget)
|
|
prog.RegisterTarget(gen.Target_386, initTarget)
|
|
prog.RegisterTarget(gen.Target_arm64, initTarget)
|
|
prog.RegisterTarget(gen.Target_arm, initTarget)
|
|
prog.RegisterTarget(gen.Target_ppc64le, initTarget)
|
|
}
|
|
|
|
func initTarget(target *prog.Target) {
|
|
arch := &arch{
|
|
unix: targets.MakeUnixSanitizer(target),
|
|
clockGettimeSyscall: target.SyscallMap["clock_gettime"],
|
|
SYSLOG_ACTION_CONSOLE_OFF: target.ConstMap["SYSLOG_ACTION_CONSOLE_OFF"],
|
|
SYSLOG_ACTION_CONSOLE_ON: target.ConstMap["SYSLOG_ACTION_CONSOLE_ON"],
|
|
SYSLOG_ACTION_SIZE_UNREAD: target.ConstMap["SYSLOG_ACTION_SIZE_UNREAD"],
|
|
FIFREEZE: target.ConstMap["FIFREEZE"],
|
|
FITHAW: target.ConstMap["FITHAW"],
|
|
PTRACE_TRACEME: target.ConstMap["PTRACE_TRACEME"],
|
|
CLOCK_REALTIME: target.ConstMap["CLOCK_REALTIME"],
|
|
ARCH_SET_FS: target.ConstMap["ARCH_SET_FS"],
|
|
ARCH_SET_GS: target.ConstMap["ARCH_SET_GS"],
|
|
AF_NFC: target.ConstMap["AF_NFC"],
|
|
AF_LLC: target.ConstMap["AF_LLC"],
|
|
AF_BLUETOOTH: target.ConstMap["AF_BLUETOOTH"],
|
|
}
|
|
|
|
target.MakeMmap = targets.MakePosixMmap(target)
|
|
target.SanitizeCall = arch.sanitizeCall
|
|
target.SpecialTypes = map[string]func(g *prog.Gen, typ prog.Type, old prog.Arg) (
|
|
prog.Arg, []*prog.Call){
|
|
"timespec": arch.generateTimespec,
|
|
"timeval": arch.generateTimespec,
|
|
"sockaddr_alg": arch.generateSockaddrAlg,
|
|
"alg_name": arch.generateAlgName,
|
|
"alg_aead_name": arch.generateAlgAeadName,
|
|
"alg_hash_name": arch.generateAlgHashName,
|
|
"alg_blkcipher_name": arch.generateAlgBlkcipherhName,
|
|
"ipt_replace": arch.generateIptables,
|
|
"ip6t_replace": arch.generateIptables,
|
|
"arpt_replace": arch.generateArptables,
|
|
"ebt_replace": arch.generateEbtables,
|
|
}
|
|
target.StringDictionary = stringDictionary
|
|
|
|
if target.Arch == runtime.GOARCH {
|
|
KCOV_INIT_TRACE = uintptr(target.ConstMap["KCOV_INIT_TRACE"])
|
|
KCOV_ENABLE = uintptr(target.ConstMap["KCOV_ENABLE"])
|
|
KCOV_DISABLE = uintptr(target.ConstMap["KCOV_DISABLE"])
|
|
KCOV_TRACE_CMP = uintptr(target.ConstMap["KCOV_TRACE_CMP"])
|
|
}
|
|
}
|
|
|
|
var (
|
|
// This should not be here, but for now we expose this for syz-fuzzer.
|
|
KCOV_INIT_TRACE uintptr
|
|
KCOV_ENABLE uintptr
|
|
KCOV_DISABLE uintptr
|
|
KCOV_TRACE_CMP uintptr
|
|
|
|
// TODO(dvyukov): get rid of this, this must be in descriptions.
|
|
stringDictionary = []string{"user", "keyring", "trusted", "system", "security", "selinux",
|
|
"posix_acl_access", "mime_type", "md5sum", "nodev", "self",
|
|
"bdev", "proc", "cgroup", "cpuset",
|
|
"lo", "eth0", "eth1", "em0", "em1", "wlan0", "wlan1", "ppp0", "ppp1",
|
|
"vboxnet0", "vboxnet1", "vmnet0", "vmnet1", "GPL"}
|
|
)
|
|
|
|
type arch struct {
|
|
unix *targets.UnixSanitizer
|
|
|
|
clockGettimeSyscall *prog.Syscall
|
|
|
|
SYSLOG_ACTION_CONSOLE_OFF uint64
|
|
SYSLOG_ACTION_CONSOLE_ON uint64
|
|
SYSLOG_ACTION_SIZE_UNREAD uint64
|
|
FIFREEZE uint64
|
|
FITHAW uint64
|
|
PTRACE_TRACEME uint64
|
|
CLOCK_REALTIME uint64
|
|
ARCH_SET_FS uint64
|
|
ARCH_SET_GS uint64
|
|
AF_NFC uint64
|
|
AF_LLC uint64
|
|
AF_BLUETOOTH uint64
|
|
}
|
|
|
|
func (arch *arch) sanitizeCall(c *prog.Call) {
|
|
arch.unix.SanitizeCall(c)
|
|
switch c.Meta.CallName {
|
|
case "syslog":
|
|
cmd := c.Args[0].(*prog.ConstArg)
|
|
cmd.Val = uint64(uint32(cmd.Val))
|
|
// These disable console output, but we need it.
|
|
if cmd.Val == arch.SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == arch.SYSLOG_ACTION_CONSOLE_ON {
|
|
cmd.Val = arch.SYSLOG_ACTION_SIZE_UNREAD
|
|
}
|
|
case "ioctl":
|
|
cmd := c.Args[1].(*prog.ConstArg)
|
|
// Freeze kills machine. Though, it is an interesting functions,
|
|
// so we need to test it somehow.
|
|
// TODO: not required if executor drops privileges.
|
|
if uint64(uint32(cmd.Val)) == arch.FIFREEZE {
|
|
cmd.Val = arch.FITHAW
|
|
}
|
|
case "ptrace":
|
|
req := c.Args[0].(*prog.ConstArg)
|
|
// PTRACE_TRACEME leads to unkillable processes, see:
|
|
// https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
|
|
if req.Val == arch.PTRACE_TRACEME {
|
|
req.Val = ^uint64(0)
|
|
}
|
|
case "arch_prctl":
|
|
// fs holds address of tls, if a program messes it at least signal
|
|
// handling will break. This also allows a program to do writes
|
|
// at arbitrary addresses, which usually leads to machine outbreak.
|
|
cmd := c.Args[0].(*prog.ConstArg)
|
|
if uint64(uint32(cmd.Val)) == arch.ARCH_SET_FS {
|
|
cmd.Val = arch.ARCH_SET_GS
|
|
}
|
|
case "syz_init_net_socket":
|
|
// Don't let it mess with arbitrary sockets in init namespace.
|
|
family := c.Args[0].(*prog.ConstArg)
|
|
switch uint64(uint32(family.Val)) {
|
|
case arch.AF_NFC, arch.AF_LLC, arch.AF_BLUETOOTH:
|
|
default:
|
|
family.Val = ^uint64(0)
|
|
}
|
|
}
|
|
|
|
switch c.Meta.Name {
|
|
case "setsockopt$EBT_SO_SET_ENTRIES":
|
|
arch.sanitizeEbtables(c)
|
|
}
|
|
}
|
|
|
|
func (arch *arch) generateTimespec(g *prog.Gen, typ0 prog.Type, old prog.Arg) (arg prog.Arg, calls []*prog.Call) {
|
|
typ := typ0.(*prog.StructType)
|
|
// We need to generate timespec/timeval that are either
|
|
// (1) definitely in the past, or
|
|
// (2) definitely in unreachable fututre, or
|
|
// (3) few ms ahead of now.
|
|
// Note: timespec/timeval can be absolute or relative to now.
|
|
// Note: executor has blocking syscall timeout of 20ms,
|
|
// so we generate both 10ms and 30ms.
|
|
usec := typ.Name() == "timeval"
|
|
switch {
|
|
case g.NOutOf(1, 4):
|
|
// Now for relative, past for absolute.
|
|
arg = prog.MakeGroupArg(typ, []prog.Arg{
|
|
prog.MakeResultArg(typ.Fields[0], nil, 0),
|
|
prog.MakeResultArg(typ.Fields[1], nil, 0),
|
|
})
|
|
case g.NOutOf(1, 3):
|
|
// Few ms ahead for relative, past for absolute
|
|
nsec := uint64(10 * 1e6)
|
|
if g.NOutOf(1, 2) {
|
|
nsec = 30 * 1e6
|
|
}
|
|
if usec {
|
|
nsec /= 1e3
|
|
}
|
|
arg = prog.MakeGroupArg(typ, []prog.Arg{
|
|
prog.MakeResultArg(typ.Fields[0], nil, 0),
|
|
prog.MakeResultArg(typ.Fields[1], nil, nsec),
|
|
})
|
|
case g.NOutOf(1, 2):
|
|
// Unreachable fututre for both relative and absolute
|
|
arg = prog.MakeGroupArg(typ, []prog.Arg{
|
|
prog.MakeResultArg(typ.Fields[0], nil, 2e9),
|
|
prog.MakeResultArg(typ.Fields[1], nil, 0),
|
|
})
|
|
default:
|
|
// Few ms ahead for absolute.
|
|
meta := arch.clockGettimeSyscall
|
|
ptrArgType := meta.Args[1].(*prog.PtrType)
|
|
argType := ptrArgType.Type.(*prog.StructType)
|
|
tp := prog.MakeGroupArg(argType, []prog.Arg{
|
|
prog.MakeResultArg(argType.Fields[0], nil, 0),
|
|
prog.MakeResultArg(argType.Fields[1], nil, 0),
|
|
})
|
|
var tpaddr prog.Arg
|
|
tpaddr, calls = g.Alloc(ptrArgType, tp)
|
|
gettime := &prog.Call{
|
|
Meta: meta,
|
|
Args: []prog.Arg{
|
|
prog.MakeConstArg(meta.Args[0], arch.CLOCK_REALTIME),
|
|
tpaddr,
|
|
},
|
|
Ret: prog.MakeReturnArg(meta.Ret),
|
|
}
|
|
calls = append(calls, gettime)
|
|
sec := prog.MakeResultArg(typ.Fields[0], tp.Inner[0].(*prog.ResultArg), 0)
|
|
nsec := prog.MakeResultArg(typ.Fields[1], tp.Inner[1].(*prog.ResultArg), 0)
|
|
msec := uint64(10)
|
|
if g.NOutOf(1, 2) {
|
|
msec = 30
|
|
}
|
|
if usec {
|
|
nsec.OpDiv = 1e3
|
|
nsec.OpAdd = msec * 1e3
|
|
} else {
|
|
nsec.OpAdd = msec * 1e6
|
|
}
|
|
arg = prog.MakeGroupArg(typ, []prog.Arg{sec, nsec})
|
|
}
|
|
return
|
|
}
|