aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/flatrpc/helpers.go
blob: 5aa5cfe74cf62a5a426f48fb005c2e1d11347eb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2024 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package flatrpc

import (
	"fmt"
	"slices"
	"sync/atomic"
	"syscall"
	"unsafe"

	"github.com/google/syzkaller/prog"
)

const AllFeatures = ^Feature(0)

// Flatbuffers compiler adds T suffix to object API types, which are actual structs representing types.
// This leads to non-idiomatic Go code, e.g. we would have to use []FileInfoT in Go code.
// So we use Raw suffix for all flatbuffers tables and rename object API types here to idiomatic names.
type ConnectHello = ConnectHelloRawT
type ConnectRequest = ConnectRequestRawT
type ConnectReply = ConnectReplyRawT
type InfoRequest = InfoRequestRawT
type InfoReply = InfoReplyRawT
type FileInfo = FileInfoRawT
type GlobInfo = GlobInfoRawT
type FeatureInfo = FeatureInfoRawT
type HostMessages = HostMessagesRawT
type HostMessage = HostMessageRawT
type ExecutorMessages = ExecutorMessagesRawT
type ExecutorMessage = ExecutorMessageRawT
type ExecRequest = ExecRequestRawT
type StateRequest = StateRequestRawT
type SignalUpdate = SignalUpdateRawT
type CorpusTriaged = CorpusTriagedRawT
type ExecutingMessage = ExecutingMessageRawT
type CallInfo = CallInfoRawT
type Comparison = ComparisonRawT
type ExecOpts = ExecOptsRawT
type ProgInfo = ProgInfoRawT
type ExecResult = ExecResultRawT
type StateResult = StateResultRawT

func init() {
	var req ExecRequest
	if prog.MaxPids > unsafe.Sizeof(req.Avoid)*8 {
		panic("all procs won't fit ito ExecRequest.Avoid")
	}
}

func (pi *ProgInfo) Clone() *ProgInfo {
	if pi == nil {
		return nil
	}
	ret := *pi
	ret.Extra = ret.Extra.clone()
	ret.Calls = make([]*CallInfo, len(pi.Calls))
	for i, call := range pi.Calls {
		ret.Calls[i] = call.clone()
	}
	return &ret
}

func (ci *CallInfo) clone() *CallInfo {
	if ci == nil {
		return nil
	}
	ret := *ci
	ret.Signal = slices.Clone(ret.Signal)
	ret.Cover = slices.Clone(ret.Cover)
	ret.Comps = slices.Clone(ret.Comps)
	return &ret
}

func EmptyProgInfo(calls int) *ProgInfo {
	info := &ProgInfo{}
	for i := 0; i < calls; i++ {
		info.Calls = append(info.Calls, &CallInfo{
			// Store some unsuccessful errno in the case we won't get any result.
			// It also won't have CallExecuted flag, but it's handy to make it
			// look failed based on errno as well.
			Error: int32(syscall.ENOSYS),
		})
	}
	return info
}

func SandboxToFlags(sandbox string) (ExecEnv, error) {
	switch sandbox {
	case "none":
		return ExecEnvSandboxNone, nil
	case "setuid":
		return ExecEnvSandboxSetuid, nil
	case "namespace":
		return ExecEnvSandboxNamespace, nil
	case "android":
		return ExecEnvSandboxAndroid, nil
	default:
		return 0, fmt.Errorf("sandbox must contain one of none/setuid/namespace/android")
	}
}

func (hdr *SnapshotHeaderT) UpdateState(state SnapshotState) {
	atomic.StoreUint64((*uint64)(unsafe.Pointer(&hdr.State)), uint64(state))
}

func (hdr *SnapshotHeaderT) LoadState() SnapshotState {
	return SnapshotState(atomic.LoadUint64((*uint64)(unsafe.Pointer(&hdr.State))))
}