• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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