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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
package main
import (
"fmt"
"runtime"
"syscall"
"unsafe"
)
var keySpecProcessKeyringArg = ^uintptr(1)
func securityKeysPtracePerf() error {
nr, err := securitySyscallNumbers(runtime.GOARCH)
if err != nil {
return err
}
// Best-effort probes: these syscalls may fail with EPERM/EACCES depending on
// policy, but the tracepoints are still exercised.
runKeySyscalls(nr)
runPtraceSyscall(nr)
runPerfEventOpenSyscall(nr)
return nil
}
type securitySyscalls struct {
addKey uintptr
requestKey uintptr
keyctl uintptr
ptrace uintptr
perfEventOpen uintptr
}
func securitySyscallNumbers(arch string) (securitySyscalls, error) {
switch arch {
case "amd64":
return securitySyscalls{
addKey: 248,
requestKey: 249,
keyctl: 250,
ptrace: 101,
perfEventOpen: 298,
}, nil
case "arm64":
return securitySyscalls{
addKey: 217,
requestKey: 218,
keyctl: 219,
ptrace: 117,
perfEventOpen: 241,
}, nil
default:
return securitySyscalls{}, fmt.Errorf("security syscall numbers not defined for GOARCH=%s", arch)
}
}
func runKeySyscalls(nr securitySyscalls) {
keyType, _ := syscall.BytePtrFromString("user")
desc, _ := syscall.BytePtrFromString("ior-key")
payload := []byte("ior")
var payloadPtr uintptr
if len(payload) > 0 {
payloadPtr = uintptr(unsafe.Pointer(&payload[0]))
}
_, _, _ = syscall.Syscall6(
nr.addKey,
uintptr(unsafe.Pointer(keyType)),
uintptr(unsafe.Pointer(desc)),
payloadPtr,
uintptr(len(payload)),
keySpecProcessKeyringArg,
0,
)
_, _, _ = syscall.Syscall6(
nr.requestKey,
uintptr(unsafe.Pointer(keyType)),
uintptr(unsafe.Pointer(desc)),
0,
keySpecProcessKeyringArg,
0,
0,
)
_, _, _ = syscall.Syscall6(
nr.keyctl,
0,
keySpecProcessKeyringArg,
0,
0,
0,
0,
)
}
func runPtraceSyscall(nr securitySyscalls) {
_, _, _ = syscall.Syscall6(
nr.ptrace,
uintptr(syscall.PTRACE_PEEKDATA),
^uintptr(0),
0,
0,
0,
0,
)
}
type perfEventAttr struct {
Type uint32
Size uint32
Config uint64
}
func runPerfEventOpenSyscall(nr securitySyscalls) {
attr := perfEventAttr{
Type: 1, // PERF_TYPE_SOFTWARE
Size: uint32(unsafe.Sizeof(perfEventAttr{})),
Config: 0, // PERF_COUNT_SW_CPU_CLOCK
}
fd, _, _ := syscall.Syscall6(
nr.perfEventOpen,
uintptr(unsafe.Pointer(&attr)),
0,
^uintptr(0), // cpu = -1
^uintptr(0), // group_fd = -1
0,
0,
)
if int64(fd) >= 0 {
_ = syscall.Close(int(fd))
}
}
|