From ffe7e17368d7ae6c2b40da2ce0703d8ad8a116ac Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 5 Sep 2017 13:31:14 +0200 Subject: prog, sys: move types to prog Large overhaul moves syscalls and arg types from sys to prog. Sys package now depends on prog and contains only generated descriptions of syscalls. Introduce prog.Target type that encapsulates all targer properties, like syscall list, ptr/page size, etc. Also moves OS-dependent pieces like mmap call generation from prog to sys. Update #191 --- prog/analysis.go | 124 ++++--------------------------------------------------- 1 file changed, 7 insertions(+), 117 deletions(-) (limited to 'prog/analysis.go') diff --git a/prog/analysis.go b/prog/analysis.go index 05837131a..009a15a21 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -10,8 +10,6 @@ package prog import ( "fmt" - - . "github.com/google/syzkaller/sys" ) const ( @@ -68,46 +66,18 @@ func (s *state) analyze(c *Call) { } } }) - switch c.Meta.Name { - case "mmap": - // Filter out only very wrong arguments. - length := c.Args[1].(*ConstArg) - if length.Val == 0 { - break + start, npages, mapped := analyzeMmap(c) + if npages != 0 { + if start+npages > uint64(len(s.pages)) { + panic(fmt.Sprintf("address is out of bounds: page=%v len=%v bound=%v", + start, npages, len(s.pages))) } - flags := c.Args[3].(*ConstArg) - fd := c.Args[4].(*ResultArg) - if flags.Val&MAP_ANONYMOUS == 0 && fd.Val == InvalidFD { - break - } - s.addressable(c.Args[0].(*PointerArg), length, true) - case "munmap": - s.addressable(c.Args[0].(*PointerArg), c.Args[1].(*ConstArg), false) - case "mremap": - s.addressable(c.Args[4].(*PointerArg), c.Args[2].(*ConstArg), true) - case "io_submit": - if arr := c.Args[2].(*PointerArg).Res; arr != nil { - for _, ptr := range arr.(*GroupArg).Inner { - p := ptr.(*PointerArg) - if p.Res != nil && p.Res.Type().Name() == "iocb" { - s.resources["iocbptr"] = append(s.resources["iocbptr"], ptr) - } - } + for i := uint64(0); i < npages; i++ { + s.pages[start+i] = mapped } } } -func (s *state) addressable(addr *PointerArg, size *ConstArg, ok bool) { - sizePages := size.Val / pageSize - if addr.PageIndex+sizePages > uint64(len(s.pages)) { - panic(fmt.Sprintf("address is out of bounds: page=%v len=%v bound=%v\naddr: %+v\nsize: %+v", - addr.PageIndex, sizePages, len(s.pages), addr, size)) - } - for i := uint64(0); i < sizePages; i++ { - s.pages[addr.PageIndex+i] = ok - } -} - func foreachSubargImpl(arg Arg, parent *[]Arg, f func(arg, base Arg, parent *[]Arg)) { var rec func(arg, base Arg, parent *[]Arg) rec = func(arg, base Arg, parent *[]Arg) { @@ -181,86 +151,6 @@ func foreachSubargOffset(arg Arg, f func(arg Arg, offset uint64)) { rec(arg, 0) } -func sanitizeCall(c *Call) { - switch c.Meta.CallName { - case "mmap": - // Add MAP_FIXED flag, otherwise it produces non-deterministic results. - _, ok := c.Args[0].(*PointerArg) - if !ok { - panic("mmap address is not ArgPointer") - } - _, ok = c.Args[1].(*ConstArg) - if !ok { - panic("mmap length is not ArgPageSize") - } - flags, ok := c.Args[3].(*ConstArg) - if !ok { - panic("mmap flag arg is not const") - } - flags.Val |= MAP_FIXED - case "mremap": - // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results. - flags, ok := c.Args[3].(*ConstArg) - if !ok { - panic("mremap flag arg is not const") - } - if flags.Val&MREMAP_MAYMOVE != 0 { - flags.Val |= MREMAP_FIXED - } - case "mknod", "mknodat": - mode, ok1 := c.Args[1].(*ConstArg) - dev, ok2 := c.Args[2].(*ConstArg) - if c.Meta.CallName == "mknodat" { - mode, ok1 = c.Args[2].(*ConstArg) - dev, ok2 = c.Args[3].(*ConstArg) - } - if !ok1 || !ok2 { - panic("mknod mode is not const") - } - // 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: - 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 - } - case "syslog": - cmd := c.Args[0].(*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 - } - case "ioctl": - cmd := c.Args[1].(*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 - } - case "ptrace": - req := c.Args[0].(*ConstArg) - // PTRACE_TRACEME leads to unkillable processes, see: - // https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw - if req.Val == PTRACE_TRACEME { - req.Val = ^uint64(0) - } - case "exit", "exit_group": - code := c.Args[0].(*ConstArg) - // These codes are reserved by executor. - if code.Val%128 == 67 || code.Val%128 == 68 { - code.Val = 1 - } - } -} - func RequiresBitmasks(p *Prog) bool { result := false for _, c := range p.Calls { -- cgit mrf-deployment