github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/sys/targets/common.go (about) 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 4 package targets 5 6 import ( 7 "github.com/google/syzkaller/prog" 8 ) 9 10 // MakePosixMmap creates a "normal" posix mmap call that maps the target data range. 11 // If exec is set, the mapping is mapped as PROT_EXEC. 12 // If contain is set, the mapping is surrounded by PROT_NONE pages. 13 // These flags should be in sync with what executor. 14 func MakePosixMmap(target *prog.Target, exec, contain bool) func() []*prog.Call { 15 meta := target.SyscallMap["mmap"] 16 protRW := target.GetConst("PROT_READ") | target.GetConst("PROT_WRITE") 17 if exec { 18 protRW |= target.GetConst("PROT_EXEC") 19 } 20 flags := target.GetConst("MAP_ANONYMOUS") | target.GetConst("MAP_PRIVATE") | target.GetConst("MAP_FIXED") 21 size := target.NumPages * target.PageSize 22 const invalidFD = ^uint64(0) 23 makeMmap := func(addr, size, prot uint64) *prog.Call { 24 call := prog.MakeCall(meta, []prog.Arg{ 25 prog.MakeVmaPointerArg(meta.Args[0].Type, prog.DirIn, addr, size), 26 prog.MakeConstArg(meta.Args[1].Type, prog.DirIn, size), 27 prog.MakeConstArg(meta.Args[2].Type, prog.DirIn, prot), 28 prog.MakeConstArg(meta.Args[3].Type, prog.DirIn, flags), 29 prog.MakeResultArg(meta.Args[4].Type, prog.DirIn, nil, invalidFD), 30 }) 31 i := len(call.Args) 32 // Some targets have a padding argument between fd and offset. 33 if len(meta.Args) > 6 { 34 call.Args = append(call.Args, prog.MakeConstArg(meta.Args[i].Type, prog.DirIn, 0)) 35 i++ 36 } 37 call.Args = append(call.Args, prog.MakeConstArg(meta.Args[i].Type, prog.DirIn, 0)) 38 return call 39 } 40 return func() []*prog.Call { 41 if contain { 42 return []*prog.Call{ 43 makeMmap(^target.PageSize+1, target.PageSize, 0), 44 makeMmap(0, size, protRW), 45 makeMmap(size, target.PageSize, 0), 46 } 47 } 48 return []*prog.Call{makeMmap(0, size, protRW)} 49 } 50 } 51 52 func MakeSyzMmap(target *prog.Target) func() []*prog.Call { 53 meta := target.SyscallMap["syz_mmap"] 54 size := target.NumPages * target.PageSize 55 return func() []*prog.Call { 56 return []*prog.Call{ 57 prog.MakeCall(meta, []prog.Arg{ 58 prog.MakeVmaPointerArg(meta.Args[0].Type, prog.DirIn, 0, size), 59 prog.MakeConstArg(meta.Args[1].Type, prog.DirIn, size), 60 }), 61 } 62 } 63 } 64 65 type UnixNeutralizer struct { 66 MAP_FIXED uint64 67 S_IFREG uint64 68 S_IFCHR uint64 69 S_IFBLK uint64 70 S_IFIFO uint64 71 S_IFSOCK uint64 72 } 73 74 func MakeUnixNeutralizer(target *prog.Target) *UnixNeutralizer { 75 return &UnixNeutralizer{ 76 MAP_FIXED: target.GetConst("MAP_FIXED"), 77 S_IFREG: target.GetConst("S_IFREG"), 78 S_IFCHR: target.GetConst("S_IFCHR"), 79 S_IFBLK: target.GetConst("S_IFBLK"), 80 S_IFIFO: target.GetConst("S_IFIFO"), 81 S_IFSOCK: target.GetConst("S_IFSOCK"), 82 } 83 } 84 85 func (arch *UnixNeutralizer) Neutralize(c *prog.Call, fixStructure bool) error { 86 switch c.Meta.CallName { 87 case "mmap": 88 if c.Meta.Name == "mmap$bifrost" { 89 // Mali bifrost mmap doesn't support MAP_FIXED. 90 return nil 91 } 92 // Add MAP_FIXED flag, otherwise it produces non-deterministic results. 93 c.Args[3].(*prog.ConstArg).Val |= arch.MAP_FIXED 94 case "mknod", "mknodat", "compat_50_mknod": 95 pos := 1 96 if c.Meta.CallName == "mknodat" { 97 pos = 2 98 } 99 switch c.Args[pos+1].Type().(type) { 100 case *prog.ProcType, *prog.ResourceType: 101 return nil 102 } 103 mode := c.Args[pos].(*prog.ConstArg) 104 dev := c.Args[pos+1].(*prog.ConstArg) 105 dev.Val = uint64(uint32(dev.Val)) 106 // Char and block devices read/write io ports, kernel memory and do other nasty things. 107 // TODO: not required if executor drops privileges. 108 mask := arch.S_IFREG | arch.S_IFCHR | arch.S_IFBLK | arch.S_IFIFO | arch.S_IFSOCK 109 switch mode.Val & mask { 110 case arch.S_IFREG, arch.S_IFIFO, arch.S_IFSOCK: 111 case arch.S_IFBLK: 112 if dev.Val>>8 == 7 { 113 break // loop 114 } 115 mode.Val &^= arch.S_IFBLK 116 mode.Val |= arch.S_IFREG 117 case arch.S_IFCHR: 118 if dev.Val == 0x103 { 119 break // /dev/null 120 } 121 mode.Val &^= arch.S_IFCHR 122 mode.Val |= arch.S_IFREG 123 } 124 case "exit", "exit_group": 125 code := c.Args[0].(*prog.ConstArg) 126 // This code is reserved by executor. 127 if code.Val%128 == 67 { 128 code.Val = 1 129 } 130 } 131 return nil 132 }