-
Notifications
You must be signed in to change notification settings - Fork 1
/
syscall_linux.go
141 lines (124 loc) · 3.21 KB
/
syscall_linux.go
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
135
136
137
138
139
140
141
// Copyright (c) Seth Hoenig
// SPDX-License-Identifier: MPL-2.0
//go:build linux
package landlock
import (
"errors"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
"kernel.org/pub/linux/libs/security/libcap/psx"
)
var (
// ErrVersionUndetectable indicates a failure when checking landlock version
ErrVersionUndetectable = errors.New("landlock version detection failure")
// ErrNotSupported indicates landlock is not supported on this system
ErrNotSupported = errors.New("landlock not supported")
)
type rule uint64
// FileSystem rules.
const (
fsExecute rule = unix.LANDLOCK_ACCESS_FS_EXECUTE
fsWriteFile rule = unix.LANDLOCK_ACCESS_FS_WRITE_FILE
fsReadFile rule = unix.LANDLOCK_ACCESS_FS_READ_FILE
fsReadDir rule = unix.LANDLOCK_ACCESS_FS_READ_DIR
fsRemoveFile rule = unix.LANDLOCK_ACCESS_FS_REMOVE_FILE
fsRemoveDir rule = unix.LANDLOCK_ACCESS_FS_REMOVE_DIR
fsMakeChar rule = unix.LANDLOCK_ACCESS_FS_MAKE_CHAR
fsMakeDir rule = unix.LANDLOCK_ACCESS_FS_MAKE_DIR
fsMakeRegular rule = unix.LANDLOCK_ACCESS_FS_MAKE_REG
fsMakeSocket rule = unix.LANDLOCK_ACCESS_FS_MAKE_SOCK
fsMakeFifo rule = unix.LANDLOCK_ACCESS_FS_MAKE_FIFO
fsMakeBlock rule = unix.LANDLOCK_ACCESS_FS_MAKE_BLOCK
fsMakeSymlink rule = unix.LANDLOCK_ACCESS_FS_MAKE_SYM
fsRefer rule = unix.LANDLOCK_ACCESS_FS_REFER
fsTruncate rule = unix.LANDLOCK_ACCESS_FS_TRUNCATE
)
func abi() (int, error) {
r0, _, e1 := syscall.Syscall(
unix.SYS_LANDLOCK_CREATE_RULESET,
0,
0,
unix.LANDLOCK_CREATE_RULESET_VERSION,
)
v := int(r0)
switch {
case e1 != 0:
return v, syscall.Errno(e1)
case v < 0:
return 0, ErrVersionUndetectable
case v == 0:
return 0, ErrNotSupported
default:
return v, nil
}
}
func capabilities() rule {
opts := fsExecute |
fsWriteFile | fsReadFile | fsReadDir |
fsRemoveFile | fsRemoveDir | fsMakeChar |
fsMakeDir | fsMakeRegular | fsMakeSocket |
fsMakeFifo | fsMakeBlock | fsMakeSymlink
if version >= 2 {
opts |= fsRefer
}
if version >= 3 {
opts |= fsTruncate
}
return opts
}
type rulesetAttr struct {
handleAccessFS uint64
}
func ruleset(ra *rulesetAttr) (int, error) {
const size = 8
r0, _, e1 := syscall.Syscall(
unix.SYS_LANDLOCK_CREATE_RULESET,
uintptr(unsafe.Pointer(ra)),
uintptr(size),
0,
)
return int(r0), errno(e1)
}
type beneathAttr struct {
allowedAccess uint64
parentFd int
}
func add(fd int, ba *beneathAttr) error {
_, _, e1 := syscall.Syscall6(
unix.SYS_LANDLOCK_ADD_RULE,
uintptr(fd),
uintptr(unix.LANDLOCK_RULE_PATH_BENEATH),
uintptr(unsafe.Pointer(ba)),
0, 0, 0,
)
return errno(e1)
}
// https://git.kernel.org/pub/scm/libs/libcap/libcap.git/tree/psx/psx.go
//
// apply NO_NEW_PRIVS to all OS threads concurrently (with or without CGO)
func prctl() error {
_, _, e1 := psx.Syscall6(
syscall.SYS_PRCTL,
unix.PR_SET_NO_NEW_PRIVS,
1, 0, 0, 0, 0,
)
return errno(e1)
}
// https://git.kernel.org/pub/scm/libs/libcap/libcap.git/tree/psx/psx.go
//
// apply SYS_LANDLOCK_RESTRICT_SELF to all OS threads concurrently (with or without CGO)
func restrict(fd int) error {
_, _, e1 := psx.Syscall3(
unix.SYS_LANDLOCK_RESTRICT_SELF,
uintptr(fd),
0, 0,
)
return errno(e1)
}
func errno(e syscall.Errno) error {
if e == 0 {
return nil
}
return e
}