| // Copyright 2018 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 targets |
| |
| import ( |
| "github.com/google/syzkaller/prog" |
| ) |
| |
| // MakePosixMmap creates a "normal" posix mmap call that maps [addr, addr+size) range. |
| func MakePosixMmap(target *prog.Target) func(addr, size uint64) *prog.Call { |
| meta := target.SyscallMap["mmap"] |
| prot := target.ConstMap["PROT_READ"] | target.ConstMap["PROT_WRITE"] |
| flags := target.ConstMap["MAP_ANONYMOUS"] | target.ConstMap["MAP_PRIVATE"] | target.ConstMap["MAP_FIXED"] |
| const invalidFD = ^uint64(0) |
| return func(addr, size uint64) *prog.Call { |
| return &prog.Call{ |
| Meta: meta, |
| Args: []prog.Arg{ |
| prog.MakeVmaPointerArg(meta.Args[0], addr, size), |
| prog.MakeConstArg(meta.Args[1], size), |
| prog.MakeConstArg(meta.Args[2], prot), |
| prog.MakeConstArg(meta.Args[3], flags), |
| prog.MakeResultArg(meta.Args[4], nil, invalidFD), |
| prog.MakeConstArg(meta.Args[5], 0), |
| }, |
| Ret: prog.MakeReturnArg(meta.Ret), |
| } |
| } |
| } |
| |
| func MakeSyzMmap(target *prog.Target) func(addr, size uint64) *prog.Call { |
| meta := target.SyscallMap["syz_mmap"] |
| return func(addr, size uint64) *prog.Call { |
| return &prog.Call{ |
| Meta: meta, |
| Args: []prog.Arg{ |
| prog.MakeVmaPointerArg(meta.Args[0], addr, size), |
| prog.MakeConstArg(meta.Args[1], size), |
| }, |
| Ret: prog.MakeReturnArg(meta.Ret), |
| } |
| } |
| } |
| |
| type UnixSanitizer struct { |
| MAP_FIXED uint64 |
| MREMAP_MAYMOVE uint64 |
| MREMAP_FIXED uint64 |
| S_IFREG uint64 |
| S_IFCHR uint64 |
| S_IFBLK uint64 |
| S_IFIFO uint64 |
| S_IFSOCK uint64 |
| } |
| |
| func MakeUnixSanitizer(target *prog.Target) *UnixSanitizer { |
| return &UnixSanitizer{ |
| MAP_FIXED: target.ConstMap["MAP_FIXED"], |
| MREMAP_MAYMOVE: target.ConstMap["MREMAP_MAYMOVE"], |
| MREMAP_FIXED: target.ConstMap["MREMAP_FIXED"], |
| S_IFREG: target.ConstMap["S_IFREG"], |
| S_IFCHR: target.ConstMap["S_IFCHR"], |
| S_IFBLK: target.ConstMap["S_IFBLK"], |
| S_IFIFO: target.ConstMap["S_IFIFO"], |
| S_IFSOCK: target.ConstMap["S_IFSOCK"], |
| } |
| } |
| |
| func (arch *UnixSanitizer) 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 |= arch.MAP_FIXED |
| case "mremap": |
| // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results. |
| flags := c.Args[3].(*prog.ConstArg) |
| if flags.Val&arch.MREMAP_MAYMOVE != 0 { |
| flags.Val |= arch.MREMAP_FIXED |
| } |
| case "mknod", "mknodat": |
| pos := 1 |
| if c.Meta.CallName == "mknodat" { |
| pos = 2 |
| } |
| if _, ok := c.Args[pos+1].Type().(*prog.ProcType); ok { |
| return |
| } |
| mode := c.Args[pos].(*prog.ConstArg) |
| dev := c.Args[pos+1].(*prog.ConstArg) |
| dev.Val = uint64(uint32(dev.Val)) |
| // Char and block devices read/write io ports, kernel memory and do other nasty things. |
| // TODO: not required if executor drops privileges. |
| mask := arch.S_IFREG | arch.S_IFCHR | arch.S_IFBLK | arch.S_IFIFO | arch.S_IFSOCK |
| switch mode.Val & mask { |
| case arch.S_IFREG, arch.S_IFIFO, arch.S_IFSOCK: |
| case arch.S_IFBLK: |
| if dev.Val>>8 == 7 { |
| break // loop |
| } |
| 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 "exit", "exit_group": |
| code := c.Args[0].(*prog.ConstArg) |
| // These codes are reserved by executor. |
| if code.Val%128 == 67 || code.Val%128 == 68 { |
| code.Val = 1 |
| } |
| } |
| } |