diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-09-13 19:16:32 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 16:02:37 +0200 |
| commit | 34bc139642b0caed49b2ba2dcb9ccff10e04c55f (patch) | |
| tree | 4575a76f5c97b3ec7c7dfbfe511917123e8a020b /sys/linux/init.go | |
| parent | b16ba6390d6b2731bf5cfa0ef04aa1299b7306cf (diff) | |
sys: compile all supported targets into the package
Currently we compile in only GOOS/GOARCH target.
Compile in all targets so that they can be selected at runtime.
Diffstat (limited to 'sys/linux/init.go')
| -rw-r--r-- | sys/linux/init.go | 183 |
1 files changed, 136 insertions, 47 deletions
diff --git a/sys/linux/init.go b/sys/linux/init.go index a62cce4ea..8d96ac27a 100644 --- a/sys/linux/init.go +++ b/sys/linux/init.go @@ -9,27 +9,27 @@ import ( "github.com/google/syzkaller/prog" ) -func init() { - lazyInit() +func initArch(syscalls []*prog.Syscall, resources []*prog.ResourceDesc, + structDescs []*prog.KeyedStruct, consts []prog.ConstValue, archName string, ptrSize uint64) { + arch := makeArch(syscalls, resources, structDescs, consts, archName) target := &prog.Target{ - OS: runtime.GOOS, - Arch: runtime.GOARCH, + OS: "linux", + Arch: archName, PtrSize: ptrSize, PageSize: pageSize, DataOffset: dataOffset, Syscalls: syscalls, Resources: resources, - MakeMmap: makeMmap, - AnalyzeMmap: analyzeMmap, - SanitizeCall: sanitizeCall, + MakeMmap: arch.makeMmap, + AnalyzeMmap: arch.analyzeMmap, + SanitizeCall: arch.sanitizeCall, SpecialStructs: map[string]func(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (prog.Arg, []*prog.Call){ - "timespec": generateTimespec, - "timeval": generateTimespec, + "timespec": arch.generateTimespec, + "timeval": arch.generateTimespec, }, StringDictionary: stringDictionary, } prog.RegisterTarget(target) - prog.SetDefaultTarget(runtime.GOOS, runtime.GOARCH) } const ( @@ -39,8 +39,10 @@ const ( ) var ( - mmapSyscall *prog.Syscall - clockGettimeSyscall *prog.Syscall + // This should not be here, but for now we expose this for syz-fuzzer. + KCOV_INIT_TRACE uintptr + KCOV_ENABLE uintptr + KCOV_TRACE_CMP uintptr stringDictionary = []string{"user", "keyring", "trusted", "system", "security", "selinux", "posix_acl_access", "mime_type", "md5sum", "nodev", "self", @@ -49,23 +51,49 @@ var ( "vboxnet0", "vboxnet1", "vmnet0", "vmnet1", "GPL"} ) +type arch struct { + mmapSyscall *prog.Syscall + clockGettimeSyscall *prog.Syscall + + PROT_READ uint64 + PROT_WRITE uint64 + MAP_ANONYMOUS uint64 + MAP_PRIVATE uint64 + MAP_FIXED uint64 + MREMAP_MAYMOVE uint64 + MREMAP_FIXED uint64 + S_IFREG uint64 + S_IFCHR uint64 + S_IFBLK uint64 + S_IFIFO uint64 + S_IFSOCK uint64 + 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 +} + // createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range. -func makeMmap(start, npages uint64) *prog.Call { +func (arch *arch) makeMmap(start, npages uint64) *prog.Call { + meta := arch.mmapSyscall return &prog.Call{ - Meta: mmapSyscall, + Meta: meta, Args: []prog.Arg{ - prog.MakePointerArg(mmapSyscall.Args[0], start, 0, npages, nil), - prog.MakeConstArg(mmapSyscall.Args[1], npages*pageSize), - prog.MakeConstArg(mmapSyscall.Args[2], PROT_READ|PROT_WRITE), - prog.MakeConstArg(mmapSyscall.Args[3], MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED), - prog.MakeResultArg(mmapSyscall.Args[4], nil, invalidFD), - prog.MakeConstArg(mmapSyscall.Args[5], 0), + prog.MakePointerArg(meta.Args[0], start, 0, npages, nil), + prog.MakeConstArg(meta.Args[1], npages*pageSize), + prog.MakeConstArg(meta.Args[2], arch.PROT_READ|arch.PROT_WRITE), + prog.MakeConstArg(meta.Args[3], arch.MAP_ANONYMOUS|arch.MAP_PRIVATE|arch.MAP_FIXED), + prog.MakeResultArg(meta.Args[4], nil, invalidFD), + prog.MakeConstArg(meta.Args[5], 0), }, - Ret: prog.MakeReturnArg(mmapSyscall.Ret), + Ret: prog.MakeReturnArg(meta.Ret), } } -func analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) { +func (arch *arch) analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) { switch c.Meta.Name { case "mmap": // Filter out only very wrong arguments. @@ -75,7 +103,7 @@ func analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) { } flags := c.Args[3].(*prog.ConstArg).Val fd := c.Args[4].(*prog.ResultArg).Val - if flags&MAP_ANONYMOUS == 0 && fd == invalidFD { + if flags&arch.MAP_ANONYMOUS == 0 && fd == invalidFD { return } start = c.Args[0].(*prog.PointerArg).PageIndex @@ -96,16 +124,16 @@ func analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) { } } -func sanitizeCall(c *prog.Call) { +func (arch *arch) sanitizeCall(c *prog.Call) { switch c.Meta.CallName { case "mmap": // Add MAP_FIXED flag, otherwise it produces non-deterministic results. - c.Args[3].(*prog.ConstArg).Val |= MAP_FIXED + c.Args[3].(*prog.ConstArg).Val |= arch.MAP_FIXED case "mremap": // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results. flags := c.Args[3].(*prog.ConstArg) - if flags.Val&MREMAP_MAYMOVE != 0 { - flags.Val |= MREMAP_FIXED + if flags.Val&arch.MREMAP_MAYMOVE != 0 { + flags.Val |= arch.MREMAP_FIXED } case "mknod", "mknodat": pos := 1 @@ -116,37 +144,41 @@ func sanitizeCall(c *prog.Call) { dev := c.Args[pos+1].(*prog.ConstArg) // Char and block devices read/write io ports, kernel memory and do other nasty things. // TODO: not required if executor drops privileges. - switch mode.Val & (S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK) { - case S_IFREG, S_IFIFO, S_IFSOCK: - case S_IFBLK: + switch mode.Val & (arch.S_IFREG | arch.S_IFCHR | arch.S_IFBLK | arch.S_IFIFO | arch.S_IFSOCK) { + case arch.S_IFREG, arch.S_IFIFO, arch.S_IFSOCK: + case arch.S_IFBLK: + // TODO(dvyukov): mknod dev argument is uint32, + // but prog arguments contain not-truncated uint64 values, + // so we can mistakenly assume that this is not loop, when it actually is. + // This is not very harmful, but need to verify other arguments in this function. if dev.Val>>8 == 7 { break // loop } - mode.Val &^= S_IFBLK - mode.Val |= S_IFREG - case S_IFCHR: - mode.Val &^= S_IFCHR - mode.Val |= S_IFREG + mode.Val &^= arch.S_IFBLK + mode.Val |= arch.S_IFREG + case arch.S_IFCHR: + mode.Val &^= arch.S_IFCHR + mode.Val |= arch.S_IFREG } case "syslog": cmd := c.Args[0].(*prog.ConstArg) // These disable console output, but we need it. - if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON { - cmd.Val = SYSLOG_ACTION_SIZE_UNREAD + 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 uint32(cmd.Val) == FIFREEZE { - cmd.Val = FITHAW + 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 == PTRACE_TRACEME { + if req.Val == arch.PTRACE_TRACEME { req.Val = ^uint64(0) } case "exit", "exit_group": @@ -158,7 +190,7 @@ func sanitizeCall(c *prog.Call) { } } -func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (arg prog.Arg, calls []*prog.Call) { +func (arch *arch) generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (arg prog.Arg, calls []*prog.Call) { // We need to generate timespec/timeval that are either // (1) definitely in the past, or // (2) definitely in unreachable fututre, or @@ -195,7 +227,7 @@ func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (ar }) default: // Few ms ahead for absolute. - meta := clockGettimeSyscall + meta := arch.clockGettimeSyscall ptrArgType := meta.Args[1].(*prog.PtrType) argType := ptrArgType.Type.(*prog.StructType) tp := prog.MakeGroupArg(argType, []prog.Arg{ @@ -207,7 +239,7 @@ func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (ar gettime := &prog.Call{ Meta: meta, Args: []prog.Arg{ - prog.MakeConstArg(meta.Args[0], CLOCK_REALTIME), + prog.MakeConstArg(meta.Args[0], arch.CLOCK_REALTIME), tpaddr, }, Ret: prog.MakeReturnArg(meta.Ret), @@ -230,7 +262,8 @@ func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (ar return } -func lazyInit() { +func makeArch(syscalls []*prog.Syscall, resources []*prog.ResourceDesc, + structDescs []*prog.KeyedStruct, consts []prog.ConstValue, archName string) *arch { resourceMap := make(map[string]*prog.ResourceDesc) for _, res := range resources { resourceMap[res.Name] = res @@ -240,8 +273,8 @@ func lazyInit() { for _, desc := range structDescs { keyedStructs[desc.Key] = desc.Desc } - structDescs = nil + arch := &arch{} for _, c := range syscalls { prog.ForeachType(c, func(t0 prog.Type) { switch t := t0.(type) { @@ -264,9 +297,65 @@ func lazyInit() { }) switch c.Name { case "mmap": - mmapSyscall = c + arch.mmapSyscall = c case "clock_gettime": - clockGettimeSyscall = c + arch.clockGettimeSyscall = c + } + } + + for _, c := range consts { + switch c.Name { + case "KCOV_INIT_TRACE": + if archName == runtime.GOARCH { + KCOV_INIT_TRACE = uintptr(c.Value) + } + case "KCOV_ENABLE": + if archName == runtime.GOARCH { + KCOV_ENABLE = uintptr(c.Value) + } + case "KCOV_TRACE_CMP": + if archName == runtime.GOARCH { + KCOV_TRACE_CMP = uintptr(c.Value) + } + case "PROT_READ": + arch.PROT_READ = c.Value + case "PROT_WRITE": + arch.PROT_WRITE = c.Value + case "MAP_ANONYMOUS": + arch.MAP_ANONYMOUS = c.Value + case "MAP_PRIVATE": + arch.MAP_PRIVATE = c.Value + case "MAP_FIXED": + arch.MAP_FIXED = c.Value + case "MREMAP_MAYMOVE": + arch.MREMAP_MAYMOVE = c.Value + case "MREMAP_FIXED": + arch.MREMAP_FIXED = c.Value + case "S_IFREG": + arch.S_IFREG = c.Value + case "S_IFCHR": + arch.S_IFCHR = c.Value + case "S_IFBLK": + arch.S_IFBLK = c.Value + case "S_IFIFO": + arch.S_IFIFO = c.Value + case "S_IFSOCK": + arch.S_IFSOCK = c.Value + case "SYSLOG_ACTION_CONSOLE_OFF": + arch.SYSLOG_ACTION_CONSOLE_OFF = c.Value + case "SYSLOG_ACTION_CONSOLE_ON": + arch.SYSLOG_ACTION_CONSOLE_ON = c.Value + case "SYSLOG_ACTION_SIZE_UNREAD": + arch.SYSLOG_ACTION_SIZE_UNREAD = c.Value + case "FIFREEZE": + arch.FIFREEZE = c.Value + case "FITHAW": + arch.FITHAW = c.Value + case "PTRACE_TRACEME": + arch.PTRACE_TRACEME = c.Value + case "CLOCK_REALTIME": + arch.CLOCK_REALTIME = c.Value } } + return arch } |
