1// Copyright 2017 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 linux 5 6import ( 7 "runtime" 8 9 "github.com/google/syzkaller/prog" 10 "github.com/google/syzkaller/sys/targets" 11) 12 13/* 14func init() { 15 prog.RegisterTarget(gen.Target_amd64, initTarget) 16 prog.RegisterTarget(gen.Target_386, initTarget) 17 prog.RegisterTarget(gen.Target_arm64, initTarget) 18 prog.RegisterTarget(gen.Target_arm, initTarget) 19 prog.RegisterTarget(gen.Target_ppc64le, initTarget) 20} 21*/ 22 23func InitTarget(target *prog.Target) { 24 arch := &arch{ 25 unix: targets.MakeUnixSanitizer(target), 26 clockGettimeSyscall: target.SyscallMap["clock_gettime"], 27 SYSLOG_ACTION_CONSOLE_OFF: target.ConstMap["SYSLOG_ACTION_CONSOLE_OFF"], 28 SYSLOG_ACTION_CONSOLE_ON: target.ConstMap["SYSLOG_ACTION_CONSOLE_ON"], 29 SYSLOG_ACTION_SIZE_UNREAD: target.ConstMap["SYSLOG_ACTION_SIZE_UNREAD"], 30 FIFREEZE: target.ConstMap["FIFREEZE"], 31 FITHAW: target.ConstMap["FITHAW"], 32 PTRACE_TRACEME: target.ConstMap["PTRACE_TRACEME"], 33 CLOCK_REALTIME: target.ConstMap["CLOCK_REALTIME"], 34 ARCH_SET_FS: target.ConstMap["ARCH_SET_FS"], 35 ARCH_SET_GS: target.ConstMap["ARCH_SET_GS"], 36 AF_NFC: target.ConstMap["AF_NFC"], 37 AF_LLC: target.ConstMap["AF_LLC"], 38 AF_BLUETOOTH: target.ConstMap["AF_BLUETOOTH"], 39 } 40 41 target.MakeMmap = targets.MakePosixMmap(target) 42 target.SanitizeCall = arch.sanitizeCall 43 target.SpecialTypes = map[string]func(g *prog.Gen, typ prog.Type, old prog.Arg) ( 44 prog.Arg, []*prog.Call){ 45 "timespec": arch.generateTimespec, 46 "timeval": arch.generateTimespec, 47 "sockaddr_alg": arch.generateSockaddrAlg, 48 "alg_name": arch.generateAlgName, 49 "alg_aead_name": arch.generateAlgAeadName, 50 "alg_hash_name": arch.generateAlgHashName, 51 "alg_blkcipher_name": arch.generateAlgBlkcipherhName, 52 "ipt_replace": arch.generateIptables, 53 "ip6t_replace": arch.generateIptables, 54 "arpt_replace": arch.generateArptables, 55 "ebt_replace": arch.generateEbtables, 56 } 57 target.StringDictionary = stringDictionary 58 59 if target.Arch == runtime.GOARCH { 60 KCOV_INIT_TRACE = uintptr(target.ConstMap["KCOV_INIT_TRACE"]) 61 KCOV_ENABLE = uintptr(target.ConstMap["KCOV_ENABLE"]) 62 KCOV_DISABLE = uintptr(target.ConstMap["KCOV_DISABLE"]) 63 KCOV_TRACE_CMP = uintptr(target.ConstMap["KCOV_TRACE_CMP"]) 64 } 65} 66 67var ( 68 // This should not be here, but for now we expose this for syz-fuzzer. 69 KCOV_INIT_TRACE uintptr 70 KCOV_ENABLE uintptr 71 KCOV_DISABLE uintptr 72 KCOV_TRACE_CMP uintptr 73 74 // TODO(dvyukov): get rid of this, this must be in descriptions. 75 stringDictionary = []string{"user", "keyring", "trusted", "system", "security", "selinux", 76 "posix_acl_access", "mime_type", "md5sum", "nodev", "self", 77 "bdev", "proc", "cgroup", "cpuset", 78 "lo", "eth0", "eth1", "em0", "em1", "wlan0", "wlan1", "ppp0", "ppp1", 79 "vboxnet0", "vboxnet1", "vmnet0", "vmnet1", "GPL"} 80) 81 82type arch struct { 83 unix *targets.UnixSanitizer 84 85 clockGettimeSyscall *prog.Syscall 86 87 SYSLOG_ACTION_CONSOLE_OFF uint64 88 SYSLOG_ACTION_CONSOLE_ON uint64 89 SYSLOG_ACTION_SIZE_UNREAD uint64 90 FIFREEZE uint64 91 FITHAW uint64 92 PTRACE_TRACEME uint64 93 CLOCK_REALTIME uint64 94 ARCH_SET_FS uint64 95 ARCH_SET_GS uint64 96 AF_NFC uint64 97 AF_LLC uint64 98 AF_BLUETOOTH uint64 99} 100 101func (arch *arch) sanitizeCall(c *prog.Call) { 102 arch.unix.SanitizeCall(c) 103 switch c.Meta.CallName { 104 case "syslog": 105 cmd := c.Args[0].(*prog.ConstArg) 106 cmd.Val = uint64(uint32(cmd.Val)) 107 // These disable console output, but we need it. 108 if cmd.Val == arch.SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == arch.SYSLOG_ACTION_CONSOLE_ON { 109 cmd.Val = arch.SYSLOG_ACTION_SIZE_UNREAD 110 } 111 case "ioctl": 112 cmd := c.Args[1].(*prog.ConstArg) 113 // Freeze kills machine. Though, it is an interesting functions, 114 // so we need to test it somehow. 115 // TODO: not required if executor drops privileges. 116 if uint64(uint32(cmd.Val)) == arch.FIFREEZE { 117 cmd.Val = arch.FITHAW 118 } 119 case "ptrace": 120 req := c.Args[0].(*prog.ConstArg) 121 // PTRACE_TRACEME leads to unkillable processes, see: 122 // https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw 123 if req.Val == arch.PTRACE_TRACEME { 124 req.Val = ^uint64(0) 125 } 126 case "arch_prctl": 127 // fs holds address of tls, if a program messes it at least signal 128 // handling will break. This also allows a program to do writes 129 // at arbitrary addresses, which usually leads to machine outbreak. 130 cmd := c.Args[0].(*prog.ConstArg) 131 if uint64(uint32(cmd.Val)) == arch.ARCH_SET_FS { 132 cmd.Val = arch.ARCH_SET_GS 133 } 134 case "syz_init_net_socket": 135 // Don't let it mess with arbitrary sockets in init namespace. 136 family := c.Args[0].(*prog.ConstArg) 137 switch uint64(uint32(family.Val)) { 138 case arch.AF_NFC, arch.AF_LLC, arch.AF_BLUETOOTH: 139 default: 140 family.Val = ^uint64(0) 141 } 142 } 143 144 switch c.Meta.Name { 145 case "setsockopt$EBT_SO_SET_ENTRIES": 146 arch.sanitizeEbtables(c) 147 } 148} 149 150func (arch *arch) generateTimespec(g *prog.Gen, typ0 prog.Type, old prog.Arg) (arg prog.Arg, calls []*prog.Call) { 151 typ := typ0.(*prog.StructType) 152 // We need to generate timespec/timeval that are either 153 // (1) definitely in the past, or 154 // (2) definitely in unreachable fututre, or 155 // (3) few ms ahead of now. 156 // Note: timespec/timeval can be absolute or relative to now. 157 // Note: executor has blocking syscall timeout of 20ms, 158 // so we generate both 10ms and 30ms. 159 usec := typ.Name() == "timeval" 160 switch { 161 case g.NOutOf(1, 4): 162 // Now for relative, past for absolute. 163 arg = prog.MakeGroupArg(typ, []prog.Arg{ 164 prog.MakeResultArg(typ.Fields[0], nil, 0), 165 prog.MakeResultArg(typ.Fields[1], nil, 0), 166 }) 167 case g.NOutOf(1, 3): 168 // Few ms ahead for relative, past for absolute 169 nsec := uint64(10 * 1e6) 170 if g.NOutOf(1, 2) { 171 nsec = 30 * 1e6 172 } 173 if usec { 174 nsec /= 1e3 175 } 176 arg = prog.MakeGroupArg(typ, []prog.Arg{ 177 prog.MakeResultArg(typ.Fields[0], nil, 0), 178 prog.MakeResultArg(typ.Fields[1], nil, nsec), 179 }) 180 case g.NOutOf(1, 2): 181 // Unreachable fututre for both relative and absolute 182 arg = prog.MakeGroupArg(typ, []prog.Arg{ 183 prog.MakeResultArg(typ.Fields[0], nil, 2e9), 184 prog.MakeResultArg(typ.Fields[1], nil, 0), 185 }) 186 default: 187 // Few ms ahead for absolute. 188 meta := arch.clockGettimeSyscall 189 ptrArgType := meta.Args[1].(*prog.PtrType) 190 argType := ptrArgType.Type.(*prog.StructType) 191 tp := prog.MakeGroupArg(argType, []prog.Arg{ 192 prog.MakeResultArg(argType.Fields[0], nil, 0), 193 prog.MakeResultArg(argType.Fields[1], nil, 0), 194 }) 195 var tpaddr prog.Arg 196 tpaddr, calls = g.Alloc(ptrArgType, tp) 197 gettime := &prog.Call{ 198 Meta: meta, 199 Args: []prog.Arg{ 200 prog.MakeConstArg(meta.Args[0], arch.CLOCK_REALTIME), 201 tpaddr, 202 }, 203 Ret: prog.MakeReturnArg(meta.Ret), 204 } 205 calls = append(calls, gettime) 206 sec := prog.MakeResultArg(typ.Fields[0], tp.Inner[0].(*prog.ResultArg), 0) 207 nsec := prog.MakeResultArg(typ.Fields[1], tp.Inner[1].(*prog.ResultArg), 0) 208 msec := uint64(10) 209 if g.NOutOf(1, 2) { 210 msec = 30 211 } 212 if usec { 213 nsec.OpDiv = 1e3 214 nsec.OpAdd = msec * 1e3 215 } else { 216 nsec.OpAdd = msec * 1e6 217 } 218 arg = prog.MakeGroupArg(typ, []prog.Arg{sec, nsec}) 219 } 220 return 221} 222