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