1// Copyright 2018 syzkaller project authors. All rights reserved. 2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4package targets 5 6import ( 7 "github.com/google/syzkaller/prog" 8) 9 10// MakePosixMmap creates a "normal" posix mmap call that maps [addr, addr+size) range. 11func MakePosixMmap(target *prog.Target) func(addr, size uint64) *prog.Call { 12 meta := target.SyscallMap["mmap"] 13 prot := target.ConstMap["PROT_READ"] | target.ConstMap["PROT_WRITE"] 14 flags := target.ConstMap["MAP_ANONYMOUS"] | target.ConstMap["MAP_PRIVATE"] | target.ConstMap["MAP_FIXED"] 15 const invalidFD = ^uint64(0) 16 return func(addr, size uint64) *prog.Call { 17 return &prog.Call{ 18 Meta: meta, 19 Args: []prog.Arg{ 20 prog.MakeVmaPointerArg(meta.Args[0], addr, size), 21 prog.MakeConstArg(meta.Args[1], size), 22 prog.MakeConstArg(meta.Args[2], prot), 23 prog.MakeConstArg(meta.Args[3], flags), 24 prog.MakeResultArg(meta.Args[4], nil, invalidFD), 25 prog.MakeConstArg(meta.Args[5], 0), 26 }, 27 Ret: prog.MakeReturnArg(meta.Ret), 28 } 29 } 30} 31 32func MakeSyzMmap(target *prog.Target) func(addr, size uint64) *prog.Call { 33 meta := target.SyscallMap["syz_mmap"] 34 return func(addr, size uint64) *prog.Call { 35 return &prog.Call{ 36 Meta: meta, 37 Args: []prog.Arg{ 38 prog.MakeVmaPointerArg(meta.Args[0], addr, size), 39 prog.MakeConstArg(meta.Args[1], size), 40 }, 41 Ret: prog.MakeReturnArg(meta.Ret), 42 } 43 } 44} 45 46type UnixSanitizer struct { 47 MAP_FIXED uint64 48 MREMAP_MAYMOVE uint64 49 MREMAP_FIXED uint64 50 S_IFREG uint64 51 S_IFCHR uint64 52 S_IFBLK uint64 53 S_IFIFO uint64 54 S_IFSOCK uint64 55} 56 57func MakeUnixSanitizer(target *prog.Target) *UnixSanitizer { 58 return &UnixSanitizer{ 59 MAP_FIXED: target.ConstMap["MAP_FIXED"], 60 MREMAP_MAYMOVE: target.ConstMap["MREMAP_MAYMOVE"], 61 MREMAP_FIXED: target.ConstMap["MREMAP_FIXED"], 62 S_IFREG: target.ConstMap["S_IFREG"], 63 S_IFCHR: target.ConstMap["S_IFCHR"], 64 S_IFBLK: target.ConstMap["S_IFBLK"], 65 S_IFIFO: target.ConstMap["S_IFIFO"], 66 S_IFSOCK: target.ConstMap["S_IFSOCK"], 67 } 68} 69 70func (arch *UnixSanitizer) SanitizeCall(c *prog.Call) { 71 switch c.Meta.CallName { 72 case "mmap": 73 // Add MAP_FIXED flag, otherwise it produces non-deterministic results. 74 c.Args[3].(*prog.ConstArg).Val |= arch.MAP_FIXED 75 case "mremap": 76 // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results. 77 flags := c.Args[3].(*prog.ConstArg) 78 if flags.Val&arch.MREMAP_MAYMOVE != 0 { 79 flags.Val |= arch.MREMAP_FIXED 80 } 81 case "mknod", "mknodat": 82 pos := 1 83 if c.Meta.CallName == "mknodat" { 84 pos = 2 85 } 86 if _, ok := c.Args[pos+1].Type().(*prog.ProcType); ok { 87 return 88 } 89 mode := c.Args[pos].(*prog.ConstArg) 90 dev := c.Args[pos+1].(*prog.ConstArg) 91 dev.Val = uint64(uint32(dev.Val)) 92 // Char and block devices read/write io ports, kernel memory and do other nasty things. 93 // TODO: not required if executor drops privileges. 94 mask := arch.S_IFREG | arch.S_IFCHR | arch.S_IFBLK | arch.S_IFIFO | arch.S_IFSOCK 95 switch mode.Val & mask { 96 case arch.S_IFREG, arch.S_IFIFO, arch.S_IFSOCK: 97 case arch.S_IFBLK: 98 if dev.Val>>8 == 7 { 99 break // loop 100 } 101 mode.Val &^= arch.S_IFBLK 102 mode.Val |= arch.S_IFREG 103 case arch.S_IFCHR: 104 mode.Val &^= arch.S_IFCHR 105 mode.Val |= arch.S_IFREG 106 } 107 case "exit", "exit_group": 108 code := c.Args[0].(*prog.ConstArg) 109 // These codes are reserved by executor. 110 if code.Val%128 == 67 || code.Val%128 == 68 { 111 code.Val = 1 112 } 113 } 114} 115