Compare commits

...

39 Commits

Author SHA1 Message Date
b73a789dfe
.clang-format: increase indent width
All checks were successful
Test / Create distribution (push) Successful in 26s
Test / Sandbox (push) Successful in 2m27s
Test / Hakurei (push) Successful in 3m17s
Test / Hpkg (push) Successful in 3m27s
Test / Sandbox (race detector) (push) Successful in 4m21s
Test / Hakurei (race detector) (push) Successful in 4m59s
Test / Flake checks (push) Successful in 1m31s
This significantly increases readability. This patch is pretty big so it is being done after mostly everything has settled.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-16 20:57:29 +09:00
38b5ff0cec
internal/wayland: check pathname size
All checks were successful
Test / Create distribution (push) Successful in 26s
Test / Sandbox (push) Successful in 39s
Test / Sandbox (race detector) (push) Successful in 39s
Test / Hakurei (push) Successful in 43s
Test / Hakurei (race detector) (push) Successful in 43s
Test / Hpkg (push) Successful in 41s
Test / Flake checks (push) Successful in 1m22s
This avoids passing a truncated pathname to the kernel.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-16 03:34:05 +09:00
3c204b9b40
internal/wayland: increase error detail
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m14s
Test / Hakurei (push) Successful in 3m16s
Test / Hpkg (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 4m18s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m21s
This includes targeted paths in the returned errors.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-16 02:09:50 +09:00
00771efeb4
internal/wayland: remove fd typecasts
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m21s
Test / Hakurei (push) Successful in 3m14s
Test / Hpkg (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 4m18s
Test / Hakurei (race detector) (push) Successful in 5m5s
Test / Flake checks (push) Successful in 1m24s
These are no longer necessary since RawConn is no longer used.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-16 01:45:37 +09:00
61972d61f6
internal/wayland: reimplement connect/bind code
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m13s
Test / Hakurei (push) Successful in 3m18s
Test / Hpkg (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 4m14s
Test / Hakurei (race detector) (push) Successful in 5m7s
Test / Flake checks (push) Successful in 1m26s
The old implementation is relocated to system/wayland/deprecated.go.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-16 01:23:16 +09:00
fe40af7b7e
internal/wayland: relocate connection struct
All checks were successful
Test / Create distribution (push) Successful in 44s
Test / Sandbox (push) Successful in 2m24s
Test / Hakurei (push) Successful in 3m23s
Test / Hpkg (push) Successful in 4m14s
Test / Sandbox (race detector) (push) Successful in 4m24s
Test / Hakurei (race detector) (push) Successful in 5m20s
Test / Flake checks (push) Successful in 1m33s
This interface is getting replaced, so relocating it to the deprecated wrapper package before working on its replacement.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-15 23:25:46 +09:00
12751932d1
internal/wayland: improve error handling
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m21s
Test / Hakurei (push) Successful in 3m20s
Test / Hpkg (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 4m24s
Test / Hakurei (race detector) (push) Successful in 5m16s
Test / Flake checks (push) Successful in 1m32s
Note: wl_registry_add_listener is undocumented everywhere. Its implementation calls wl_proxy_add_listener which returns 0 on success or -1 on failure.
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-15 21:26:31 +09:00
41b49137a8
.clang-format: do not limit line length
All checks were successful
Test / Create distribution (push) Successful in 38s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 4m26s
Test / Hakurei (race detector) (push) Successful in 5m10s
Test / Flake checks (push) Successful in 1m27s
This hard limit destroys readability in some places.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-15 17:06:43 +09:00
c761e1de4d
nix: build with clang
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 41s
Test / Sandbox (race detector) (push) Successful in 41s
Test / Hakurei (push) Successful in 44s
Test / Hakurei (race detector) (push) Successful in 45s
Test / Hpkg (push) Successful in 42s
Test / Flake checks (push) Successful in 1m29s
Clang is better than gcc in various ways. This also pulls in clang-format which is very helpful.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-15 16:36:36 +09:00
a91920310d
internal: relocate packages
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m20s
Test / Hakurei (push) Successful in 3m19s
Test / Hpkg (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 4m31s
Test / Hakurei (race detector) (push) Successful in 5m12s
Test / Flake checks (push) Successful in 1m32s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-15 13:58:34 +09:00
16e674782a
cmd/hakurei: reorder show entries
All checks were successful
Test / Create distribution (push) Successful in 25s
Test / Sandbox (race detector) (push) Successful in 39s
Test / Sandbox (push) Successful in 40s
Test / Hakurei (push) Successful in 44s
Test / Hakurei (race detector) (push) Successful in 43s
Test / Hpkg (push) Successful in 41s
Test / Flake checks (push) Successful in 1m20s
This order semantically makes more sense and generally looks tidier.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 22:14:49 +09:00
47244daefb
treewide: migrate ldd callers
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m22s
Test / Hakurei (push) Successful in 3m17s
Test / Hpkg (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 4m15s
Test / Hakurei (race detector) (push) Successful in 5m6s
Test / Flake checks (push) Successful in 1m22s
This discontinues use of the deprecated ldd.Exec function for #25.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 21:59:59 +09:00
46fa104419
ldd: require absolute pathname
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m22s
Test / Hakurei (push) Successful in 3m18s
Test / Hpkg (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 4m12s
Test / Hakurei (race detector) (push) Successful in 5m7s
Test / Flake checks (push) Successful in 1m23s
The sandbox which ldd(1) runs in does not inherit parent work directory, so relative pathnames will not work correctly. While it is trivial to support such a use case, the use of relative pathnames is highly error-prone and generally frowned against in this project. The Exec function remains available under the same signature until v0.4.0 where it will be removed.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 21:53:10 +09:00
45953b3d9c
ldd: cancel on decoder error
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m20s
Test / Hakurei (push) Successful in 3m14s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m22s
Test / Hakurei (race detector) (push) Successful in 5m7s
Test / Flake checks (push) Successful in 1m28s
This prevents blocking from failures caused by ldd(1) emitting output that is not anticipated by the decoder.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 21:43:34 +09:00
42759e7a9f
ldd: create musl entry representation
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m16s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 3m59s
Test / Sandbox (race detector) (push) Successful in 4m15s
Test / Hakurei (race detector) (push) Successful in 5m4s
Test / Flake checks (push) Successful in 1m39s
This mostly helps with debugging.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 21:38:35 +09:00
8e2d2c8246
ldd: check decoder scan guard
All checks were successful
Test / Create distribution (push) Successful in 38s
Test / Sandbox (push) Successful in 2m19s
Test / Hakurei (push) Successful in 3m23s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m19s
Test / Hakurei (race detector) (push) Successful in 5m12s
Test / Flake checks (push) Successful in 1m27s
This was unreachable via the Parse wrapper.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 18:32:47 +09:00
299685775a
container: provide usage example
All checks were successful
Test / Create distribution (push) Successful in 39s
Test / Sandbox (push) Successful in 2m17s
Test / Hakurei (push) Successful in 3m15s
Test / Sandbox (race detector) (push) Successful in 4m12s
Test / Hpkg (push) Successful in 4m16s
Test / Hakurei (race detector) (push) Successful in 5m7s
Test / Flake checks (push) Successful in 1m29s
This requires cgo so unfortunately will not run in the playground.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 18:25:22 +09:00
b7406cc4c4
ldd: update package doc comment
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m19s
Test / Hakurei (push) Successful in 3m18s
Test / Sandbox (race detector) (push) Successful in 4m16s
Test / Hpkg (push) Successful in 4m14s
Test / Hakurei (race detector) (push) Successful in 5m7s
Test / Flake checks (push) Successful in 1m34s
This should hopefully deter misuse of this package.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 17:49:01 +09:00
690a0ed0d6
ldd: decode from reader
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m27s
Test / Hakurei (push) Successful in 3m20s
Test / Hpkg (push) Successful in 4m10s
Test / Sandbox (race detector) (push) Successful in 4m18s
Test / Hakurei (race detector) (push) Successful in 5m5s
Test / Flake checks (push) Successful in 1m31s
This should reduce memory footprint of the parsing process and allow decoding part of the stream.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 08:33:19 +09:00
a9d72a5eb1
internal/outcome: rename run from main
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m31s
Test / Hakurei (push) Successful in 3m23s
Test / Sandbox (race detector) (push) Successful in 4m14s
Test / Hpkg (push) Successful in 4m16s
Test / Hakurei (race detector) (push) Successful in 5m4s
Test / Flake checks (push) Successful in 1m30s
The "main.go" name is quite confusing as this is often only present in main packages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 01:06:14 +09:00
6d14bb814f
container/fhs: add constant for /dev/shm/
All checks were successful
Test / Create distribution (push) Successful in 36s
Test / Sandbox (push) Successful in 2m21s
Test / Hakurei (push) Successful in 3m16s
Test / Hpkg (push) Successful in 4m11s
Test / Sandbox (race detector) (push) Successful in 4m12s
Test / Hakurei (race detector) (push) Successful in 5m6s
Test / Flake checks (push) Successful in 1m32s
This is mounted for the default read-only /dev/ when programs want to use shm_open(3). Defining it here is less error-prone and saves the extra append at runtime.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-14 01:03:26 +09:00
be0e387ab0
internal/info: relocate from internal
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m27s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m11s
Test / Sandbox (race detector) (push) Successful in 4m18s
Test / Hakurei (race detector) (push) Successful in 5m2s
Test / Flake checks (push) Successful in 1m30s
This is cleaner and makes more sense. The longer LDFLAGS was never a valid concern since it is always inserted by a script.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-13 07:29:46 +09:00
abeb67964f
treewide: document linkname uses
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m17s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 4m12s
Test / Hakurei (race detector) (push) Successful in 5m2s
Test / Flake checks (push) Successful in 1m26s
These provide justification for each use of linkname. Poorly thought out uses of linkname are removed.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-13 07:14:16 +09:00
bf5d10743f
treewide: import internal/system
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 4m16s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m31s
For #24.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-13 01:22:47 +09:00
4e7aab07d5
internal/system: relocate from system
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m17s
Test / Sandbox (race detector) (push) Successful in 4m7s
Test / Hpkg (push) Successful in 4m13s
Test / Hakurei (race detector) (push) Successful in 5m3s
Test / Flake checks (push) Successful in 1m40s
These packages are highly specific to hakurei and are difficult to use safely from other pieces of code.

Their exported symbols are made available until v0.4.0 where they will be removed for #24.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-13 01:17:47 +09:00
15a66a2b31
treewide: import internal/helper
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m15s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m4s
Test / Sandbox (race detector) (push) Successful in 4m8s
Test / Hakurei (race detector) (push) Successful in 5m3s
Test / Flake checks (push) Successful in 1m27s
For #24.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-12 23:19:34 +09:00
f347d44c22
internal/helper: relocate from helper
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m26s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m16s
Test / Hakurei (race detector) (push) Successful in 5m5s
Test / Flake checks (push) Successful in 1m23s
This package is ugly and is pending removal only kept alive by xdg-dbus-proxy.

Its exported symbols are made available until v0.4.0 where it will be removed for #24.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-12 23:16:13 +09:00
b5630f6883
test: move package sandbox internal
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Hakurei (push) Successful in 43s
Test / Hpkg (push) Successful in 40s
Test / Hakurei (race detector) (push) Successful in 43s
Test / Sandbox (push) Successful in 1m56s
Test / Sandbox (race detector) (push) Successful in 2m39s
Test / Flake checks (push) Successful in 1m24s
This should never be used outside vm tests.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-12 23:03:22 +09:00
17ffdb2dcf
release: 0.3.1
All checks were successful
Release / Create release (push) Successful in 39s
Test / Sandbox (push) Successful in 40s
Test / Hakurei (push) Successful in 1m36s
Test / Create distribution (push) Successful in 26s
Test / Sandbox (race detector) (push) Successful in 4m33s
Test / Hpkg (push) Successful in 4m23s
Test / Hakurei (race detector) (push) Successful in 5m11s
Test / Flake checks (push) Successful in 1m37s
Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-12 00:53:14 +09:00
ac34635890
container: set FD_CLOEXEC on all open files
All checks were successful
Test / Create distribution (push) Successful in 29s
Test / Sandbox (race detector) (push) Successful in 40s
Test / Hakurei (race detector) (push) Successful in 46s
Test / Hakurei (push) Successful in 47s
Test / Sandbox (push) Successful in 44s
Test / Hpkg (push) Successful in 43s
Test / Flake checks (push) Successful in 1m31s
While fd created from this side always has the FD_CLOEXEC flag, the same is not true for files left open by the parent. This change prevents those files from leaking into the container.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-12 00:18:29 +09:00
9dec9dbc4b
container/init: close setup pipe early
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m32s
Test / Sandbox (race detector) (push) Successful in 4m30s
Test / Hpkg (push) Successful in 4m48s
Test / Hakurei (race detector) (push) Successful in 6m17s
Test / Hakurei (push) Successful in 3m17s
Test / Flake checks (push) Successful in 1m21s
This prevents leaking the setup pipe.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-11 07:31:58 +09:00
2f74adc8bd
container/init: close initial process files on termination
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m29s
Test / Sandbox (race detector) (push) Successful in 4m28s
Test / Hakurei (push) Successful in 4m34s
Test / Hpkg (push) Successful in 4m42s
Test / Hakurei (race detector) (push) Successful in 6m9s
Test / Flake checks (push) Successful in 1m26s
This closes them during the adopt wait delay. This also keeps them alive.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-10 20:35:59 +09:00
d7e0104ae4
treewide: reject impossible user-supplied fd
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m36s
Test / Hakurei (push) Successful in 4m33s
Test / Sandbox (race detector) (push) Successful in 4m30s
Test / Hpkg (push) Successful in 4m53s
Test / Hakurei (race detector) (push) Successful in 6m12s
Test / Flake checks (push) Successful in 1m31s
These are all trusted user input, however this check reduces the likelihood of hard to debug errors.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-10 20:31:26 +09:00
bb92e3ada9
cmd/hakurei: expose current instance identifier
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m25s
Test / Hakurei (push) Successful in 4m36s
Test / Sandbox (race detector) (push) Successful in 4m31s
Test / Hpkg (push) Successful in 4m52s
Test / Hakurei (race detector) (push) Successful in 6m4s
Test / Flake checks (push) Successful in 1m24s
This writes the 16-byte instance identifier to file descriptor specified by --identifier-fd if set, and closes the file.

This enables safely obtaining the new instance's identifier.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-10 07:52:35 +09:00
fad419c2a2
internal/outcome: handle group lookup message
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m37s
Test / Sandbox (race detector) (push) Successful in 4m37s
Test / Hpkg (push) Successful in 5m1s
Test / Hakurei (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m35s
This results in slightly less messy error reporting.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-09 02:15:48 +09:00
b1a1e73238
nix: update names to reflect new terminology
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 40s
Test / Sandbox (race detector) (push) Successful in 39s
Test / Hakurei (race detector) (push) Successful in 44s
Test / Hakurei (push) Successful in 46s
Test / Hpkg (push) Successful in 41s
Test / Flake checks (push) Successful in 1m30s
These are terminology from way early days. Update them now to be less confusing.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-09 01:48:31 +09:00
38e9128a8c
container/std/seccomp: remove ineffectual typecast
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m17s
Test / Hakurei (push) Successful in 3m9s
Test / Hpkg (push) Successful in 4m6s
Test / Sandbox (race detector) (push) Successful in 4m11s
Test / Hakurei (race detector) (push) Successful in 5m1s
Test / Flake checks (push) Successful in 1m26s
This is no longer necessary since the return type changed.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-07 05:45:51 +09:00
7ee702a44e
container/seccomp/presets: add fields to literals
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m11s
Test / Hakurei (push) Successful in 3m15s
Test / Hpkg (push) Successful in 4m2s
Test / Sandbox (race detector) (push) Successful in 4m10s
Test / Hakurei (race detector) (push) Successful in 5m2s
Test / Flake checks (push) Successful in 1m26s
This keeps composites analysis happy.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-07 05:11:57 +09:00
3d188ef884
std: separate seccomp constants
All checks were successful
Test / Create distribution (push) Successful in 39s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m26s
Test / Sandbox (race detector) (push) Successful in 4m13s
Test / Hpkg (push) Successful in 4m12s
Test / Hakurei (race detector) (push) Successful in 5m9s
Test / Flake checks (push) Successful in 1m28s
This avoids inadvertently using PNRs as syscall numbers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2025-11-07 04:30:06 +09:00
162 changed files with 4999 additions and 2569 deletions

2
.clang-format Normal file
View File

@ -0,0 +1,2 @@
ColumnLimit: 0
IndentWidth: 4

View File

@ -11,21 +11,24 @@ import (
"strconv"
"sync"
"time"
_ "unsafe"
_ "unsafe" // for go:linkname
"hakurei.app/command"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/internal/dbus"
"hakurei.app/internal/env"
"hakurei.app/internal/info"
"hakurei.app/internal/outcome"
"hakurei.app/message"
"hakurei.app/system/dbus"
)
// optionalErrorUnwrap calls [errors.Unwrap] and returns the resulting value
// if it is not nil, or the original value if it is.
//
//go:linkname optionalErrorUnwrap hakurei.app/container.optionalErrorUnwrap
func optionalErrorUnwrap(_ error) error
func optionalErrorUnwrap(err error) error
func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErrs, out io.Writer) command.Command {
var (
@ -52,20 +55,26 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
c.Command("shim", command.UsageInternal, func([]string) error { outcome.Shim(msg); return errSuccess })
c.Command("app", "Load and start container from configuration file", func(args []string) error {
{
var (
flagIdentifierFile int
)
c.NewCommand("app", "Load and start container from configuration file", func(args []string) error {
if len(args) < 1 {
log.Fatal("app requires at least 1 argument")
}
// config extraArgs...
config := tryPath(msg, args[0])
if config != nil && config.Container != nil {
config.Container.Args = append(config.Container.Args, args[1:]...)
}
outcome.Main(ctx, msg, config)
outcome.Main(ctx, msg, config, flagIdentifierFile)
panic("unreachable")
})
}).
Flag(&flagIdentifierFile, "identifier-fd", command.IntFlag(-1),
"Write identifier of current instance to fd after successful startup")
}
{
var (
@ -257,7 +266,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
}
}
outcome.Main(ctx, msg, config)
outcome.Main(ctx, msg, config, -1)
panic("unreachable")
}).
Flag(&flagDBusConfigSession, "dbus-config", command.StringFlag("builtin"),
@ -344,7 +353,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
}).Flag(&flagShort, "short", command.BoolFlag(false), "Print instance id")
}
c.Command("version", "Display version information", func(args []string) error { fmt.Println(internal.Version()); return errSuccess })
c.Command("version", "Display version information", func(args []string) error { fmt.Println(info.Version()); return errSuccess })
c.Command("license", "Show full license text", func(args []string) error { fmt.Println(license); return errSuccess })
c.Command("template", "Produce a config template", func(args []string) error { encodeJSON(log.Fatal, os.Stdout, false, hst.Template()); return errSuccess })
c.Command("help", "Show this help message", func([]string) error { c.PrintHelp(); return errSuccess })

View File

@ -1,18 +1,13 @@
package main_test
package main
import (
"io"
"reflect"
"strings"
"testing"
_ "unsafe"
"hakurei.app/container/stub"
)
//go:linkname decodeJSON hakurei.app/cmd/hakurei.decodeJSON
func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any)
func TestDecodeJSON(t *testing.T) {
t.Parallel()
@ -62,9 +57,6 @@ func TestDecodeJSON(t *testing.T) {
}
}
//go:linkname encodeJSON hakurei.app/cmd/hakurei.encodeJSON
func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any)
func TestEncodeJSON(t *testing.T) {
t.Parallel()
@ -74,7 +66,7 @@ func TestEncodeJSON(t *testing.T) {
want string
}{
{"marshaler", errorJSONMarshaler{},
`cannot encode json for main_test.errorJSONMarshaler: unique error 3735928559 injected by the test suite`},
`cannot encode json for main.errorJSONMarshaler: unique error 3735928559 injected by the test suite`},
{"default", func() {},
`cannot write json: json: unsupported type: func()`},
}

View File

@ -11,6 +11,7 @@ import (
"syscall"
"hakurei.app/hst"
"hakurei.app/internal/outcome"
"hakurei.app/internal/store"
"hakurei.app/message"
)
@ -53,14 +54,23 @@ func tryFd(msg message.Msg, name string) io.ReadCloser {
}
return nil
} else {
if v < 3 { // reject standard streams
return nil
}
msg.Verbosef("trying config stream from %d", v)
fd := uintptr(v)
if _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, fd, syscall.F_GETFD, 0); errno != 0 {
if errors.Is(errno, syscall.EBADF) {
if errors.Is(errno, syscall.EBADF) { // reject bad fd
return nil
}
log.Fatalf("cannot get fd %d: %v", fd, errno)
}
if outcome.IsPollDescriptor(fd) { // reject runtime internals
log.Fatalf("invalid config stream %d", fd)
}
return os.NewFile(fd, strconv.Itoa(v))
}
}

View File

@ -12,8 +12,8 @@ import (
"time"
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/internal/env"
"hakurei.app/internal/info"
"hakurei.app/internal/outcome"
"hakurei.app/internal/store"
"hakurei.app/message"
@ -24,20 +24,20 @@ func printShowSystem(output io.Writer, short, flagJSON bool) {
t := newPrinter(output)
defer t.MustFlush()
info := &hst.Info{Version: internal.Version(), User: new(outcome.Hsu).MustID(nil)}
env.CopyPaths().Copy(&info.Paths, info.User)
hi := &hst.Info{Version: info.Version(), User: new(outcome.Hsu).MustID(nil)}
env.CopyPaths().Copy(&hi.Paths, hi.User)
if flagJSON {
encodeJSON(log.Fatal, output, short, info)
encodeJSON(log.Fatal, output, short, hi)
return
}
t.Printf("Version:\t%s\n", info.Version)
t.Printf("User:\t%d\n", info.User)
t.Printf("TempDir:\t%s\n", info.TempDir)
t.Printf("SharePath:\t%s\n", info.SharePath)
t.Printf("RuntimePath:\t%s\n", info.RuntimePath)
t.Printf("RunDirPath:\t%s\n", info.RunDirPath)
t.Printf("Version:\t%s\n", hi.Version)
t.Printf("User:\t%d\n", hi.User)
t.Printf("TempDir:\t%s\n", hi.TempDir)
t.Printf("SharePath:\t%s\n", hi.SharePath)
t.Printf("RuntimePath:\t%s\n", hi.RuntimePath)
t.Printf("RunDirPath:\t%s\n", hi.RunDirPath)
}
// printShowInstance writes a representation of [hst.State] or [hst.Config] to output.
@ -90,12 +90,6 @@ func printShowInstance(
t.Printf(" Groups:\t%s\n", strings.Join(config.Groups, ", "))
}
if config.Container != nil {
if config.Container.Home != nil {
t.Printf(" Home:\t%s\n", config.Container.Home)
}
if config.Container.Hostname != "" {
t.Printf(" Hostname:\t%s\n", config.Container.Hostname)
}
flags := config.Container.Flags.String()
// this is included in the upper hst.Config struct but is relevant here
@ -110,6 +104,12 @@ func printShowInstance(
}
t.Printf(" Flags:\t%s\n", flags)
if config.Container.Home != nil {
t.Printf(" Home:\t%s\n", config.Container.Home)
}
if config.Container.Hostname != "" {
t.Printf(" Hostname:\t%s\n", config.Container.Hostname)
}
if config.Container.Path != nil {
t.Printf(" Path:\t%s\n", config.Container.Path)
}

View File

@ -64,9 +64,9 @@ func TestPrintShowInstance(t *testing.T) {
Identity: 9 (org.chromium.Chromium)
Enablements: wayland, dbus, pulseaudio
Groups: video, dialout, plugdev
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir
Home: /data/data/org.chromium.Chromium
Hostname: localhost
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir
Path: /run/current-system/sw/bin/chromium
Arguments: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
@ -161,9 +161,9 @@ App
Identity: 9 (org.chromium.Chromium)
Enablements: wayland, dbus, pulseaudio
Groups: video, dialout, plugdev
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir
Home: /data/data/org.chromium.Chromium
Hostname: localhost
Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir
Path: /run/current-system/sw/bin/chromium
Arguments: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland

View File

@ -10,11 +10,11 @@ import (
"os/exec"
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/internal/info"
"hakurei.app/message"
)
var hakureiPathVal = internal.MustHakureiPath().String()
var hakureiPathVal = info.MustHakureiPath().String()
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
var (

View File

@ -56,7 +56,7 @@ func NewAbs(pathname string) (*Absolute, error) {
// MustAbs calls [NewAbs] and panics on error.
func MustAbs(pathname string) *Absolute {
if a, err := NewAbs(pathname); err != nil {
panic(err.Error())
panic(err)
} else {
return a
}

View File

@ -9,13 +9,15 @@ import (
"strings"
"syscall"
"testing"
_ "unsafe"
_ "unsafe" // for go:linkname
. "hakurei.app/container/check"
)
// unsafeAbs returns check.Absolute on any string value.
//
//go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs
func unsafeAbs(_ string) *Absolute
func unsafeAbs(pathname string) *Absolute
func TestAbsoluteError(t *testing.T) {
t.Parallel()
@ -82,9 +84,9 @@ func TestNewAbs(t *testing.T) {
t.Parallel()
defer func() {
wantPanic := `path "etc" is not absolute`
wantPanic := &AbsoluteError{Pathname: "etc"}
if r := recover(); r != wantPanic {
if r := recover(); !reflect.DeepEqual(r, wantPanic) {
t.Errorf("MustAbs: panic = %v; want %v", r, wantPanic)
}
}()

View File

@ -11,6 +11,7 @@ import (
"os/exec"
"runtime"
"strconv"
"sync"
. "syscall"
"time"
@ -143,11 +144,18 @@ func (e *StartError) Error() string {
// Message returns a user-facing error message.
func (e *StartError) Message() string {
if e.Passthrough {
var (
numError *strconv.NumError
)
switch {
case errors.As(e.Err, new(*os.PathError)),
errors.As(e.Err, new(*os.SyscallError)):
return "cannot " + e.Err.Error()
case errors.As(e.Err, &numError) && numError != nil:
return "cannot parse " + strconv.Quote(numError.Num) + ": " + numError.Err.Error()
default:
return e.Err.Error()
}
@ -158,6 +166,39 @@ func (e *StartError) Message() string {
return "cannot " + e.Error()
}
// for ensureCloseOnExec
var (
closeOnExecOnce sync.Once
closeOnExecErr error
)
// ensureCloseOnExec ensures all currently open file descriptors have the syscall.FD_CLOEXEC flag set.
// This is only ran once as it is intended to handle files left open by the parent, and any file opened
// on this side should already have syscall.FD_CLOEXEC set.
func ensureCloseOnExec() error {
closeOnExecOnce.Do(func() {
const fdPrefixPath = "/proc/self/fd/"
var entries []os.DirEntry
if entries, closeOnExecErr = os.ReadDir(fdPrefixPath); closeOnExecErr != nil {
return
}
var fd int
for _, ent := range entries {
if fd, closeOnExecErr = strconv.Atoi(ent.Name()); closeOnExecErr != nil {
break // not reached
}
CloseOnExec(fd)
}
})
if closeOnExecErr == nil {
return nil
}
return &StartError{Fatal: true, Step: "set FD_CLOEXEC on all open files", Err: closeOnExecErr, Passthrough: true}
}
// Start starts the container init. The init process blocks until Serve is called.
func (p *Container) Start() error {
if p == nil || p.cmd == nil ||
@ -168,6 +209,10 @@ func (p *Container) Start() error {
return errors.New("container: already started")
}
if err := ensureCloseOnExec(); err != nil {
return err
}
// map to overflow id to work around ownership checks
if p.Uid < 1 {
p.Uid = OverflowUid(p.msg)

View File

@ -21,6 +21,7 @@ import (
"hakurei.app/command"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/container/vfs"
@ -29,6 +30,45 @@ import (
"hakurei.app/message"
)
// Note: this package requires cgo, which is unavailable in the Go playground.
func Example() {
// Must be called early if the current process starts containers.
container.TryArgv0(nil)
// Configure the container.
z := container.New(context.Background(), nil)
z.Hostname = "hakurei-example"
z.Proc(fhs.AbsProc).Dev(fhs.AbsDev, true)
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
// Bind / for demonstration.
z.Bind(fhs.AbsRoot, fhs.AbsRoot, 0)
if name, err := exec.LookPath("hostname"); err != nil {
panic(err)
} else {
z.Path = check.MustAbs(name)
}
// This completes the first stage of container setup and starts the container init process.
// The new process blocks until the Serve method is called.
if err := z.Start(); err != nil {
panic(err)
}
// This serves the setup payload to the container init process,
// starting the second stage of container setup.
if err := z.Serve(); err != nil {
panic(err)
}
// Must be called if the Start method succeeds.
if err := z.Wait(); err != nil {
panic(err)
}
// Output: hakurei-example
}
func TestStartError(t *testing.T) {
t.Parallel()
@ -44,8 +84,7 @@ func TestStartError(t *testing.T) {
Fatal: true,
Step: "set up params stream",
Err: container.ErrReceiveEnv,
},
"set up params stream: environment variable not set",
}, "set up params stream: environment variable not set",
container.ErrReceiveEnv, syscall.EBADF,
"cannot set up params stream: environment variable not set"},
@ -53,8 +92,7 @@ func TestStartError(t *testing.T) {
Fatal: true,
Step: "set up params stream",
Err: &os.SyscallError{Syscall: "pipe2", Err: syscall.EBADF},
},
"set up params stream pipe2: bad file descriptor",
}, "set up params stream pipe2: bad file descriptor",
syscall.EBADF, os.ErrInvalid,
"cannot set up params stream pipe2: bad file descriptor"},
@ -62,16 +100,14 @@ func TestStartError(t *testing.T) {
Fatal: true,
Step: "prctl(PR_SET_NO_NEW_PRIVS)",
Err: syscall.EPERM,
},
"prctl(PR_SET_NO_NEW_PRIVS): operation not permitted",
}, "prctl(PR_SET_NO_NEW_PRIVS): operation not permitted",
syscall.EPERM, syscall.EACCES,
"cannot prctl(PR_SET_NO_NEW_PRIVS): operation not permitted"},
{"landlock abi", &container.StartError{
Step: "get landlock ABI",
Err: syscall.ENOSYS,
},
"get landlock ABI: function not implemented",
}, "get landlock ABI: function not implemented",
syscall.ENOSYS, syscall.ENOEXEC,
"cannot get landlock ABI: function not implemented"},
@ -79,8 +115,7 @@ func TestStartError(t *testing.T) {
Step: "kernel version too old for LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET",
Err: syscall.ENOSYS,
Origin: true,
},
"kernel version too old for LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET",
}, "kernel version too old for LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET",
syscall.ENOSYS, syscall.ENOSPC,
"kernel version too old for LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET"},
@ -88,8 +123,7 @@ func TestStartError(t *testing.T) {
Fatal: true,
Step: "create landlock ruleset",
Err: syscall.EBADFD,
},
"create landlock ruleset: file descriptor in bad state",
}, "create landlock ruleset: file descriptor in bad state",
syscall.EBADFD, syscall.EBADF,
"cannot create landlock ruleset: file descriptor in bad state"},
@ -97,8 +131,7 @@ func TestStartError(t *testing.T) {
Fatal: true,
Step: "enforce landlock ruleset",
Err: syscall.ENOTRECOVERABLE,
},
"enforce landlock ruleset: state not recoverable",
}, "enforce landlock ruleset: state not recoverable",
syscall.ENOTRECOVERABLE, syscall.ETIMEDOUT,
"cannot enforce landlock ruleset: state not recoverable"},
@ -109,8 +142,7 @@ func TestStartError(t *testing.T) {
Path: "/proc/nonexistent",
Err: syscall.ENOENT,
}, Passthrough: true,
},
"fork/exec /proc/nonexistent: no such file or directory",
}, "fork/exec /proc/nonexistent: no such file or directory",
syscall.ENOENT, syscall.ENOSYS,
"cannot fork/exec /proc/nonexistent: no such file or directory"},
@ -120,11 +152,19 @@ func TestStartError(t *testing.T) {
Syscall: "open",
Err: syscall.ENOSYS,
}, Passthrough: true,
},
"open: function not implemented",
}, "open: function not implemented",
syscall.ENOSYS, syscall.ENOENT,
"cannot open: function not implemented"},
{"start FD_CLOEXEC", &container.StartError{
Fatal: true,
Step: "set FD_CLOEXEC on all open files",
Err: func() error { _, err := strconv.Atoi("invalid"); return err }(),
Passthrough: true,
}, `strconv.Atoi: parsing "invalid": invalid syntax`,
strconv.ErrSyntax, os.ErrInvalid,
`cannot parse "invalid": invalid syntax`},
{"start other", &container.StartError{
Step: "start container init",
Err: &net.OpError{
@ -132,8 +172,7 @@ func TestStartError(t *testing.T) {
Net: "unix",
Err: syscall.ECONNREFUSED,
}, Passthrough: true,
},
"dial unix: connection refused",
}, "dial unix: connection refused",
syscall.ECONNREFUSED, syscall.ECONNABORTED,
"dial unix: connection refused"},
}
@ -722,12 +761,15 @@ func TestMain(m *testing.M) {
func helperNewContainerLibPaths(ctx context.Context, libPaths *[]*check.Absolute, args ...string) (c *container.Container) {
msg := message.New(nil)
msg.SwapVerbose(testing.Verbose())
executable := check.MustAbs(container.MustExecutable(msg))
c = container.NewCommand(ctx, msg, absHelperInnerPath, "helper", args...)
c.Env = append(c.Env, envDoCheck+"=1")
c.Bind(check.MustAbs(os.Args[0]), absHelperInnerPath, 0)
c.Bind(executable, absHelperInnerPath, 0)
// in case test has cgo enabled
if entries, err := ldd.Exec(ctx, msg, os.Args[0]); err != nil {
if entries, err := ldd.Resolve(ctx, msg, executable); err != nil {
log.Fatalf("ldd: %v", err)
} else {
*libPaths = ldd.Path(entries)

View File

@ -1,15 +1,17 @@
package fhs
import (
_ "unsafe"
_ "unsafe" // for go:linkname
"hakurei.app/container/check"
)
/* constants in this file bypass abs check, be extremely careful when changing them! */
// unsafeAbs returns check.Absolute on any string value.
//
//go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs
func unsafeAbs(_ string) *check.Absolute
func unsafeAbs(pathname string) *check.Absolute
var (
// AbsRoot is [Root] as [check.Absolute].
@ -34,6 +36,8 @@ var (
// AbsDev is [Dev] as [check.Absolute].
AbsDev = unsafeAbs(Dev)
// AbsDevShm is [DevShm] as [check.Absolute].
AbsDevShm = unsafeAbs(DevShm)
// AbsProc is [Proc] as [check.Absolute].
AbsProc = unsafeAbs(Proc)
// AbsSys is [Sys] as [check.Absolute].

View File

@ -29,6 +29,8 @@ const (
// Dev points to the root directory for device nodes.
Dev = "/dev/"
// DevShm is the place for POSIX shared memory segments, as created via shm_open(3).
DevShm = "/dev/shm/"
// Proc points to a virtual kernel file system exposing the process list and other functionality.
Proc = "/proc/"
// ProcSys points to a hierarchy below /proc/ that exposes a number of kernel tunables.

View File

@ -330,6 +330,10 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
}
k.umask(oldmask)
if err := closeSetup(); err != nil {
k.fatalf(msg, "cannot close setup pipe: %v", err)
}
cmd := exec.Command(params.Path.String())
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
cmd.Args = params.Args
@ -342,11 +346,6 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
k.fatalf(msg, "%v", err)
}
if err := closeSetup(); err != nil {
k.printf(msg, "cannot close setup pipe: %v", err)
// not fatal
}
type winfo struct {
wpid int
wstatus WaitStatus
@ -427,6 +426,16 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
}
if w.wpid == cmd.Process.Pid {
// start timeout early
go func() { time.Sleep(params.AdoptWaitDelay); close(timeout) }()
// close initial process files; this also keeps them alive
for _, f := range extraFiles {
if err := f.Close(); err != nil {
msg.Verbose(err.Error())
}
}
switch {
case w.wstatus.Exited():
r = w.wstatus.ExitStatus()
@ -440,8 +449,6 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
r = 255
msg.Verbosef("initial process exited with status %#x", w.wstatus)
}
go func() { time.Sleep(params.AdoptWaitDelay); close(timeout) }()
}
case <-timeout:

View File

@ -1983,6 +1983,7 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(13)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, nil, stub.UniqueError(12)),
call("fatalf", stub.ExpectArgs{"%v", []any{stub.UniqueError(12)}}, nil, nil),
@ -2061,15 +2062,17 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(10)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(10)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- CancelSignal }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{"forwarding context cancellation"}}, nil, nil),
// magicWait4Signal as ret causes wait4 stub to unblock
call("signal", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent", os.Interrupt}, magicWait4Signal, stub.UniqueError(9)),
call("printf", stub.ExpectArgs{"cannot forward cancellation: %v", []any{stub.UniqueError(9)}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil),
call("printf", stub.ExpectArgs{"timeout exceeded waiting for lingering processes", ([]any)(nil)}, nil, nil),
call("beforeExit", stub.ExpectArgs{}, nil, nil),
@ -2159,15 +2162,17 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- syscall.SIGQUIT }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbosef", stub.ExpectArgs{"got %s, forwarding to initial process", []any{"quit"}}, nil, nil),
// magicWait4Signal as ret causes wait4 stub to unblock
call("signal", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent", syscall.SIGQUIT}, magicWait4Signal, stub.UniqueError(0xfe)),
call("printf", stub.ExpectArgs{"cannot forward signal: %v", []any{stub.UniqueError(0xfe)}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil),
call("printf", stub.ExpectArgs{"timeout exceeded waiting for lingering processes", []any(nil)}, nil, nil),
call("beforeExit", stub.ExpectArgs{}, nil, nil),
@ -2257,9 +2262,9 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- os.Interrupt }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbosef", stub.ExpectArgs{"got %s", []any{"interrupt"}}, nil, nil),
@ -2348,11 +2353,13 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(5)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(5)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil),
call("printf", stub.ExpectArgs{"timeout exceeded waiting for lingering processes", ([]any)(nil)}, nil, nil),
call("beforeExit", stub.ExpectArgs{}, nil, nil),
@ -2441,11 +2448,13 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(3)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(3)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil),
call("beforeExit", stub.ExpectArgs{}, nil, nil),
call("exit", stub.ExpectArgs{0xce}, nil, nil),
@ -2577,11 +2586,13 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(1)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil),
call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(1)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbosef", stub.ExpectArgs{"initial process exited with code %d", []any{1}}, nil, nil),
call("beforeExit", stub.ExpectArgs{}, nil, nil),
call("exit", stub.ExpectArgs{1}, nil, nil),
@ -2717,11 +2728,14 @@ func TestInitEntrypoint(t *testing.T) {
call("newFile", stub.ExpectArgs{uintptr(11), "extra file 1"}, (*os.File)(nil), nil),
call("newFile", stub.ExpectArgs{uintptr(12), "extra file 2"}, (*os.File)(nil), nil),
call("umask", stub.ExpectArgs{022}, 0, nil),
call("fatalf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(0)}}, nil, nil),
call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/bin/zsh")}}, nil, nil),
call("start", stub.ExpectArgs{"/bin/zsh", []string{"zsh", "-c", "exec vim"}, []string{"DISPLAY=:0"}, "/.hakurei"}, &os.Process{Pid: 0xcafe}, nil),
call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(0)}}, nil, nil),
call("New", stub.ExpectArgs{}, nil, nil),
call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbose", stub.ExpectArgs{[]any{os.ErrInvalid.Error()}}, nil, nil),
call("verbosef", stub.ExpectArgs{"initial process exited with status %#x", []any{syscall.WaitStatus(0xfade007f)}}, nil, nil),
call("beforeExit", stub.ExpectArgs{}, nil, nil),
call("exit", stub.ExpectArgs{0xff}, nil, nil),

View File

@ -9,7 +9,8 @@
#define LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
int32_t hakurei_scmp_make_filter(int *ret_p, uintptr_t allocate_p,
int32_t hakurei_scmp_make_filter(
int *ret_p, uintptr_t allocate_p,
uint32_t arch, uint32_t multiarch,
struct hakurei_syscall_rule *rules,
size_t rules_sz, hakurei_export_flag flags) {
@ -72,11 +73,9 @@ int32_t hakurei_scmp_make_filter(int *ret_p, uintptr_t allocate_p,
assert(rule->m_errno == EPERM || rule->m_errno == ENOSYS);
if (rule->arg)
*ret_p = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(rule->m_errno),
rule->syscall, 1, *rule->arg);
*ret_p = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(rule->m_errno), rule->syscall, 1, *rule->arg);
else
*ret_p = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(rule->m_errno),
rule->syscall, 0);
*ret_p = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(rule->m_errno), rule->syscall, 0);
if (*ret_p == -EFAULT) {
res = 4;
@ -93,22 +92,17 @@ int32_t hakurei_scmp_make_filter(int *ret_p, uintptr_t allocate_p,
last_allowed_family = -1;
for (i = 0; i < LEN(socket_family_allowlist); i++) {
if (socket_family_allowlist[i].flags_mask != 0 &&
(socket_family_allowlist[i].flags_mask & flags) !=
socket_family_allowlist[i].flags_mask)
(socket_family_allowlist[i].flags_mask & flags) != socket_family_allowlist[i].flags_mask)
continue;
for (disallowed = last_allowed_family + 1;
disallowed < socket_family_allowlist[i].family; disallowed++) {
for (disallowed = last_allowed_family + 1; disallowed < socket_family_allowlist[i].family; disallowed++) {
/* Blocklist the in-between valid families */
seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EAFNOSUPPORT),
SCMP_SYS(socket), 1,
SCMP_A0(SCMP_CMP_EQ, disallowed));
seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, disallowed));
}
last_allowed_family = socket_family_allowlist[i].family;
}
/* Blocklist the rest */
seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1,
SCMP_A0(SCMP_CMP_GE, last_allowed_family + 1));
seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_GE, last_allowed_family + 1));
if (allocate_p == 0) {
*ret_p = seccomp_load(ctx);

View File

@ -19,7 +19,8 @@ struct hakurei_syscall_rule {
};
extern void *hakurei_scmp_allocate(uintptr_t f, size_t len);
int32_t hakurei_scmp_make_filter(int *ret_p, uintptr_t allocate_p,
int32_t hakurei_scmp_make_filter(
int *ret_p, uintptr_t allocate_p,
uint32_t arch, uint32_t multiarch,
struct hakurei_syscall_rule *rules,
size_t rules_sz, hakurei_export_flag flags);

View File

@ -215,10 +215,10 @@ const (
// syscallResolveName resolves a syscall number by name via seccomp_syscall_resolve_name.
// This function is only for testing the lookup tables and included here for convenience.
func syscallResolveName(s string) (trap int, ok bool) {
func syscallResolveName(s string) (num std.ScmpSyscall, ok bool) {
v := C.CString(s)
trap = int(C.seccomp_syscall_resolve_name(v))
num = std.ScmpSyscall(C.seccomp_syscall_resolve_name(v))
C.free(unsafe.Pointer(v))
ok = trap != C.__NR_SCMP_ERROR
ok = num != C.__NR_SCMP_ERROR
return
}

View File

@ -68,121 +68,121 @@ func Preset(presets FilterPreset, flags ExportFlag) (rules []NativeRule) {
var (
presetCommon = []NativeRule{
/* Block dmesg */
{ScmpSyscall(SYS_SYSLOG), ScmpErrno(EPERM), nil},
{Syscall: SNR_SYSLOG, Errno: ScmpErrno(EPERM), Arg: nil},
/* Useless old syscall */
{ScmpSyscall(SYS_USELIB), ScmpErrno(EPERM), nil},
{Syscall: SNR_USELIB, Errno: ScmpErrno(EPERM), Arg: nil},
/* Don't allow disabling accounting */
{ScmpSyscall(SYS_ACCT), ScmpErrno(EPERM), nil},
{Syscall: SNR_ACCT, Errno: ScmpErrno(EPERM), Arg: nil},
/* Don't allow reading current quota use */
{ScmpSyscall(SYS_QUOTACTL), ScmpErrno(EPERM), nil},
{Syscall: SNR_QUOTACTL, Errno: ScmpErrno(EPERM), Arg: nil},
/* Don't allow access to the kernel keyring */
{ScmpSyscall(SYS_ADD_KEY), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_KEYCTL), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_REQUEST_KEY), ScmpErrno(EPERM), nil},
{Syscall: SNR_ADD_KEY, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_KEYCTL, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_REQUEST_KEY, Errno: ScmpErrno(EPERM), Arg: nil},
/* Scary VM/NUMA ops */
{ScmpSyscall(SYS_MOVE_PAGES), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_MBIND), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_GET_MEMPOLICY), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SET_MEMPOLICY), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_MIGRATE_PAGES), ScmpErrno(EPERM), nil},
{Syscall: SNR_MOVE_PAGES, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_MBIND, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_GET_MEMPOLICY, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SET_MEMPOLICY, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_MIGRATE_PAGES, Errno: ScmpErrno(EPERM), Arg: nil},
}
/* hakurei: project-specific extensions */
presetCommonExt = []NativeRule{
/* system calls for changing the system clock */
{ScmpSyscall(SYS_ADJTIMEX), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CLOCK_ADJTIME), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CLOCK_ADJTIME64), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CLOCK_SETTIME), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CLOCK_SETTIME64), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETTIMEOFDAY), ScmpErrno(EPERM), nil},
{Syscall: SNR_ADJTIMEX, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CLOCK_ADJTIME, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CLOCK_ADJTIME64, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CLOCK_SETTIME, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CLOCK_SETTIME64, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETTIMEOFDAY, Errno: ScmpErrno(EPERM), Arg: nil},
/* loading and unloading of kernel modules */
{ScmpSyscall(SYS_DELETE_MODULE), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_FINIT_MODULE), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_INIT_MODULE), ScmpErrno(EPERM), nil},
{Syscall: SNR_DELETE_MODULE, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_FINIT_MODULE, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_INIT_MODULE, Errno: ScmpErrno(EPERM), Arg: nil},
/* system calls for rebooting and reboot preparation */
{ScmpSyscall(SYS_KEXEC_FILE_LOAD), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_KEXEC_LOAD), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_REBOOT), ScmpErrno(EPERM), nil},
{Syscall: SNR_KEXEC_FILE_LOAD, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_KEXEC_LOAD, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_REBOOT, Errno: ScmpErrno(EPERM), Arg: nil},
/* system calls for enabling/disabling swap devices */
{ScmpSyscall(SYS_SWAPOFF), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SWAPON), ScmpErrno(EPERM), nil},
{Syscall: SNR_SWAPOFF, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SWAPON, Errno: ScmpErrno(EPERM), Arg: nil},
}
presetNamespace = []NativeRule{
/* Don't allow subnamespace setups: */
{ScmpSyscall(SYS_UNSHARE), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETNS), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_MOUNT), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_UMOUNT), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_UMOUNT2), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_PIVOT_ROOT), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CHROOT), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CLONE), ScmpErrno(EPERM),
&ScmpArgCmp{cloneArg, SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER}},
{Syscall: SNR_UNSHARE, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETNS, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_MOUNT, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_UMOUNT, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_UMOUNT2, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_PIVOT_ROOT, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CHROOT, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CLONE, Errno: ScmpErrno(EPERM),
Arg: &ScmpArgCmp{Arg: cloneArg, Op: SCMP_CMP_MASKED_EQ, DatumA: CLONE_NEWUSER, DatumB: CLONE_NEWUSER}},
/* seccomp can't look into clone3()'s struct clone_args to check whether
* the flags are OK, so we have no choice but to block clone3().
* Return ENOSYS so user-space will fall back to clone().
* (CVE-2021-41133; see also https://github.com/moby/moby/commit/9f6b562d)
*/
{ScmpSyscall(SYS_CLONE3), ScmpErrno(ENOSYS), nil},
{Syscall: SNR_CLONE3, Errno: ScmpErrno(ENOSYS), Arg: nil},
/* New mount manipulation APIs can also change our VFS. There's no
* legitimate reason to do these in the sandbox, so block all of them
* rather than thinking about which ones might be dangerous.
* (CVE-2021-41133) */
{ScmpSyscall(SYS_OPEN_TREE), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_MOVE_MOUNT), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_FSOPEN), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_FSCONFIG), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_FSMOUNT), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_FSPICK), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_MOUNT_SETATTR), ScmpErrno(ENOSYS), nil},
{Syscall: SNR_OPEN_TREE, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_MOVE_MOUNT, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_FSOPEN, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_FSCONFIG, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_FSMOUNT, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_FSPICK, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_MOUNT_SETATTR, Errno: ScmpErrno(ENOSYS), Arg: nil},
}
/* hakurei: project-specific extensions */
presetNamespaceExt = []NativeRule{
/* changing file ownership */
{ScmpSyscall(SYS_CHOWN), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_CHOWN32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_FCHOWN), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_FCHOWN32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_FCHOWNAT), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_LCHOWN), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_LCHOWN32), ScmpErrno(EPERM), nil},
{Syscall: SNR_CHOWN, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_CHOWN32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_FCHOWN, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_FCHOWN32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_FCHOWNAT, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_LCHOWN, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_LCHOWN32, Errno: ScmpErrno(EPERM), Arg: nil},
/* system calls for changing user ID and group ID credentials */
{ScmpSyscall(SYS_SETGID), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETGID32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETGROUPS), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETGROUPS32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETREGID), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETREGID32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETRESGID), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETRESGID32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETRESUID), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETRESUID32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETREUID), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETREUID32), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETUID), ScmpErrno(EPERM), nil},
{ScmpSyscall(SYS_SETUID32), ScmpErrno(EPERM), nil},
{Syscall: SNR_SETGID, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETGID32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETGROUPS, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETGROUPS32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETREGID, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETREGID32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETRESGID, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETRESGID32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETRESUID, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETRESUID32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETREUID, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETREUID32, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETUID, Errno: ScmpErrno(EPERM), Arg: nil},
{Syscall: SNR_SETUID32, Errno: ScmpErrno(EPERM), Arg: nil},
}
presetTTY = []NativeRule{
/* Don't allow faking input to the controlling tty (CVE-2017-5226) */
{ScmpSyscall(SYS_IOCTL), ScmpErrno(EPERM),
&ScmpArgCmp{1, SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, TIOCSTI}},
{Syscall: SNR_IOCTL, Errno: ScmpErrno(EPERM),
Arg: &ScmpArgCmp{Arg: 1, Op: SCMP_CMP_MASKED_EQ, DatumA: 0xFFFFFFFF, DatumB: TIOCSTI}},
/* In the unlikely event that the controlling tty is a Linux virtual
* console (/dev/tty2 or similar), copy/paste operations have an effect
* similar to TIOCSTI (CVE-2023-28100) */
{ScmpSyscall(SYS_IOCTL), ScmpErrno(EPERM),
&ScmpArgCmp{1, SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, TIOCLINUX}},
{Syscall: SNR_IOCTL, Errno: ScmpErrno(EPERM),
Arg: &ScmpArgCmp{Arg: 1, Op: SCMP_CMP_MASKED_EQ, DatumA: 0xFFFFFFFF, DatumB: TIOCLINUX}},
}
presetEmu = []NativeRule{
@ -190,15 +190,15 @@ var (
* so it's disabled as a hardening measure.
* However, it is required to run old 16-bit applications
* as well as some Wine patches, so it's allowed in multiarch. */
{ScmpSyscall(SYS_MODIFY_LDT), ScmpErrno(EPERM), nil},
{Syscall: SNR_MODIFY_LDT, Errno: ScmpErrno(EPERM), Arg: nil},
}
/* hakurei: project-specific extensions */
presetEmuExt = []NativeRule{
{ScmpSyscall(SYS_SUBPAGE_PROT), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_SWITCH_ENDIAN), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_VM86), ScmpErrno(ENOSYS), nil},
{ScmpSyscall(SYS_VM86OLD), ScmpErrno(ENOSYS), nil},
{Syscall: SNR_SUBPAGE_PROT, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_SWITCH_ENDIAN, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_VM86, Errno: ScmpErrno(ENOSYS), Arg: nil},
{Syscall: SNR_VM86OLD, Errno: ScmpErrno(ENOSYS), Arg: nil},
}
)
@ -206,11 +206,11 @@ func presetDevel(allowedPersonality ScmpDatum) []NativeRule {
return []NativeRule{
/* Profiling operations; we expect these to be done by tools from outside
* the sandbox. In particular perf has been the source of many CVEs. */
{ScmpSyscall(SYS_PERF_EVENT_OPEN), ScmpErrno(EPERM), nil},
{Syscall: SNR_PERF_EVENT_OPEN, Errno: ScmpErrno(EPERM), Arg: nil},
/* Don't allow you to switch to bsd emulation or whatnot */
{ScmpSyscall(SYS_PERSONALITY), ScmpErrno(EPERM),
&ScmpArgCmp{0, SCMP_CMP_NE, allowedPersonality, 0}},
{Syscall: SNR_PERSONALITY, Errno: ScmpErrno(EPERM),
Arg: &ScmpArgCmp{Arg: 0, Op: SCMP_CMP_NE, DatumA: allowedPersonality}},
{ScmpSyscall(SYS_PTRACE), ScmpErrno(EPERM), nil},
{Syscall: SNR_PTRACE, Errno: ScmpErrno(EPERM), Arg: nil},
}
}

View File

@ -22,7 +22,7 @@ package std
import . "syscall"
var syscallNum = map[string]int{
var syscallNum = map[string]ScmpSyscall{
EOF
my $offset = 0;
@ -37,16 +37,14 @@ sub fmt {
}
(my $name_upper = $name) =~ y/a-z/A-Z/;
$num = $num + $offset;
if($num > $syscall_cutoff_arch{$uname_arch}){ # not wired in Go standard library
if($state < 0){
print " \"$name\": SYS_$name_upper,\n";
if($num > $syscall_cutoff_arch{$uname_arch} && $state == 0){ # not wired in Go standard library
print " SYS_$name_upper = $num\n";
}
else{
print " SYS_$name_upper = $num;\n";
elsif($state == -1){
print " \"$name\": SNR_$name_upper,\n";
}
}
elsif($state < 0){
print " \"$name\": SYS_$name_upper,\n";
elsif($state == 1){
print " SNR_$name_upper ScmpSyscall = SYS_$name_upper\n";
}
else{
return;
@ -81,10 +79,16 @@ while(<GCC>){
}
}
if($state < 0){
$state = $state + 1;
if($state == -1){
print "}\n\nconst (\n";
goto GENERATE;
}
elsif($state == 0){
print ")\n\nconst (\n";
}
elsif($state == 1){
print ")";
exit;
}
++$state;
goto GENERATE;
print ")";

View File

@ -46,7 +46,7 @@ type (
// MarshalJSON resolves the name of [ScmpSyscall] and encodes it as a [json] string.
// If such a name does not exist, the syscall number is encoded instead.
func (num *ScmpSyscall) MarshalJSON() ([]byte, error) {
n := int(*num)
n := *num
for name, cur := range Syscalls() {
if cur == n {
return json.Marshal(name)
@ -70,7 +70,7 @@ func (num *ScmpSyscall) UnmarshalJSON(data []byte) error {
if n, ok := SyscallResolveName(name); !ok {
return SyscallNameError(name)
} else {
*num = ScmpSyscall(n)
*num = n
return nil
}
}

View File

@ -5,7 +5,6 @@ import (
"errors"
"math"
"reflect"
"syscall"
"testing"
"hakurei.app/container/std"
@ -20,8 +19,8 @@ func TestScmpSyscall(t *testing.T) {
want std.ScmpSyscall
err error
}{
{"select", `"select"`, syscall.SYS_SELECT, nil},
{"clone3", `"clone3"`, std.SYS_CLONE3, nil},
{"epoll_create1", `"epoll_create1"`, std.SNR_EPOLL_CREATE1, nil},
{"clone3", `"clone3"`, std.SNR_CLONE3, nil},
{"oob", `-2147483647`, -math.MaxInt32,
&json.UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[string](), Offset: 11}},

View File

@ -3,8 +3,8 @@ package std
import "iter"
// Syscalls returns an iterator over all wired syscalls.
func Syscalls() iter.Seq2[string, int] {
return func(yield func(string, int) bool) {
func Syscalls() iter.Seq2[string, ScmpSyscall] {
return func(yield func(string, ScmpSyscall) bool) {
for name, num := range syscallNum {
if !yield(name, num) {
return
@ -19,7 +19,7 @@ func Syscalls() iter.Seq2[string, int] {
}
// SyscallResolveName resolves a syscall number from its string representation.
func SyscallResolveName(name string) (num int, ok bool) {
func SyscallResolveName(name string) (num ScmpSyscall, ok bool) {
if num, ok = syscallNum[name]; ok {
return
}

View File

@ -1,13 +1,13 @@
package std
var syscallNumExtra = map[string]int{
"kexec_file_load": SYS_KEXEC_FILE_LOAD,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
var syscallNumExtra = map[string]ScmpSyscall{
"kexec_file_load": SNR_KEXEC_FILE_LOAD,
"subpage_prot": SNR_SUBPAGE_PROT,
"switch_endian": SNR_SWITCH_ENDIAN,
}
const (
SYS_KEXEC_FILE_LOAD = __PNR_kexec_file_load
SYS_SUBPAGE_PROT = __PNR_subpage_prot
SYS_SWITCH_ENDIAN = __PNR_switch_endian
SNR_KEXEC_FILE_LOAD ScmpSyscall = __PNR_kexec_file_load
SNR_SUBPAGE_PROT ScmpSyscall = __PNR_subpage_prot
SNR_SWITCH_ENDIAN ScmpSyscall = __PNR_switch_endian
)

View File

@ -1,41 +1,41 @@
package std
var syscallNumExtra = map[string]int{
"umount": SYS_UMOUNT,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
"vm86": SYS_VM86,
"vm86old": SYS_VM86OLD,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"chown32": SYS_CHOWN32,
"fchown32": SYS_FCHOWN32,
"lchown32": SYS_LCHOWN32,
"setgid32": SYS_SETGID32,
"setgroups32": SYS_SETGROUPS32,
"setregid32": SYS_SETREGID32,
"setresgid32": SYS_SETRESGID32,
"setresuid32": SYS_SETRESUID32,
"setreuid32": SYS_SETREUID32,
"setuid32": SYS_SETUID32,
var syscallNumExtra = map[string]ScmpSyscall{
"umount": SNR_UMOUNT,
"subpage_prot": SNR_SUBPAGE_PROT,
"switch_endian": SNR_SWITCH_ENDIAN,
"vm86": SNR_VM86,
"vm86old": SNR_VM86OLD,
"clock_adjtime64": SNR_CLOCK_ADJTIME64,
"clock_settime64": SNR_CLOCK_SETTIME64,
"chown32": SNR_CHOWN32,
"fchown32": SNR_FCHOWN32,
"lchown32": SNR_LCHOWN32,
"setgid32": SNR_SETGID32,
"setgroups32": SNR_SETGROUPS32,
"setregid32": SNR_SETREGID32,
"setresgid32": SNR_SETRESGID32,
"setresuid32": SNR_SETRESUID32,
"setreuid32": SNR_SETREUID32,
"setuid32": SNR_SETUID32,
}
const (
SYS_UMOUNT = __PNR_umount
SYS_SUBPAGE_PROT = __PNR_subpage_prot
SYS_SWITCH_ENDIAN = __PNR_switch_endian
SYS_VM86 = __PNR_vm86
SYS_VM86OLD = __PNR_vm86old
SYS_CLOCK_ADJTIME64 = __PNR_clock_adjtime64
SYS_CLOCK_SETTIME64 = __PNR_clock_settime64
SYS_CHOWN32 = __PNR_chown32
SYS_FCHOWN32 = __PNR_fchown32
SYS_LCHOWN32 = __PNR_lchown32
SYS_SETGID32 = __PNR_setgid32
SYS_SETGROUPS32 = __PNR_setgroups32
SYS_SETREGID32 = __PNR_setregid32
SYS_SETRESGID32 = __PNR_setresgid32
SYS_SETRESUID32 = __PNR_setresuid32
SYS_SETREUID32 = __PNR_setreuid32
SYS_SETUID32 = __PNR_setuid32
SNR_UMOUNT ScmpSyscall = __PNR_umount
SNR_SUBPAGE_PROT ScmpSyscall = __PNR_subpage_prot
SNR_SWITCH_ENDIAN ScmpSyscall = __PNR_switch_endian
SNR_VM86 ScmpSyscall = __PNR_vm86
SNR_VM86OLD ScmpSyscall = __PNR_vm86old
SNR_CLOCK_ADJTIME64 ScmpSyscall = __PNR_clock_adjtime64
SNR_CLOCK_SETTIME64 ScmpSyscall = __PNR_clock_settime64
SNR_CHOWN32 ScmpSyscall = __PNR_chown32
SNR_FCHOWN32 ScmpSyscall = __PNR_fchown32
SNR_LCHOWN32 ScmpSyscall = __PNR_lchown32
SNR_SETGID32 ScmpSyscall = __PNR_setgid32
SNR_SETGROUPS32 ScmpSyscall = __PNR_setgroups32
SNR_SETREGID32 ScmpSyscall = __PNR_setregid32
SNR_SETRESGID32 ScmpSyscall = __PNR_setresgid32
SNR_SETRESUID32 ScmpSyscall = __PNR_setresuid32
SNR_SETREUID32 ScmpSyscall = __PNR_setreuid32
SNR_SETUID32 ScmpSyscall = __PNR_setuid32
)

View File

@ -6,50 +6,50 @@ const (
SYS_NEWFSTATAT = syscall.SYS_FSTATAT
)
var syscallNumExtra = map[string]int{
"uselib": SYS_USELIB,
"clock_adjtime64": SYS_CLOCK_ADJTIME64,
"clock_settime64": SYS_CLOCK_SETTIME64,
"umount": SYS_UMOUNT,
"chown": SYS_CHOWN,
"chown32": SYS_CHOWN32,
"fchown32": SYS_FCHOWN32,
"lchown": SYS_LCHOWN,
"lchown32": SYS_LCHOWN32,
"setgid32": SYS_SETGID32,
"setgroups32": SYS_SETGROUPS32,
"setregid32": SYS_SETREGID32,
"setresgid32": SYS_SETRESGID32,
"setresuid32": SYS_SETRESUID32,
"setreuid32": SYS_SETREUID32,
"setuid32": SYS_SETUID32,
"modify_ldt": SYS_MODIFY_LDT,
"subpage_prot": SYS_SUBPAGE_PROT,
"switch_endian": SYS_SWITCH_ENDIAN,
"vm86": SYS_VM86,
"vm86old": SYS_VM86OLD,
var syscallNumExtra = map[string]ScmpSyscall{
"uselib": SNR_USELIB,
"clock_adjtime64": SNR_CLOCK_ADJTIME64,
"clock_settime64": SNR_CLOCK_SETTIME64,
"umount": SNR_UMOUNT,
"chown": SNR_CHOWN,
"chown32": SNR_CHOWN32,
"fchown32": SNR_FCHOWN32,
"lchown": SNR_LCHOWN,
"lchown32": SNR_LCHOWN32,
"setgid32": SNR_SETGID32,
"setgroups32": SNR_SETGROUPS32,
"setregid32": SNR_SETREGID32,
"setresgid32": SNR_SETRESGID32,
"setresuid32": SNR_SETRESUID32,
"setreuid32": SNR_SETREUID32,
"setuid32": SNR_SETUID32,
"modify_ldt": SNR_MODIFY_LDT,
"subpage_prot": SNR_SUBPAGE_PROT,
"switch_endian": SNR_SWITCH_ENDIAN,
"vm86": SNR_VM86,
"vm86old": SNR_VM86OLD,
}
const (
SYS_USELIB = __PNR_uselib
SYS_CLOCK_ADJTIME64 = __PNR_clock_adjtime64
SYS_CLOCK_SETTIME64 = __PNR_clock_settime64
SYS_UMOUNT = __PNR_umount
SYS_CHOWN = __PNR_chown
SYS_CHOWN32 = __PNR_chown32
SYS_FCHOWN32 = __PNR_fchown32
SYS_LCHOWN = __PNR_lchown
SYS_LCHOWN32 = __PNR_lchown32
SYS_SETGID32 = __PNR_setgid32
SYS_SETGROUPS32 = __PNR_setgroups32
SYS_SETREGID32 = __PNR_setregid32
SYS_SETRESGID32 = __PNR_setresgid32
SYS_SETRESUID32 = __PNR_setresuid32
SYS_SETREUID32 = __PNR_setreuid32
SYS_SETUID32 = __PNR_setuid32
SYS_MODIFY_LDT = __PNR_modify_ldt
SYS_SUBPAGE_PROT = __PNR_subpage_prot
SYS_SWITCH_ENDIAN = __PNR_switch_endian
SYS_VM86 = __PNR_vm86
SYS_VM86OLD = __PNR_vm86old
SNR_USELIB ScmpSyscall = __PNR_uselib
SNR_CLOCK_ADJTIME64 ScmpSyscall = __PNR_clock_adjtime64
SNR_CLOCK_SETTIME64 ScmpSyscall = __PNR_clock_settime64
SNR_UMOUNT ScmpSyscall = __PNR_umount
SNR_CHOWN ScmpSyscall = __PNR_chown
SNR_CHOWN32 ScmpSyscall = __PNR_chown32
SNR_FCHOWN32 ScmpSyscall = __PNR_fchown32
SNR_LCHOWN ScmpSyscall = __PNR_lchown
SNR_LCHOWN32 ScmpSyscall = __PNR_lchown32
SNR_SETGID32 ScmpSyscall = __PNR_setgid32
SNR_SETGROUPS32 ScmpSyscall = __PNR_setgroups32
SNR_SETREGID32 ScmpSyscall = __PNR_setregid32
SNR_SETRESGID32 ScmpSyscall = __PNR_setresgid32
SNR_SETRESUID32 ScmpSyscall = __PNR_setresuid32
SNR_SETREUID32 ScmpSyscall = __PNR_setreuid32
SNR_SETUID32 ScmpSyscall = __PNR_setuid32
SNR_MODIFY_LDT ScmpSyscall = __PNR_modify_ldt
SNR_SUBPAGE_PROT ScmpSyscall = __PNR_subpage_prot
SNR_SWITCH_ENDIAN ScmpSyscall = __PNR_switch_endian
SNR_VM86 ScmpSyscall = __PNR_vm86
SNR_VM86OLD ScmpSyscall = __PNR_vm86old
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,325 +5,325 @@ package std
import . "syscall"
var syscallNum = map[string]int{
"io_setup": SYS_IO_SETUP,
"io_destroy": SYS_IO_DESTROY,
"io_submit": SYS_IO_SUBMIT,
"io_cancel": SYS_IO_CANCEL,
"io_getevents": SYS_IO_GETEVENTS,
"setxattr": SYS_SETXATTR,
"lsetxattr": SYS_LSETXATTR,
"fsetxattr": SYS_FSETXATTR,
"getxattr": SYS_GETXATTR,
"lgetxattr": SYS_LGETXATTR,
"fgetxattr": SYS_FGETXATTR,
"listxattr": SYS_LISTXATTR,
"llistxattr": SYS_LLISTXATTR,
"flistxattr": SYS_FLISTXATTR,
"removexattr": SYS_REMOVEXATTR,
"lremovexattr": SYS_LREMOVEXATTR,
"fremovexattr": SYS_FREMOVEXATTR,
"getcwd": SYS_GETCWD,
"lookup_dcookie": SYS_LOOKUP_DCOOKIE,
"eventfd2": SYS_EVENTFD2,
"epoll_create1": SYS_EPOLL_CREATE1,
"epoll_ctl": SYS_EPOLL_CTL,
"epoll_pwait": SYS_EPOLL_PWAIT,
"dup": SYS_DUP,
"dup3": SYS_DUP3,
"fcntl": SYS_FCNTL,
"inotify_init1": SYS_INOTIFY_INIT1,
"inotify_add_watch": SYS_INOTIFY_ADD_WATCH,
"inotify_rm_watch": SYS_INOTIFY_RM_WATCH,
"ioctl": SYS_IOCTL,
"ioprio_set": SYS_IOPRIO_SET,
"ioprio_get": SYS_IOPRIO_GET,
"flock": SYS_FLOCK,
"mknodat": SYS_MKNODAT,
"mkdirat": SYS_MKDIRAT,
"unlinkat": SYS_UNLINKAT,
"symlinkat": SYS_SYMLINKAT,
"linkat": SYS_LINKAT,
"renameat": SYS_RENAMEAT,
"umount2": SYS_UMOUNT2,
"mount": SYS_MOUNT,
"pivot_root": SYS_PIVOT_ROOT,
"nfsservctl": SYS_NFSSERVCTL,
"statfs": SYS_STATFS,
"fstatfs": SYS_FSTATFS,
"truncate": SYS_TRUNCATE,
"ftruncate": SYS_FTRUNCATE,
"fallocate": SYS_FALLOCATE,
"faccessat": SYS_FACCESSAT,
"chdir": SYS_CHDIR,
"fchdir": SYS_FCHDIR,
"chroot": SYS_CHROOT,
"fchmod": SYS_FCHMOD,
"fchmodat": SYS_FCHMODAT,
"fchownat": SYS_FCHOWNAT,
"fchown": SYS_FCHOWN,
"openat": SYS_OPENAT,
"close": SYS_CLOSE,
"vhangup": SYS_VHANGUP,
"pipe2": SYS_PIPE2,
"quotactl": SYS_QUOTACTL,
"getdents64": SYS_GETDENTS64,
"lseek": SYS_LSEEK,
"read": SYS_READ,
"write": SYS_WRITE,
"readv": SYS_READV,
"writev": SYS_WRITEV,
"pread64": SYS_PREAD64,
"pwrite64": SYS_PWRITE64,
"preadv": SYS_PREADV,
"pwritev": SYS_PWRITEV,
"sendfile": SYS_SENDFILE,
"pselect6": SYS_PSELECT6,
"ppoll": SYS_PPOLL,
"signalfd4": SYS_SIGNALFD4,
"vmsplice": SYS_VMSPLICE,
"splice": SYS_SPLICE,
"tee": SYS_TEE,
"readlinkat": SYS_READLINKAT,
"newfstatat": SYS_NEWFSTATAT,
"fstat": SYS_FSTAT,
"sync": SYS_SYNC,
"fsync": SYS_FSYNC,
"fdatasync": SYS_FDATASYNC,
"sync_file_range": SYS_SYNC_FILE_RANGE,
"timerfd_create": SYS_TIMERFD_CREATE,
"timerfd_settime": SYS_TIMERFD_SETTIME,
"timerfd_gettime": SYS_TIMERFD_GETTIME,
"utimensat": SYS_UTIMENSAT,
"acct": SYS_ACCT,
"capget": SYS_CAPGET,
"capset": SYS_CAPSET,
"personality": SYS_PERSONALITY,
"exit": SYS_EXIT,
"exit_group": SYS_EXIT_GROUP,
"waitid": SYS_WAITID,
"set_tid_address": SYS_SET_TID_ADDRESS,
"unshare": SYS_UNSHARE,
"futex": SYS_FUTEX,
"set_robust_list": SYS_SET_ROBUST_LIST,
"get_robust_list": SYS_GET_ROBUST_LIST,
"nanosleep": SYS_NANOSLEEP,
"getitimer": SYS_GETITIMER,
"setitimer": SYS_SETITIMER,
"kexec_load": SYS_KEXEC_LOAD,
"init_module": SYS_INIT_MODULE,
"delete_module": SYS_DELETE_MODULE,
"timer_create": SYS_TIMER_CREATE,
"timer_gettime": SYS_TIMER_GETTIME,
"timer_getoverrun": SYS_TIMER_GETOVERRUN,
"timer_settime": SYS_TIMER_SETTIME,
"timer_delete": SYS_TIMER_DELETE,
"clock_settime": SYS_CLOCK_SETTIME,
"clock_gettime": SYS_CLOCK_GETTIME,
"clock_getres": SYS_CLOCK_GETRES,
"clock_nanosleep": SYS_CLOCK_NANOSLEEP,
"syslog": SYS_SYSLOG,
"ptrace": SYS_PTRACE,
"sched_setparam": SYS_SCHED_SETPARAM,
"sched_setscheduler": SYS_SCHED_SETSCHEDULER,
"sched_getscheduler": SYS_SCHED_GETSCHEDULER,
"sched_getparam": SYS_SCHED_GETPARAM,
"sched_setaffinity": SYS_SCHED_SETAFFINITY,
"sched_getaffinity": SYS_SCHED_GETAFFINITY,
"sched_yield": SYS_SCHED_YIELD,
"sched_get_priority_max": SYS_SCHED_GET_PRIORITY_MAX,
"sched_get_priority_min": SYS_SCHED_GET_PRIORITY_MIN,
"sched_rr_get_interval": SYS_SCHED_RR_GET_INTERVAL,
"restart_syscall": SYS_RESTART_SYSCALL,
"kill": SYS_KILL,
"tkill": SYS_TKILL,
"tgkill": SYS_TGKILL,
"sigaltstack": SYS_SIGALTSTACK,
"rt_sigsuspend": SYS_RT_SIGSUSPEND,
"rt_sigaction": SYS_RT_SIGACTION,
"rt_sigprocmask": SYS_RT_SIGPROCMASK,
"rt_sigpending": SYS_RT_SIGPENDING,
"rt_sigtimedwait": SYS_RT_SIGTIMEDWAIT,
"rt_sigqueueinfo": SYS_RT_SIGQUEUEINFO,
"rt_sigreturn": SYS_RT_SIGRETURN,
"setpriority": SYS_SETPRIORITY,
"getpriority": SYS_GETPRIORITY,
"reboot": SYS_REBOOT,
"setregid": SYS_SETREGID,
"setgid": SYS_SETGID,
"setreuid": SYS_SETREUID,
"setuid": SYS_SETUID,
"setresuid": SYS_SETRESUID,
"getresuid": SYS_GETRESUID,
"setresgid": SYS_SETRESGID,
"getresgid": SYS_GETRESGID,
"setfsuid": SYS_SETFSUID,
"setfsgid": SYS_SETFSGID,
"times": SYS_TIMES,
"setpgid": SYS_SETPGID,
"getpgid": SYS_GETPGID,
"getsid": SYS_GETSID,
"setsid": SYS_SETSID,
"getgroups": SYS_GETGROUPS,
"setgroups": SYS_SETGROUPS,
"uname": SYS_UNAME,
"sethostname": SYS_SETHOSTNAME,
"setdomainname": SYS_SETDOMAINNAME,
"getrlimit": SYS_GETRLIMIT,
"setrlimit": SYS_SETRLIMIT,
"getrusage": SYS_GETRUSAGE,
"umask": SYS_UMASK,
"prctl": SYS_PRCTL,
"getcpu": SYS_GETCPU,
"gettimeofday": SYS_GETTIMEOFDAY,
"settimeofday": SYS_SETTIMEOFDAY,
"adjtimex": SYS_ADJTIMEX,
"getpid": SYS_GETPID,
"getppid": SYS_GETPPID,
"getuid": SYS_GETUID,
"geteuid": SYS_GETEUID,
"getgid": SYS_GETGID,
"getegid": SYS_GETEGID,
"gettid": SYS_GETTID,
"sysinfo": SYS_SYSINFO,
"mq_open": SYS_MQ_OPEN,
"mq_unlink": SYS_MQ_UNLINK,
"mq_timedsend": SYS_MQ_TIMEDSEND,
"mq_timedreceive": SYS_MQ_TIMEDRECEIVE,
"mq_notify": SYS_MQ_NOTIFY,
"mq_getsetattr": SYS_MQ_GETSETATTR,
"msgget": SYS_MSGGET,
"msgctl": SYS_MSGCTL,
"msgrcv": SYS_MSGRCV,
"msgsnd": SYS_MSGSND,
"semget": SYS_SEMGET,
"semctl": SYS_SEMCTL,
"semtimedop": SYS_SEMTIMEDOP,
"semop": SYS_SEMOP,
"shmget": SYS_SHMGET,
"shmctl": SYS_SHMCTL,
"shmat": SYS_SHMAT,
"shmdt": SYS_SHMDT,
"socket": SYS_SOCKET,
"socketpair": SYS_SOCKETPAIR,
"bind": SYS_BIND,
"listen": SYS_LISTEN,
"accept": SYS_ACCEPT,
"connect": SYS_CONNECT,
"getsockname": SYS_GETSOCKNAME,
"getpeername": SYS_GETPEERNAME,
"sendto": SYS_SENDTO,
"recvfrom": SYS_RECVFROM,
"setsockopt": SYS_SETSOCKOPT,
"getsockopt": SYS_GETSOCKOPT,
"shutdown": SYS_SHUTDOWN,
"sendmsg": SYS_SENDMSG,
"recvmsg": SYS_RECVMSG,
"readahead": SYS_READAHEAD,
"brk": SYS_BRK,
"munmap": SYS_MUNMAP,
"mremap": SYS_MREMAP,
"add_key": SYS_ADD_KEY,
"request_key": SYS_REQUEST_KEY,
"keyctl": SYS_KEYCTL,
"clone": SYS_CLONE,
"execve": SYS_EXECVE,
"mmap": SYS_MMAP,
"fadvise64": SYS_FADVISE64,
"swapon": SYS_SWAPON,
"swapoff": SYS_SWAPOFF,
"mprotect": SYS_MPROTECT,
"msync": SYS_MSYNC,
"mlock": SYS_MLOCK,
"munlock": SYS_MUNLOCK,
"mlockall": SYS_MLOCKALL,
"munlockall": SYS_MUNLOCKALL,
"mincore": SYS_MINCORE,
"madvise": SYS_MADVISE,
"remap_file_pages": SYS_REMAP_FILE_PAGES,
"mbind": SYS_MBIND,
"get_mempolicy": SYS_GET_MEMPOLICY,
"set_mempolicy": SYS_SET_MEMPOLICY,
"migrate_pages": SYS_MIGRATE_PAGES,
"move_pages": SYS_MOVE_PAGES,
"rt_tgsigqueueinfo": SYS_RT_TGSIGQUEUEINFO,
"perf_event_open": SYS_PERF_EVENT_OPEN,
"accept4": SYS_ACCEPT4,
"recvmmsg": SYS_RECVMMSG,
"wait4": SYS_WAIT4,
"prlimit64": SYS_PRLIMIT64,
"fanotify_init": SYS_FANOTIFY_INIT,
"fanotify_mark": SYS_FANOTIFY_MARK,
"name_to_handle_at": SYS_NAME_TO_HANDLE_AT,
"open_by_handle_at": SYS_OPEN_BY_HANDLE_AT,
"clock_adjtime": SYS_CLOCK_ADJTIME,
"syncfs": SYS_SYNCFS,
"setns": SYS_SETNS,
"sendmmsg": SYS_SENDMMSG,
"process_vm_readv": SYS_PROCESS_VM_READV,
"process_vm_writev": SYS_PROCESS_VM_WRITEV,
"kcmp": SYS_KCMP,
"finit_module": SYS_FINIT_MODULE,
"sched_setattr": SYS_SCHED_SETATTR,
"sched_getattr": SYS_SCHED_GETATTR,
"renameat2": SYS_RENAMEAT2,
"seccomp": SYS_SECCOMP,
"getrandom": SYS_GETRANDOM,
"memfd_create": SYS_MEMFD_CREATE,
"bpf": SYS_BPF,
"execveat": SYS_EXECVEAT,
"userfaultfd": SYS_USERFAULTFD,
"membarrier": SYS_MEMBARRIER,
"mlock2": SYS_MLOCK2,
"copy_file_range": SYS_COPY_FILE_RANGE,
"preadv2": SYS_PREADV2,
"pwritev2": SYS_PWRITEV2,
"pkey_mprotect": SYS_PKEY_MPROTECT,
"pkey_alloc": SYS_PKEY_ALLOC,
"pkey_free": SYS_PKEY_FREE,
"statx": SYS_STATX,
"io_pgetevents": SYS_IO_PGETEVENTS,
"rseq": SYS_RSEQ,
"kexec_file_load": SYS_KEXEC_FILE_LOAD,
"pidfd_send_signal": SYS_PIDFD_SEND_SIGNAL,
"io_uring_setup": SYS_IO_URING_SETUP,
"io_uring_enter": SYS_IO_URING_ENTER,
"io_uring_register": SYS_IO_URING_REGISTER,
"open_tree": SYS_OPEN_TREE,
"move_mount": SYS_MOVE_MOUNT,
"fsopen": SYS_FSOPEN,
"fsconfig": SYS_FSCONFIG,
"fsmount": SYS_FSMOUNT,
"fspick": SYS_FSPICK,
"pidfd_open": SYS_PIDFD_OPEN,
"clone3": SYS_CLONE3,
"close_range": SYS_CLOSE_RANGE,
"openat2": SYS_OPENAT2,
"pidfd_getfd": SYS_PIDFD_GETFD,
"faccessat2": SYS_FACCESSAT2,
"process_madvise": SYS_PROCESS_MADVISE,
"epoll_pwait2": SYS_EPOLL_PWAIT2,
"mount_setattr": SYS_MOUNT_SETATTR,
"quotactl_fd": SYS_QUOTACTL_FD,
"landlock_create_ruleset": SYS_LANDLOCK_CREATE_RULESET,
"landlock_add_rule": SYS_LANDLOCK_ADD_RULE,
"landlock_restrict_self": SYS_LANDLOCK_RESTRICT_SELF,
"memfd_secret": SYS_MEMFD_SECRET,
"process_mrelease": SYS_PROCESS_MRELEASE,
"futex_waitv": SYS_FUTEX_WAITV,
"set_mempolicy_home_node": SYS_SET_MEMPOLICY_HOME_NODE,
"cachestat": SYS_CACHESTAT,
"fchmodat2": SYS_FCHMODAT2,
"map_shadow_stack": SYS_MAP_SHADOW_STACK,
"futex_wake": SYS_FUTEX_WAKE,
"futex_wait": SYS_FUTEX_WAIT,
"futex_requeue": SYS_FUTEX_REQUEUE,
"statmount": SYS_STATMOUNT,
"listmount": SYS_LISTMOUNT,
"lsm_get_self_attr": SYS_LSM_GET_SELF_ATTR,
"lsm_set_self_attr": SYS_LSM_SET_SELF_ATTR,
"lsm_list_modules": SYS_LSM_LIST_MODULES,
"mseal": SYS_MSEAL,
var syscallNum = map[string]ScmpSyscall{
"io_setup": SNR_IO_SETUP,
"io_destroy": SNR_IO_DESTROY,
"io_submit": SNR_IO_SUBMIT,
"io_cancel": SNR_IO_CANCEL,
"io_getevents": SNR_IO_GETEVENTS,
"setxattr": SNR_SETXATTR,
"lsetxattr": SNR_LSETXATTR,
"fsetxattr": SNR_FSETXATTR,
"getxattr": SNR_GETXATTR,
"lgetxattr": SNR_LGETXATTR,
"fgetxattr": SNR_FGETXATTR,
"listxattr": SNR_LISTXATTR,
"llistxattr": SNR_LLISTXATTR,
"flistxattr": SNR_FLISTXATTR,
"removexattr": SNR_REMOVEXATTR,
"lremovexattr": SNR_LREMOVEXATTR,
"fremovexattr": SNR_FREMOVEXATTR,
"getcwd": SNR_GETCWD,
"lookup_dcookie": SNR_LOOKUP_DCOOKIE,
"eventfd2": SNR_EVENTFD2,
"epoll_create1": SNR_EPOLL_CREATE1,
"epoll_ctl": SNR_EPOLL_CTL,
"epoll_pwait": SNR_EPOLL_PWAIT,
"dup": SNR_DUP,
"dup3": SNR_DUP3,
"fcntl": SNR_FCNTL,
"inotify_init1": SNR_INOTIFY_INIT1,
"inotify_add_watch": SNR_INOTIFY_ADD_WATCH,
"inotify_rm_watch": SNR_INOTIFY_RM_WATCH,
"ioctl": SNR_IOCTL,
"ioprio_set": SNR_IOPRIO_SET,
"ioprio_get": SNR_IOPRIO_GET,
"flock": SNR_FLOCK,
"mknodat": SNR_MKNODAT,
"mkdirat": SNR_MKDIRAT,
"unlinkat": SNR_UNLINKAT,
"symlinkat": SNR_SYMLINKAT,
"linkat": SNR_LINKAT,
"renameat": SNR_RENAMEAT,
"umount2": SNR_UMOUNT2,
"mount": SNR_MOUNT,
"pivot_root": SNR_PIVOT_ROOT,
"nfsservctl": SNR_NFSSERVCTL,
"statfs": SNR_STATFS,
"fstatfs": SNR_FSTATFS,
"truncate": SNR_TRUNCATE,
"ftruncate": SNR_FTRUNCATE,
"fallocate": SNR_FALLOCATE,
"faccessat": SNR_FACCESSAT,
"chdir": SNR_CHDIR,
"fchdir": SNR_FCHDIR,
"chroot": SNR_CHROOT,
"fchmod": SNR_FCHMOD,
"fchmodat": SNR_FCHMODAT,
"fchownat": SNR_FCHOWNAT,
"fchown": SNR_FCHOWN,
"openat": SNR_OPENAT,
"close": SNR_CLOSE,
"vhangup": SNR_VHANGUP,
"pipe2": SNR_PIPE2,
"quotactl": SNR_QUOTACTL,
"getdents64": SNR_GETDENTS64,
"lseek": SNR_LSEEK,
"read": SNR_READ,
"write": SNR_WRITE,
"readv": SNR_READV,
"writev": SNR_WRITEV,
"pread64": SNR_PREAD64,
"pwrite64": SNR_PWRITE64,
"preadv": SNR_PREADV,
"pwritev": SNR_PWRITEV,
"sendfile": SNR_SENDFILE,
"pselect6": SNR_PSELECT6,
"ppoll": SNR_PPOLL,
"signalfd4": SNR_SIGNALFD4,
"vmsplice": SNR_VMSPLICE,
"splice": SNR_SPLICE,
"tee": SNR_TEE,
"readlinkat": SNR_READLINKAT,
"newfstatat": SNR_NEWFSTATAT,
"fstat": SNR_FSTAT,
"sync": SNR_SYNC,
"fsync": SNR_FSYNC,
"fdatasync": SNR_FDATASYNC,
"sync_file_range": SNR_SYNC_FILE_RANGE,
"timerfd_create": SNR_TIMERFD_CREATE,
"timerfd_settime": SNR_TIMERFD_SETTIME,
"timerfd_gettime": SNR_TIMERFD_GETTIME,
"utimensat": SNR_UTIMENSAT,
"acct": SNR_ACCT,
"capget": SNR_CAPGET,
"capset": SNR_CAPSET,
"personality": SNR_PERSONALITY,
"exit": SNR_EXIT,
"exit_group": SNR_EXIT_GROUP,
"waitid": SNR_WAITID,
"set_tid_address": SNR_SET_TID_ADDRESS,
"unshare": SNR_UNSHARE,
"futex": SNR_FUTEX,
"set_robust_list": SNR_SET_ROBUST_LIST,
"get_robust_list": SNR_GET_ROBUST_LIST,
"nanosleep": SNR_NANOSLEEP,
"getitimer": SNR_GETITIMER,
"setitimer": SNR_SETITIMER,
"kexec_load": SNR_KEXEC_LOAD,
"init_module": SNR_INIT_MODULE,
"delete_module": SNR_DELETE_MODULE,
"timer_create": SNR_TIMER_CREATE,
"timer_gettime": SNR_TIMER_GETTIME,
"timer_getoverrun": SNR_TIMER_GETOVERRUN,
"timer_settime": SNR_TIMER_SETTIME,
"timer_delete": SNR_TIMER_DELETE,
"clock_settime": SNR_CLOCK_SETTIME,
"clock_gettime": SNR_CLOCK_GETTIME,
"clock_getres": SNR_CLOCK_GETRES,
"clock_nanosleep": SNR_CLOCK_NANOSLEEP,
"syslog": SNR_SYSLOG,
"ptrace": SNR_PTRACE,
"sched_setparam": SNR_SCHED_SETPARAM,
"sched_setscheduler": SNR_SCHED_SETSCHEDULER,
"sched_getscheduler": SNR_SCHED_GETSCHEDULER,
"sched_getparam": SNR_SCHED_GETPARAM,
"sched_setaffinity": SNR_SCHED_SETAFFINITY,
"sched_getaffinity": SNR_SCHED_GETAFFINITY,
"sched_yield": SNR_SCHED_YIELD,
"sched_get_priority_max": SNR_SCHED_GET_PRIORITY_MAX,
"sched_get_priority_min": SNR_SCHED_GET_PRIORITY_MIN,
"sched_rr_get_interval": SNR_SCHED_RR_GET_INTERVAL,
"restart_syscall": SNR_RESTART_SYSCALL,
"kill": SNR_KILL,
"tkill": SNR_TKILL,
"tgkill": SNR_TGKILL,
"sigaltstack": SNR_SIGALTSTACK,
"rt_sigsuspend": SNR_RT_SIGSUSPEND,
"rt_sigaction": SNR_RT_SIGACTION,
"rt_sigprocmask": SNR_RT_SIGPROCMASK,
"rt_sigpending": SNR_RT_SIGPENDING,
"rt_sigtimedwait": SNR_RT_SIGTIMEDWAIT,
"rt_sigqueueinfo": SNR_RT_SIGQUEUEINFO,
"rt_sigreturn": SNR_RT_SIGRETURN,
"setpriority": SNR_SETPRIORITY,
"getpriority": SNR_GETPRIORITY,
"reboot": SNR_REBOOT,
"setregid": SNR_SETREGID,
"setgid": SNR_SETGID,
"setreuid": SNR_SETREUID,
"setuid": SNR_SETUID,
"setresuid": SNR_SETRESUID,
"getresuid": SNR_GETRESUID,
"setresgid": SNR_SETRESGID,
"getresgid": SNR_GETRESGID,
"setfsuid": SNR_SETFSUID,
"setfsgid": SNR_SETFSGID,
"times": SNR_TIMES,
"setpgid": SNR_SETPGID,
"getpgid": SNR_GETPGID,
"getsid": SNR_GETSID,
"setsid": SNR_SETSID,
"getgroups": SNR_GETGROUPS,
"setgroups": SNR_SETGROUPS,
"uname": SNR_UNAME,
"sethostname": SNR_SETHOSTNAME,
"setdomainname": SNR_SETDOMAINNAME,
"getrlimit": SNR_GETRLIMIT,
"setrlimit": SNR_SETRLIMIT,
"getrusage": SNR_GETRUSAGE,
"umask": SNR_UMASK,
"prctl": SNR_PRCTL,
"getcpu": SNR_GETCPU,
"gettimeofday": SNR_GETTIMEOFDAY,
"settimeofday": SNR_SETTIMEOFDAY,
"adjtimex": SNR_ADJTIMEX,
"getpid": SNR_GETPID,
"getppid": SNR_GETPPID,
"getuid": SNR_GETUID,
"geteuid": SNR_GETEUID,
"getgid": SNR_GETGID,
"getegid": SNR_GETEGID,
"gettid": SNR_GETTID,
"sysinfo": SNR_SYSINFO,
"mq_open": SNR_MQ_OPEN,
"mq_unlink": SNR_MQ_UNLINK,
"mq_timedsend": SNR_MQ_TIMEDSEND,
"mq_timedreceive": SNR_MQ_TIMEDRECEIVE,
"mq_notify": SNR_MQ_NOTIFY,
"mq_getsetattr": SNR_MQ_GETSETATTR,
"msgget": SNR_MSGGET,
"msgctl": SNR_MSGCTL,
"msgrcv": SNR_MSGRCV,
"msgsnd": SNR_MSGSND,
"semget": SNR_SEMGET,
"semctl": SNR_SEMCTL,
"semtimedop": SNR_SEMTIMEDOP,
"semop": SNR_SEMOP,
"shmget": SNR_SHMGET,
"shmctl": SNR_SHMCTL,
"shmat": SNR_SHMAT,
"shmdt": SNR_SHMDT,
"socket": SNR_SOCKET,
"socketpair": SNR_SOCKETPAIR,
"bind": SNR_BIND,
"listen": SNR_LISTEN,
"accept": SNR_ACCEPT,
"connect": SNR_CONNECT,
"getsockname": SNR_GETSOCKNAME,
"getpeername": SNR_GETPEERNAME,
"sendto": SNR_SENDTO,
"recvfrom": SNR_RECVFROM,
"setsockopt": SNR_SETSOCKOPT,
"getsockopt": SNR_GETSOCKOPT,
"shutdown": SNR_SHUTDOWN,
"sendmsg": SNR_SENDMSG,
"recvmsg": SNR_RECVMSG,
"readahead": SNR_READAHEAD,
"brk": SNR_BRK,
"munmap": SNR_MUNMAP,
"mremap": SNR_MREMAP,
"add_key": SNR_ADD_KEY,
"request_key": SNR_REQUEST_KEY,
"keyctl": SNR_KEYCTL,
"clone": SNR_CLONE,
"execve": SNR_EXECVE,
"mmap": SNR_MMAP,
"fadvise64": SNR_FADVISE64,
"swapon": SNR_SWAPON,
"swapoff": SNR_SWAPOFF,
"mprotect": SNR_MPROTECT,
"msync": SNR_MSYNC,
"mlock": SNR_MLOCK,
"munlock": SNR_MUNLOCK,
"mlockall": SNR_MLOCKALL,
"munlockall": SNR_MUNLOCKALL,
"mincore": SNR_MINCORE,
"madvise": SNR_MADVISE,
"remap_file_pages": SNR_REMAP_FILE_PAGES,
"mbind": SNR_MBIND,
"get_mempolicy": SNR_GET_MEMPOLICY,
"set_mempolicy": SNR_SET_MEMPOLICY,
"migrate_pages": SNR_MIGRATE_PAGES,
"move_pages": SNR_MOVE_PAGES,
"rt_tgsigqueueinfo": SNR_RT_TGSIGQUEUEINFO,
"perf_event_open": SNR_PERF_EVENT_OPEN,
"accept4": SNR_ACCEPT4,
"recvmmsg": SNR_RECVMMSG,
"wait4": SNR_WAIT4,
"prlimit64": SNR_PRLIMIT64,
"fanotify_init": SNR_FANOTIFY_INIT,
"fanotify_mark": SNR_FANOTIFY_MARK,
"name_to_handle_at": SNR_NAME_TO_HANDLE_AT,
"open_by_handle_at": SNR_OPEN_BY_HANDLE_AT,
"clock_adjtime": SNR_CLOCK_ADJTIME,
"syncfs": SNR_SYNCFS,
"setns": SNR_SETNS,
"sendmmsg": SNR_SENDMMSG,
"process_vm_readv": SNR_PROCESS_VM_READV,
"process_vm_writev": SNR_PROCESS_VM_WRITEV,
"kcmp": SNR_KCMP,
"finit_module": SNR_FINIT_MODULE,
"sched_setattr": SNR_SCHED_SETATTR,
"sched_getattr": SNR_SCHED_GETATTR,
"renameat2": SNR_RENAMEAT2,
"seccomp": SNR_SECCOMP,
"getrandom": SNR_GETRANDOM,
"memfd_create": SNR_MEMFD_CREATE,
"bpf": SNR_BPF,
"execveat": SNR_EXECVEAT,
"userfaultfd": SNR_USERFAULTFD,
"membarrier": SNR_MEMBARRIER,
"mlock2": SNR_MLOCK2,
"copy_file_range": SNR_COPY_FILE_RANGE,
"preadv2": SNR_PREADV2,
"pwritev2": SNR_PWRITEV2,
"pkey_mprotect": SNR_PKEY_MPROTECT,
"pkey_alloc": SNR_PKEY_ALLOC,
"pkey_free": SNR_PKEY_FREE,
"statx": SNR_STATX,
"io_pgetevents": SNR_IO_PGETEVENTS,
"rseq": SNR_RSEQ,
"kexec_file_load": SNR_KEXEC_FILE_LOAD,
"pidfd_send_signal": SNR_PIDFD_SEND_SIGNAL,
"io_uring_setup": SNR_IO_URING_SETUP,
"io_uring_enter": SNR_IO_URING_ENTER,
"io_uring_register": SNR_IO_URING_REGISTER,
"open_tree": SNR_OPEN_TREE,
"move_mount": SNR_MOVE_MOUNT,
"fsopen": SNR_FSOPEN,
"fsconfig": SNR_FSCONFIG,
"fsmount": SNR_FSMOUNT,
"fspick": SNR_FSPICK,
"pidfd_open": SNR_PIDFD_OPEN,
"clone3": SNR_CLONE3,
"close_range": SNR_CLOSE_RANGE,
"openat2": SNR_OPENAT2,
"pidfd_getfd": SNR_PIDFD_GETFD,
"faccessat2": SNR_FACCESSAT2,
"process_madvise": SNR_PROCESS_MADVISE,
"epoll_pwait2": SNR_EPOLL_PWAIT2,
"mount_setattr": SNR_MOUNT_SETATTR,
"quotactl_fd": SNR_QUOTACTL_FD,
"landlock_create_ruleset": SNR_LANDLOCK_CREATE_RULESET,
"landlock_add_rule": SNR_LANDLOCK_ADD_RULE,
"landlock_restrict_self": SNR_LANDLOCK_RESTRICT_SELF,
"memfd_secret": SNR_MEMFD_SECRET,
"process_mrelease": SNR_PROCESS_MRELEASE,
"futex_waitv": SNR_FUTEX_WAITV,
"set_mempolicy_home_node": SNR_SET_MEMPOLICY_HOME_NODE,
"cachestat": SNR_CACHESTAT,
"fchmodat2": SNR_FCHMODAT2,
"map_shadow_stack": SNR_MAP_SHADOW_STACK,
"futex_wake": SNR_FUTEX_WAKE,
"futex_wait": SNR_FUTEX_WAIT,
"futex_requeue": SNR_FUTEX_REQUEUE,
"statmount": SNR_STATMOUNT,
"listmount": SNR_LISTMOUNT,
"lsm_get_self_attr": SNR_LSM_GET_SELF_ATTR,
"lsm_set_self_attr": SNR_LSM_SET_SELF_ATTR,
"lsm_list_modules": SNR_LSM_LIST_MODULES,
"mseal": SNR_MSEAL,
}
const (
@ -380,3 +380,324 @@ const (
SYS_LSM_LIST_MODULES = 461
SYS_MSEAL = 462
)
const (
SNR_IO_SETUP ScmpSyscall = SYS_IO_SETUP
SNR_IO_DESTROY ScmpSyscall = SYS_IO_DESTROY
SNR_IO_SUBMIT ScmpSyscall = SYS_IO_SUBMIT
SNR_IO_CANCEL ScmpSyscall = SYS_IO_CANCEL
SNR_IO_GETEVENTS ScmpSyscall = SYS_IO_GETEVENTS
SNR_SETXATTR ScmpSyscall = SYS_SETXATTR
SNR_LSETXATTR ScmpSyscall = SYS_LSETXATTR
SNR_FSETXATTR ScmpSyscall = SYS_FSETXATTR
SNR_GETXATTR ScmpSyscall = SYS_GETXATTR
SNR_LGETXATTR ScmpSyscall = SYS_LGETXATTR
SNR_FGETXATTR ScmpSyscall = SYS_FGETXATTR
SNR_LISTXATTR ScmpSyscall = SYS_LISTXATTR
SNR_LLISTXATTR ScmpSyscall = SYS_LLISTXATTR
SNR_FLISTXATTR ScmpSyscall = SYS_FLISTXATTR
SNR_REMOVEXATTR ScmpSyscall = SYS_REMOVEXATTR
SNR_LREMOVEXATTR ScmpSyscall = SYS_LREMOVEXATTR
SNR_FREMOVEXATTR ScmpSyscall = SYS_FREMOVEXATTR
SNR_GETCWD ScmpSyscall = SYS_GETCWD
SNR_LOOKUP_DCOOKIE ScmpSyscall = SYS_LOOKUP_DCOOKIE
SNR_EVENTFD2 ScmpSyscall = SYS_EVENTFD2
SNR_EPOLL_CREATE1 ScmpSyscall = SYS_EPOLL_CREATE1
SNR_EPOLL_CTL ScmpSyscall = SYS_EPOLL_CTL
SNR_EPOLL_PWAIT ScmpSyscall = SYS_EPOLL_PWAIT
SNR_DUP ScmpSyscall = SYS_DUP
SNR_DUP3 ScmpSyscall = SYS_DUP3
SNR_FCNTL ScmpSyscall = SYS_FCNTL
SNR_INOTIFY_INIT1 ScmpSyscall = SYS_INOTIFY_INIT1
SNR_INOTIFY_ADD_WATCH ScmpSyscall = SYS_INOTIFY_ADD_WATCH
SNR_INOTIFY_RM_WATCH ScmpSyscall = SYS_INOTIFY_RM_WATCH
SNR_IOCTL ScmpSyscall = SYS_IOCTL
SNR_IOPRIO_SET ScmpSyscall = SYS_IOPRIO_SET
SNR_IOPRIO_GET ScmpSyscall = SYS_IOPRIO_GET
SNR_FLOCK ScmpSyscall = SYS_FLOCK
SNR_MKNODAT ScmpSyscall = SYS_MKNODAT
SNR_MKDIRAT ScmpSyscall = SYS_MKDIRAT
SNR_UNLINKAT ScmpSyscall = SYS_UNLINKAT
SNR_SYMLINKAT ScmpSyscall = SYS_SYMLINKAT
SNR_LINKAT ScmpSyscall = SYS_LINKAT
SNR_RENAMEAT ScmpSyscall = SYS_RENAMEAT
SNR_UMOUNT2 ScmpSyscall = SYS_UMOUNT2
SNR_MOUNT ScmpSyscall = SYS_MOUNT
SNR_PIVOT_ROOT ScmpSyscall = SYS_PIVOT_ROOT
SNR_NFSSERVCTL ScmpSyscall = SYS_NFSSERVCTL
SNR_STATFS ScmpSyscall = SYS_STATFS
SNR_FSTATFS ScmpSyscall = SYS_FSTATFS
SNR_TRUNCATE ScmpSyscall = SYS_TRUNCATE
SNR_FTRUNCATE ScmpSyscall = SYS_FTRUNCATE
SNR_FALLOCATE ScmpSyscall = SYS_FALLOCATE
SNR_FACCESSAT ScmpSyscall = SYS_FACCESSAT
SNR_CHDIR ScmpSyscall = SYS_CHDIR
SNR_FCHDIR ScmpSyscall = SYS_FCHDIR
SNR_CHROOT ScmpSyscall = SYS_CHROOT
SNR_FCHMOD ScmpSyscall = SYS_FCHMOD
SNR_FCHMODAT ScmpSyscall = SYS_FCHMODAT
SNR_FCHOWNAT ScmpSyscall = SYS_FCHOWNAT
SNR_FCHOWN ScmpSyscall = SYS_FCHOWN
SNR_OPENAT ScmpSyscall = SYS_OPENAT
SNR_CLOSE ScmpSyscall = SYS_CLOSE
SNR_VHANGUP ScmpSyscall = SYS_VHANGUP
SNR_PIPE2 ScmpSyscall = SYS_PIPE2
SNR_QUOTACTL ScmpSyscall = SYS_QUOTACTL
SNR_GETDENTS64 ScmpSyscall = SYS_GETDENTS64
SNR_LSEEK ScmpSyscall = SYS_LSEEK
SNR_READ ScmpSyscall = SYS_READ
SNR_WRITE ScmpSyscall = SYS_WRITE
SNR_READV ScmpSyscall = SYS_READV
SNR_WRITEV ScmpSyscall = SYS_WRITEV
SNR_PREAD64 ScmpSyscall = SYS_PREAD64
SNR_PWRITE64 ScmpSyscall = SYS_PWRITE64
SNR_PREADV ScmpSyscall = SYS_PREADV
SNR_PWRITEV ScmpSyscall = SYS_PWRITEV
SNR_SENDFILE ScmpSyscall = SYS_SENDFILE
SNR_PSELECT6 ScmpSyscall = SYS_PSELECT6
SNR_PPOLL ScmpSyscall = SYS_PPOLL
SNR_SIGNALFD4 ScmpSyscall = SYS_SIGNALFD4
SNR_VMSPLICE ScmpSyscall = SYS_VMSPLICE
SNR_SPLICE ScmpSyscall = SYS_SPLICE
SNR_TEE ScmpSyscall = SYS_TEE
SNR_READLINKAT ScmpSyscall = SYS_READLINKAT
SNR_NEWFSTATAT ScmpSyscall = SYS_NEWFSTATAT
SNR_FSTAT ScmpSyscall = SYS_FSTAT
SNR_SYNC ScmpSyscall = SYS_SYNC
SNR_FSYNC ScmpSyscall = SYS_FSYNC
SNR_FDATASYNC ScmpSyscall = SYS_FDATASYNC
SNR_SYNC_FILE_RANGE ScmpSyscall = SYS_SYNC_FILE_RANGE
SNR_TIMERFD_CREATE ScmpSyscall = SYS_TIMERFD_CREATE
SNR_TIMERFD_SETTIME ScmpSyscall = SYS_TIMERFD_SETTIME
SNR_TIMERFD_GETTIME ScmpSyscall = SYS_TIMERFD_GETTIME
SNR_UTIMENSAT ScmpSyscall = SYS_UTIMENSAT
SNR_ACCT ScmpSyscall = SYS_ACCT
SNR_CAPGET ScmpSyscall = SYS_CAPGET
SNR_CAPSET ScmpSyscall = SYS_CAPSET
SNR_PERSONALITY ScmpSyscall = SYS_PERSONALITY
SNR_EXIT ScmpSyscall = SYS_EXIT
SNR_EXIT_GROUP ScmpSyscall = SYS_EXIT_GROUP
SNR_WAITID ScmpSyscall = SYS_WAITID
SNR_SET_TID_ADDRESS ScmpSyscall = SYS_SET_TID_ADDRESS
SNR_UNSHARE ScmpSyscall = SYS_UNSHARE
SNR_FUTEX ScmpSyscall = SYS_FUTEX
SNR_SET_ROBUST_LIST ScmpSyscall = SYS_SET_ROBUST_LIST
SNR_GET_ROBUST_LIST ScmpSyscall = SYS_GET_ROBUST_LIST
SNR_NANOSLEEP ScmpSyscall = SYS_NANOSLEEP
SNR_GETITIMER ScmpSyscall = SYS_GETITIMER
SNR_SETITIMER ScmpSyscall = SYS_SETITIMER
SNR_KEXEC_LOAD ScmpSyscall = SYS_KEXEC_LOAD
SNR_INIT_MODULE ScmpSyscall = SYS_INIT_MODULE
SNR_DELETE_MODULE ScmpSyscall = SYS_DELETE_MODULE
SNR_TIMER_CREATE ScmpSyscall = SYS_TIMER_CREATE
SNR_TIMER_GETTIME ScmpSyscall = SYS_TIMER_GETTIME
SNR_TIMER_GETOVERRUN ScmpSyscall = SYS_TIMER_GETOVERRUN
SNR_TIMER_SETTIME ScmpSyscall = SYS_TIMER_SETTIME
SNR_TIMER_DELETE ScmpSyscall = SYS_TIMER_DELETE
SNR_CLOCK_SETTIME ScmpSyscall = SYS_CLOCK_SETTIME
SNR_CLOCK_GETTIME ScmpSyscall = SYS_CLOCK_GETTIME
SNR_CLOCK_GETRES ScmpSyscall = SYS_CLOCK_GETRES
SNR_CLOCK_NANOSLEEP ScmpSyscall = SYS_CLOCK_NANOSLEEP
SNR_SYSLOG ScmpSyscall = SYS_SYSLOG
SNR_PTRACE ScmpSyscall = SYS_PTRACE
SNR_SCHED_SETPARAM ScmpSyscall = SYS_SCHED_SETPARAM
SNR_SCHED_SETSCHEDULER ScmpSyscall = SYS_SCHED_SETSCHEDULER
SNR_SCHED_GETSCHEDULER ScmpSyscall = SYS_SCHED_GETSCHEDULER
SNR_SCHED_GETPARAM ScmpSyscall = SYS_SCHED_GETPARAM
SNR_SCHED_SETAFFINITY ScmpSyscall = SYS_SCHED_SETAFFINITY
SNR_SCHED_GETAFFINITY ScmpSyscall = SYS_SCHED_GETAFFINITY
SNR_SCHED_YIELD ScmpSyscall = SYS_SCHED_YIELD
SNR_SCHED_GET_PRIORITY_MAX ScmpSyscall = SYS_SCHED_GET_PRIORITY_MAX
SNR_SCHED_GET_PRIORITY_MIN ScmpSyscall = SYS_SCHED_GET_PRIORITY_MIN
SNR_SCHED_RR_GET_INTERVAL ScmpSyscall = SYS_SCHED_RR_GET_INTERVAL
SNR_RESTART_SYSCALL ScmpSyscall = SYS_RESTART_SYSCALL
SNR_KILL ScmpSyscall = SYS_KILL
SNR_TKILL ScmpSyscall = SYS_TKILL
SNR_TGKILL ScmpSyscall = SYS_TGKILL
SNR_SIGALTSTACK ScmpSyscall = SYS_SIGALTSTACK
SNR_RT_SIGSUSPEND ScmpSyscall = SYS_RT_SIGSUSPEND
SNR_RT_SIGACTION ScmpSyscall = SYS_RT_SIGACTION
SNR_RT_SIGPROCMASK ScmpSyscall = SYS_RT_SIGPROCMASK
SNR_RT_SIGPENDING ScmpSyscall = SYS_RT_SIGPENDING
SNR_RT_SIGTIMEDWAIT ScmpSyscall = SYS_RT_SIGTIMEDWAIT
SNR_RT_SIGQUEUEINFO ScmpSyscall = SYS_RT_SIGQUEUEINFO
SNR_RT_SIGRETURN ScmpSyscall = SYS_RT_SIGRETURN
SNR_SETPRIORITY ScmpSyscall = SYS_SETPRIORITY
SNR_GETPRIORITY ScmpSyscall = SYS_GETPRIORITY
SNR_REBOOT ScmpSyscall = SYS_REBOOT
SNR_SETREGID ScmpSyscall = SYS_SETREGID
SNR_SETGID ScmpSyscall = SYS_SETGID
SNR_SETREUID ScmpSyscall = SYS_SETREUID
SNR_SETUID ScmpSyscall = SYS_SETUID
SNR_SETRESUID ScmpSyscall = SYS_SETRESUID
SNR_GETRESUID ScmpSyscall = SYS_GETRESUID
SNR_SETRESGID ScmpSyscall = SYS_SETRESGID
SNR_GETRESGID ScmpSyscall = SYS_GETRESGID
SNR_SETFSUID ScmpSyscall = SYS_SETFSUID
SNR_SETFSGID ScmpSyscall = SYS_SETFSGID
SNR_TIMES ScmpSyscall = SYS_TIMES
SNR_SETPGID ScmpSyscall = SYS_SETPGID
SNR_GETPGID ScmpSyscall = SYS_GETPGID
SNR_GETSID ScmpSyscall = SYS_GETSID
SNR_SETSID ScmpSyscall = SYS_SETSID
SNR_GETGROUPS ScmpSyscall = SYS_GETGROUPS
SNR_SETGROUPS ScmpSyscall = SYS_SETGROUPS
SNR_UNAME ScmpSyscall = SYS_UNAME
SNR_SETHOSTNAME ScmpSyscall = SYS_SETHOSTNAME
SNR_SETDOMAINNAME ScmpSyscall = SYS_SETDOMAINNAME
SNR_GETRLIMIT ScmpSyscall = SYS_GETRLIMIT
SNR_SETRLIMIT ScmpSyscall = SYS_SETRLIMIT
SNR_GETRUSAGE ScmpSyscall = SYS_GETRUSAGE
SNR_UMASK ScmpSyscall = SYS_UMASK
SNR_PRCTL ScmpSyscall = SYS_PRCTL
SNR_GETCPU ScmpSyscall = SYS_GETCPU
SNR_GETTIMEOFDAY ScmpSyscall = SYS_GETTIMEOFDAY
SNR_SETTIMEOFDAY ScmpSyscall = SYS_SETTIMEOFDAY
SNR_ADJTIMEX ScmpSyscall = SYS_ADJTIMEX
SNR_GETPID ScmpSyscall = SYS_GETPID
SNR_GETPPID ScmpSyscall = SYS_GETPPID
SNR_GETUID ScmpSyscall = SYS_GETUID
SNR_GETEUID ScmpSyscall = SYS_GETEUID
SNR_GETGID ScmpSyscall = SYS_GETGID
SNR_GETEGID ScmpSyscall = SYS_GETEGID
SNR_GETTID ScmpSyscall = SYS_GETTID
SNR_SYSINFO ScmpSyscall = SYS_SYSINFO
SNR_MQ_OPEN ScmpSyscall = SYS_MQ_OPEN
SNR_MQ_UNLINK ScmpSyscall = SYS_MQ_UNLINK
SNR_MQ_TIMEDSEND ScmpSyscall = SYS_MQ_TIMEDSEND
SNR_MQ_TIMEDRECEIVE ScmpSyscall = SYS_MQ_TIMEDRECEIVE
SNR_MQ_NOTIFY ScmpSyscall = SYS_MQ_NOTIFY
SNR_MQ_GETSETATTR ScmpSyscall = SYS_MQ_GETSETATTR
SNR_MSGGET ScmpSyscall = SYS_MSGGET
SNR_MSGCTL ScmpSyscall = SYS_MSGCTL
SNR_MSGRCV ScmpSyscall = SYS_MSGRCV
SNR_MSGSND ScmpSyscall = SYS_MSGSND
SNR_SEMGET ScmpSyscall = SYS_SEMGET
SNR_SEMCTL ScmpSyscall = SYS_SEMCTL
SNR_SEMTIMEDOP ScmpSyscall = SYS_SEMTIMEDOP
SNR_SEMOP ScmpSyscall = SYS_SEMOP
SNR_SHMGET ScmpSyscall = SYS_SHMGET
SNR_SHMCTL ScmpSyscall = SYS_SHMCTL
SNR_SHMAT ScmpSyscall = SYS_SHMAT
SNR_SHMDT ScmpSyscall = SYS_SHMDT
SNR_SOCKET ScmpSyscall = SYS_SOCKET
SNR_SOCKETPAIR ScmpSyscall = SYS_SOCKETPAIR
SNR_BIND ScmpSyscall = SYS_BIND
SNR_LISTEN ScmpSyscall = SYS_LISTEN
SNR_ACCEPT ScmpSyscall = SYS_ACCEPT
SNR_CONNECT ScmpSyscall = SYS_CONNECT
SNR_GETSOCKNAME ScmpSyscall = SYS_GETSOCKNAME
SNR_GETPEERNAME ScmpSyscall = SYS_GETPEERNAME
SNR_SENDTO ScmpSyscall = SYS_SENDTO
SNR_RECVFROM ScmpSyscall = SYS_RECVFROM
SNR_SETSOCKOPT ScmpSyscall = SYS_SETSOCKOPT
SNR_GETSOCKOPT ScmpSyscall = SYS_GETSOCKOPT
SNR_SHUTDOWN ScmpSyscall = SYS_SHUTDOWN
SNR_SENDMSG ScmpSyscall = SYS_SENDMSG
SNR_RECVMSG ScmpSyscall = SYS_RECVMSG
SNR_READAHEAD ScmpSyscall = SYS_READAHEAD
SNR_BRK ScmpSyscall = SYS_BRK
SNR_MUNMAP ScmpSyscall = SYS_MUNMAP
SNR_MREMAP ScmpSyscall = SYS_MREMAP
SNR_ADD_KEY ScmpSyscall = SYS_ADD_KEY
SNR_REQUEST_KEY ScmpSyscall = SYS_REQUEST_KEY
SNR_KEYCTL ScmpSyscall = SYS_KEYCTL
SNR_CLONE ScmpSyscall = SYS_CLONE
SNR_EXECVE ScmpSyscall = SYS_EXECVE
SNR_MMAP ScmpSyscall = SYS_MMAP
SNR_FADVISE64 ScmpSyscall = SYS_FADVISE64
SNR_SWAPON ScmpSyscall = SYS_SWAPON
SNR_SWAPOFF ScmpSyscall = SYS_SWAPOFF
SNR_MPROTECT ScmpSyscall = SYS_MPROTECT
SNR_MSYNC ScmpSyscall = SYS_MSYNC
SNR_MLOCK ScmpSyscall = SYS_MLOCK
SNR_MUNLOCK ScmpSyscall = SYS_MUNLOCK
SNR_MLOCKALL ScmpSyscall = SYS_MLOCKALL
SNR_MUNLOCKALL ScmpSyscall = SYS_MUNLOCKALL
SNR_MINCORE ScmpSyscall = SYS_MINCORE
SNR_MADVISE ScmpSyscall = SYS_MADVISE
SNR_REMAP_FILE_PAGES ScmpSyscall = SYS_REMAP_FILE_PAGES
SNR_MBIND ScmpSyscall = SYS_MBIND
SNR_GET_MEMPOLICY ScmpSyscall = SYS_GET_MEMPOLICY
SNR_SET_MEMPOLICY ScmpSyscall = SYS_SET_MEMPOLICY
SNR_MIGRATE_PAGES ScmpSyscall = SYS_MIGRATE_PAGES
SNR_MOVE_PAGES ScmpSyscall = SYS_MOVE_PAGES
SNR_RT_TGSIGQUEUEINFO ScmpSyscall = SYS_RT_TGSIGQUEUEINFO
SNR_PERF_EVENT_OPEN ScmpSyscall = SYS_PERF_EVENT_OPEN
SNR_ACCEPT4 ScmpSyscall = SYS_ACCEPT4
SNR_RECVMMSG ScmpSyscall = SYS_RECVMMSG
SNR_WAIT4 ScmpSyscall = SYS_WAIT4
SNR_PRLIMIT64 ScmpSyscall = SYS_PRLIMIT64
SNR_FANOTIFY_INIT ScmpSyscall = SYS_FANOTIFY_INIT
SNR_FANOTIFY_MARK ScmpSyscall = SYS_FANOTIFY_MARK
SNR_NAME_TO_HANDLE_AT ScmpSyscall = SYS_NAME_TO_HANDLE_AT
SNR_OPEN_BY_HANDLE_AT ScmpSyscall = SYS_OPEN_BY_HANDLE_AT
SNR_CLOCK_ADJTIME ScmpSyscall = SYS_CLOCK_ADJTIME
SNR_SYNCFS ScmpSyscall = SYS_SYNCFS
SNR_SETNS ScmpSyscall = SYS_SETNS
SNR_SENDMMSG ScmpSyscall = SYS_SENDMMSG
SNR_PROCESS_VM_READV ScmpSyscall = SYS_PROCESS_VM_READV
SNR_PROCESS_VM_WRITEV ScmpSyscall = SYS_PROCESS_VM_WRITEV
SNR_KCMP ScmpSyscall = SYS_KCMP
SNR_FINIT_MODULE ScmpSyscall = SYS_FINIT_MODULE
SNR_SCHED_SETATTR ScmpSyscall = SYS_SCHED_SETATTR
SNR_SCHED_GETATTR ScmpSyscall = SYS_SCHED_GETATTR
SNR_RENAMEAT2 ScmpSyscall = SYS_RENAMEAT2
SNR_SECCOMP ScmpSyscall = SYS_SECCOMP
SNR_GETRANDOM ScmpSyscall = SYS_GETRANDOM
SNR_MEMFD_CREATE ScmpSyscall = SYS_MEMFD_CREATE
SNR_BPF ScmpSyscall = SYS_BPF
SNR_EXECVEAT ScmpSyscall = SYS_EXECVEAT
SNR_USERFAULTFD ScmpSyscall = SYS_USERFAULTFD
SNR_MEMBARRIER ScmpSyscall = SYS_MEMBARRIER
SNR_MLOCK2 ScmpSyscall = SYS_MLOCK2
SNR_COPY_FILE_RANGE ScmpSyscall = SYS_COPY_FILE_RANGE
SNR_PREADV2 ScmpSyscall = SYS_PREADV2
SNR_PWRITEV2 ScmpSyscall = SYS_PWRITEV2
SNR_PKEY_MPROTECT ScmpSyscall = SYS_PKEY_MPROTECT
SNR_PKEY_ALLOC ScmpSyscall = SYS_PKEY_ALLOC
SNR_PKEY_FREE ScmpSyscall = SYS_PKEY_FREE
SNR_STATX ScmpSyscall = SYS_STATX
SNR_IO_PGETEVENTS ScmpSyscall = SYS_IO_PGETEVENTS
SNR_RSEQ ScmpSyscall = SYS_RSEQ
SNR_KEXEC_FILE_LOAD ScmpSyscall = SYS_KEXEC_FILE_LOAD
SNR_PIDFD_SEND_SIGNAL ScmpSyscall = SYS_PIDFD_SEND_SIGNAL
SNR_IO_URING_SETUP ScmpSyscall = SYS_IO_URING_SETUP
SNR_IO_URING_ENTER ScmpSyscall = SYS_IO_URING_ENTER
SNR_IO_URING_REGISTER ScmpSyscall = SYS_IO_URING_REGISTER
SNR_OPEN_TREE ScmpSyscall = SYS_OPEN_TREE
SNR_MOVE_MOUNT ScmpSyscall = SYS_MOVE_MOUNT
SNR_FSOPEN ScmpSyscall = SYS_FSOPEN
SNR_FSCONFIG ScmpSyscall = SYS_FSCONFIG
SNR_FSMOUNT ScmpSyscall = SYS_FSMOUNT
SNR_FSPICK ScmpSyscall = SYS_FSPICK
SNR_PIDFD_OPEN ScmpSyscall = SYS_PIDFD_OPEN
SNR_CLONE3 ScmpSyscall = SYS_CLONE3
SNR_CLOSE_RANGE ScmpSyscall = SYS_CLOSE_RANGE
SNR_OPENAT2 ScmpSyscall = SYS_OPENAT2
SNR_PIDFD_GETFD ScmpSyscall = SYS_PIDFD_GETFD
SNR_FACCESSAT2 ScmpSyscall = SYS_FACCESSAT2
SNR_PROCESS_MADVISE ScmpSyscall = SYS_PROCESS_MADVISE
SNR_EPOLL_PWAIT2 ScmpSyscall = SYS_EPOLL_PWAIT2
SNR_MOUNT_SETATTR ScmpSyscall = SYS_MOUNT_SETATTR
SNR_QUOTACTL_FD ScmpSyscall = SYS_QUOTACTL_FD
SNR_LANDLOCK_CREATE_RULESET ScmpSyscall = SYS_LANDLOCK_CREATE_RULESET
SNR_LANDLOCK_ADD_RULE ScmpSyscall = SYS_LANDLOCK_ADD_RULE
SNR_LANDLOCK_RESTRICT_SELF ScmpSyscall = SYS_LANDLOCK_RESTRICT_SELF
SNR_MEMFD_SECRET ScmpSyscall = SYS_MEMFD_SECRET
SNR_PROCESS_MRELEASE ScmpSyscall = SYS_PROCESS_MRELEASE
SNR_FUTEX_WAITV ScmpSyscall = SYS_FUTEX_WAITV
SNR_SET_MEMPOLICY_HOME_NODE ScmpSyscall = SYS_SET_MEMPOLICY_HOME_NODE
SNR_CACHESTAT ScmpSyscall = SYS_CACHESTAT
SNR_FCHMODAT2 ScmpSyscall = SYS_FCHMODAT2
SNR_MAP_SHADOW_STACK ScmpSyscall = SYS_MAP_SHADOW_STACK
SNR_FUTEX_WAKE ScmpSyscall = SYS_FUTEX_WAKE
SNR_FUTEX_WAIT ScmpSyscall = SYS_FUTEX_WAIT
SNR_FUTEX_REQUEUE ScmpSyscall = SYS_FUTEX_REQUEUE
SNR_STATMOUNT ScmpSyscall = SYS_STATMOUNT
SNR_LISTMOUNT ScmpSyscall = SYS_LISTMOUNT
SNR_LSM_GET_SELF_ATTR ScmpSyscall = SYS_LSM_GET_SELF_ATTR
SNR_LSM_SET_SELF_ATTR ScmpSyscall = SYS_LSM_SET_SELF_ATTR
SNR_LSM_LIST_MODULES ScmpSyscall = SYS_LSM_LIST_MODULES
SNR_MSEAL ScmpSyscall = SYS_MSEAL
)

View File

@ -2,13 +2,15 @@ package stub_test
import (
"testing"
_ "unsafe"
_ "unsafe" // for go:linkname
"hakurei.app/container/stub"
)
// Made available here to check panic recovery behaviour.
//
//go:linkname handleExitNew hakurei.app/container/stub.handleExitNew
func handleExitNew(_ testing.TB)
func handleExitNew(t testing.TB)
// overrideTFailNow overrides the Fail and FailNow method.
type overrideTFailNow struct {

6
dist/release.sh vendored
View File

@ -10,9 +10,9 @@ cp -rv "dist/comp" "${out}"
go generate ./...
go build -trimpath -v -o "${out}/bin/" -ldflags "-s -w -buildid= -extldflags '-static'
-X hakurei.app/internal.buildVersion=${VERSION}
-X hakurei.app/internal.hakureiPath=/usr/bin/hakurei
-X hakurei.app/internal.hsuPath=/usr/bin/hsu
-X hakurei.app/internal/info.buildVersion=${VERSION}
-X hakurei.app/internal/info.hakureiPath=/usr/bin/hakurei
-X hakurei.app/internal/info.hsuPath=/usr/bin/hsu
-X main.hakureiPath=/usr/bin/hakurei" ./...
rm -f "./${out}.tar.gz" && tar -C dist -czf "${out}.tar.gz" "${pname}"

View File

@ -114,7 +114,7 @@
inherit (pkgs)
# passthru.buildInputs
go
gcc
clang
# nativeBuildInputs
pkg-config
@ -129,6 +129,10 @@
zstd
gnutar
coreutils
# for check
util-linux
nettools
;
};
hsu = pkgs.callPackage ./cmd/hsu/package.nix { inherit (self.packages.${system}) hakurei; };
@ -144,7 +148,7 @@
&& chmod -R +w .
export HAKUREI_VERSION="v${hakurei.version}"
./dist/release.sh && mkdir $out && cp -v "dist/hakurei-$HAKUREI_VERSION.tar.gz"* $out
CC="clang -O3 -Werror" ./dist/release.sh && mkdir $out && cp -v "dist/hakurei-$HAKUREI_VERSION.tar.gz"* $out
'';
}
);

73
helper/deprecated.go Normal file
View File

@ -0,0 +1,73 @@
// Package helper exposes the internal/helper package.
//
// Deprecated: This package will be removed in 0.4.
package helper
import (
"context"
"io"
"os"
"os/exec"
"time"
_ "unsafe" // for go:linkname
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/internal/helper"
"hakurei.app/message"
)
//go:linkname WaitDelay hakurei.app/internal/helper.WaitDelay
var WaitDelay time.Duration
const (
// HakureiHelper is set to 1 when args fd is enabled and 0 otherwise.
HakureiHelper = helper.HakureiHelper
// HakureiStatus is set to 1 when stat fd is enabled and 0 otherwise.
HakureiStatus = helper.HakureiStatus
)
type Helper = helper.Helper
// NewCheckedArgs returns a checked null-terminated argument writer for a copy of args.
//
//go:linkname NewCheckedArgs hakurei.app/internal/helper.NewCheckedArgs
func NewCheckedArgs(args ...string) (wt io.WriterTo, err error)
// MustNewCheckedArgs returns a checked null-terminated argument writer for a copy of args.
// If s contains a NUL byte this function panics instead of returning an error.
//
//go:linkname MustNewCheckedArgs hakurei.app/internal/helper.MustNewCheckedArgs
func MustNewCheckedArgs(args ...string) io.WriterTo
// NewDirect initialises a new direct Helper instance with wt as the null-terminated argument writer.
// Function argF returns an array of arguments passed directly to the child process.
//
//go:linkname NewDirect hakurei.app/internal/helper.NewDirect
func NewDirect(
ctx context.Context,
name string,
wt io.WriterTo,
stat bool,
argF func(argsFd, statFd int) []string,
cmdF func(cmd *exec.Cmd),
extraFiles []*os.File,
) Helper
// New initialises a Helper instance with wt as the null-terminated argument writer.
//
//go:linkname New hakurei.app/internal/helper.New
func New(
ctx context.Context,
msg message.Msg,
pathname *check.Absolute, name string,
wt io.WriterTo,
stat bool,
argF func(argsFd, statFd int) []string,
cmdF func(z *container.Container),
extraFiles []*os.File,
) Helper
// InternalHelperStub is an internal function but exported because it is cross-package;
// it is part of the implementation of the helper stub.
func InternalHelperStub() { helper.InternalHelperStub() }

63
helper/proc/deprecated.go Normal file
View File

@ -0,0 +1,63 @@
// Deprecated: This package will be removed in 0.4.
package proc
import (
"context"
"io"
"os"
"os/exec"
"time"
_ "unsafe" // for go:linkname
"hakurei.app/internal/helper/proc"
)
//go:linkname FulfillmentTimeout hakurei.app/internal/helper/proc.FulfillmentTimeout
var FulfillmentTimeout time.Duration
// A File is an extra file with deferred initialisation.
type File = proc.File
// ExtraFilesPre is a linked list storing addresses of [os.File].
type ExtraFilesPre = proc.ExtraFilesPre
// Fulfill calls the [File.Fulfill] method on all files, starts cmd and blocks until all fulfillment completes.
//
//go:linkname Fulfill hakurei.app/internal/helper/proc.Fulfill
func Fulfill(ctx context.Context,
v *[]*os.File, start func() error,
files []File, extraFiles *ExtraFilesPre,
) (err error)
// InitFile initialises f as part of the slice extraFiles points to,
// and returns its final fd value.
//
//go:linkname InitFile hakurei.app/internal/helper/proc.InitFile
func InitFile(f File, extraFiles *ExtraFilesPre) (fd uintptr)
// BaseFile implements the Init method of the File interface and provides indirect access to extra file state.
type BaseFile = proc.BaseFile
//go:linkname ExtraFile hakurei.app/internal/helper/proc.ExtraFile
func ExtraFile(cmd *exec.Cmd, f *os.File) (fd uintptr)
//go:linkname ExtraFileSlice hakurei.app/internal/helper/proc.ExtraFileSlice
func ExtraFileSlice(extraFiles *[]*os.File, f *os.File) (fd uintptr)
// NewWriterTo returns a [File] that receives content from wt on fulfillment.
//
//go:linkname NewWriterTo hakurei.app/internal/helper/proc.NewWriterTo
func NewWriterTo(wt io.WriterTo) File
// NewStat returns a [File] implementing the behaviour
// of the receiving end of xdg-dbus-proxy stat fd.
//
//go:linkname NewStat hakurei.app/internal/helper/proc.NewStat
func NewStat(s *io.Closer) File
var (
//go:linkname ErrStatFault hakurei.app/internal/helper/proc.ErrStatFault
ErrStatFault error
//go:linkname ErrStatRead hakurei.app/internal/helper/proc.ErrStatRead
ErrStatRead error
)

View File

@ -6,11 +6,13 @@ import (
"reflect"
"testing"
"time"
_ "unsafe"
_ "unsafe" // for go:linkname
"hakurei.app/hst"
)
// Made available here to check time encoding behaviour of [hst.ID].
//
//go:linkname newInstanceID hakurei.app/hst.newInstanceID
func newInstanceID(id *hst.ID, p uint64) error

View File

@ -13,7 +13,7 @@ import (
"strconv"
"testing"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
)
const testFileName = "acl.test"

View File

@ -0,0 +1,90 @@
#include "libacl-helper.h"
#include <acl/libacl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/acl.h>
int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
acl_perm_t *perms, size_t plen) {
int ret;
bool v;
int i;
acl_t acl;
acl_entry_t entry;
acl_tag_t tag_type;
void *qualifier_p;
acl_permset_t permset;
ret = -1; /* acl_get_file */
acl = acl_get_file(path_p, ACL_TYPE_ACCESS);
if (acl == NULL)
goto out;
/* prune entries by uid */
for (i = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); i == 1;
i = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
ret = -2; /* acl_get_tag_type */
if (acl_get_tag_type(entry, &tag_type) != 0)
goto out;
if (tag_type != ACL_USER)
continue;
ret = -3; /* acl_get_qualifier */
qualifier_p = acl_get_qualifier(entry);
if (qualifier_p == NULL)
goto out;
v = *(uid_t *)qualifier_p == uid;
acl_free(qualifier_p);
if (!v)
continue;
ret = -4; /* acl_delete_entry */
if (acl_delete_entry(acl, entry) != 0)
goto out;
}
if (plen == 0)
goto set;
ret = -5; /* acl_create_entry */
if (acl_create_entry(&acl, &entry) != 0)
goto out;
ret = -6; /* acl_get_permset */
if (acl_get_permset(entry, &permset) != 0)
goto out;
ret = -7; /* acl_add_perm */
for (i = 0; i < plen; i++) {
if (acl_add_perm(permset, perms[i]) != 0)
goto out;
}
ret = -8; /* acl_set_tag_type */
if (acl_set_tag_type(entry, ACL_USER) != 0)
goto out;
ret = -9; /* acl_set_qualifier */
if (acl_set_qualifier(entry, (void *)&uid) != 0)
goto out;
set:
ret = -10; /* acl_calc_mask */
if (acl_calc_mask(&acl) != 0)
goto out;
ret = -11; /* acl_valid */
if (acl_valid(acl) != 0)
goto out;
ret = -12; /* acl_set_file */
if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) == 0)
ret = 0;
out:
free((void *)path_p);
if (acl != NULL)
acl_free((void *)acl);
return ret;
}

View File

@ -3,7 +3,7 @@ package acl_test
import (
"testing"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
)
func TestPerms(t *testing.T) {

View File

@ -5,7 +5,7 @@ import (
"reflect"
"testing"
"hakurei.app/system/dbus"
"hakurei.app/internal/dbus"
)
func TestParse(t *testing.T) {

View File

@ -7,7 +7,7 @@ import (
"testing"
"hakurei.app/hst"
"hakurei.app/system/dbus"
"hakurei.app/internal/dbus"
)
func TestConfigArgs(t *testing.T) {

View File

@ -11,9 +11,9 @@ import (
"testing"
"time"
"hakurei.app/helper"
"hakurei.app/internal/dbus"
"hakurei.app/internal/helper"
"hakurei.app/message"
"hakurei.app/system/dbus"
)
func TestFinalise(t *testing.T) {

View File

@ -12,7 +12,7 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/helper"
"hakurei.app/internal/helper"
"hakurei.app/ldd"
)
@ -54,7 +54,7 @@ func (p *Proxy) Start() error {
}
var libPaths []*check.Absolute
if entries, err := ldd.Exec(ctx, p.msg, toolPath.String()); err != nil {
if entries, err := ldd.Resolve(ctx, p.msg, toolPath); err != nil {
return err
} else {
libPaths = ldd.Path(entries)

View File

@ -5,7 +5,7 @@ import (
"testing"
"hakurei.app/container"
"hakurei.app/helper"
"hakurei.app/internal/helper"
)
func TestMain(m *testing.M) { container.TryArgv0(nil); helper.InternalHelperStub(); os.Exit(m.Run()) }

View File

@ -6,8 +6,8 @@ import (
"sync"
"syscall"
"hakurei.app/helper"
"hakurei.app/hst"
"hakurei.app/internal/helper"
"hakurei.app/message"
)

View File

@ -7,7 +7,7 @@ import (
"syscall"
"testing"
"hakurei.app/helper"
"hakurei.app/internal/helper"
)
func TestArgsString(t *testing.T) {

View File

@ -10,7 +10,7 @@ import (
"sync"
"syscall"
"hakurei.app/helper/proc"
"hakurei.app/internal/helper/proc"
)
// NewDirect initialises a new direct Helper instance with wt as the null-terminated argument writer.

View File

@ -9,7 +9,7 @@ import (
"testing"
"hakurei.app/container"
"hakurei.app/helper"
"hakurei.app/internal/helper"
)
func TestCmd(t *testing.T) {

View File

@ -11,7 +11,7 @@ import (
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/helper/proc"
"hakurei.app/internal/helper/proc"
"hakurei.app/message"
)

View File

@ -9,7 +9,7 @@ import (
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/helper"
"hakurei.app/internal/helper"
)
func TestContainer(t *testing.T) {

View File

@ -8,7 +8,7 @@ import (
"os"
"time"
"hakurei.app/helper/proc"
"hakurei.app/internal/helper/proc"
)
var WaitDelay = 2 * time.Second

View File

@ -13,7 +13,7 @@ import (
"testing"
"time"
"hakurei.app/helper"
"hakurei.app/internal/helper"
)
var (

View File

@ -5,7 +5,7 @@ import (
"testing"
"hakurei.app/container"
"hakurei.app/helper"
"hakurei.app/internal/helper"
)
func TestMain(m *testing.M) { container.TryArgv0(nil); helper.InternalHelperStub(); os.Exit(m.Run()) }

View File

@ -1,4 +1,4 @@
package internal
package info
import (
"log"

View File

@ -1,4 +1,4 @@
package internal
package info
import (
"reflect"

View File

@ -1,4 +1,4 @@
package internal
package info
// FallbackVersion is returned when a version string was not set by the linker.
const FallbackVersion = "dirty"

View File

@ -14,9 +14,9 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/internal"
"hakurei.app/internal/dbus"
"hakurei.app/internal/info"
"hakurei.app/message"
"hakurei.app/system/dbus"
)
// osFile represents [os.File].
@ -156,7 +156,7 @@ func (direct) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) erro
return seccomp.Load(rules, flags)
}
func (direct) mustHsuPath() *check.Absolute { return internal.MustHsuPath() }
func (direct) mustHsuPath() *check.Absolute { return info.MustHsuPath() }
func (direct) dbusAddress() (session, system string) { return dbus.Address() }

View File

@ -24,8 +24,8 @@ import (
"hakurei.app/container/std"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/internal/system"
"hakurei.app/message"
"hakurei.app/system"
)
// call initialises a [stub.Call].

View File

@ -8,8 +8,8 @@ import (
"os/user"
"hakurei.app/hst"
"hakurei.app/internal/system"
"hakurei.app/message"
"hakurei.app/system"
)
func newWithMessage(msg string) error { return newWithMessageError(msg, os.ErrInvalid) }
@ -55,7 +55,7 @@ func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *hst.ID, con
if errors.As(err, &unknownGroupError) {
return newWithMessageError(fmt.Sprintf("unknown group %q", name), unknownGroupError)
} else {
return &hst.AppError{Step: "look up group by name", Err: err}
return &hst.AppError{Step: "look up group by name", Err: err, Msg: err.Error()}
}
} else {
supp[i] = gid

View File

@ -1,30 +0,0 @@
package outcome
import (
"context"
"log"
"time"
"hakurei.app/hst"
"hakurei.app/message"
)
// Main runs an app according to [hst.Config] and terminates. Main does not return.
func Main(ctx context.Context, msg message.Msg, config *hst.Config) {
var id hst.ID
if err := hst.NewInstanceID(&id); err != nil {
log.Fatal(err.Error())
}
seal := outcome{syscallDispatcher: direct{msg}}
finaliseTime := time.Now()
if err := seal.finalise(ctx, msg, &id, config); err != nil {
printMessageError(msg.GetLogger().Fatalln, "cannot seal app:", err)
panic("unreachable")
}
msg.Verbosef("finalise took %.2f ms", float64(time.Since(finaliseTime).Nanoseconds())/1e6)
seal.main(msg)
panic("unreachable")
}

View File

@ -9,10 +9,10 @@ import (
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/hst"
"hakurei.app/internal/acl"
"hakurei.app/internal/env"
"hakurei.app/internal/system"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
)
// envAllocSize is the initial size of the env map pre-allocated when the configured env map is nil.

View File

@ -16,10 +16,10 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/internal"
"hakurei.app/internal/info"
"hakurei.app/internal/store"
"hakurei.app/internal/system"
"hakurei.app/message"
"hakurei.app/system"
)
const (
@ -33,13 +33,13 @@ const (
func NewStore(sc *hst.Paths) *store.Store { return store.New(sc.SharePath.Append("state")) }
// main carries out outcome and terminates. main does not return.
func (k *outcome) main(msg message.Msg) {
func (k *outcome) main(msg message.Msg, identifierFd int) {
if k.ctx == nil || k.sys == nil || k.state == nil {
panic("outcome: did not finalise")
}
// read comp value early for early failure
hsuPath := internal.MustHsuPath()
hsuPath := info.MustHsuPath()
const (
// transitions to processCommit, or processFinal on failure
@ -163,6 +163,21 @@ func (k *outcome) main(msg message.Msg) {
continue
}
if f := os.NewFile(uintptr(identifierFd), "identifier"); f != nil {
_, err = f.Write(k.state.id.v[:])
if err != nil {
unlock()
// transition here to avoid the commit/revert cycle on the doomed instance
perrorFatal(&hst.AppError{Step: "write instance identifier", Err: err},
"write instance identifier", processLifecycle)
continue
}
msg.Verbosef("wrote identifier to %d", identifierFd)
if err = f.Close(); err != nil {
msg.Verbose(err.Error())
}
}
err = k.sys.Commit()
unlock()
if err != nil {

45
internal/outcome/run.go Normal file
View File

@ -0,0 +1,45 @@
package outcome
import (
"context"
"log"
"time"
_ "unsafe" // for go:linkname
"hakurei.app/hst"
"hakurei.app/message"
)
// IsPollDescriptor reports whether fd is the descriptor being used by the poller.
//
// Made available here to determine and reject impossible fd.
//
//go:linkname IsPollDescriptor internal/poll.IsPollDescriptor
func IsPollDescriptor(fd uintptr) bool
// Main runs an app according to [hst.Config] and terminates. Main does not return.
func Main(ctx context.Context, msg message.Msg, config *hst.Config, fd int) {
// avoids runtime internals or standard streams
if fd >= 0 {
if IsPollDescriptor(uintptr(fd)) || fd < 3 {
log.Fatalf("invalid identifier fd %d", fd)
}
}
var id hst.ID
if err := hst.NewInstanceID(&id); err != nil {
log.Fatal(err.Error())
}
k := outcome{syscallDispatcher: direct{msg}}
finaliseTime := time.Now()
if err := k.finalise(ctx, msg, &id, config); err != nil {
printMessageError(msg.GetLogger().Fatalln, "cannot seal app:", err)
panic("unreachable")
}
msg.Verbosef("finalise took %.2f ms", float64(time.Since(finaliseTime).Nanoseconds())/1e6)
k.main(msg, fd)
panic("unreachable")
}

View File

@ -21,10 +21,10 @@ import (
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst"
"hakurei.app/internal/acl"
"hakurei.app/internal/dbus"
"hakurei.app/internal/system"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/system/dbus"
)
func TestOutcomeMain(t *testing.T) {
@ -141,7 +141,7 @@ func TestOutcomeMain(t *testing.T) {
Proc(fhs.AbsProc).
Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777).
Tmpfs(fhs.AbsDevShm, 0, 01777).
// spRuntimeOp
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).
@ -243,7 +243,7 @@ func TestOutcomeMain(t *testing.T) {
Proc(m("/proc/")).
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
DevWritable(m("/dev/"), true).
Tmpfs(m("/dev/shm"), 0, 01777).
Tmpfs(m("/dev/shm/"), 0, 01777).
Tmpfs(m("/run/user/"), 4096, 0755).
Bind(m("/tmp/hakurei.0/runtime/0"), m("/run/user/65534"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/0"), m("/tmp/"), std.BindWritable).
@ -412,7 +412,7 @@ func TestOutcomeMain(t *testing.T) {
Proc(m("/proc/")).
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
DevWritable(m("/dev/"), true).
Tmpfs(m("/dev/shm"), 0, 01777).
Tmpfs(m("/dev/shm/"), 0, 01777).
Tmpfs(m("/run/user/"), 4096, 0755).
Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/65534"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/9"), m("/tmp/"), std.BindWritable).
@ -558,7 +558,7 @@ func TestOutcomeMain(t *testing.T) {
Proc(m("/proc/")).
Tmpfs(hst.AbsPrivateTmp, 4096, 0755).
DevWritable(m("/dev/"), true).
Tmpfs(m("/dev/shm"), 0, 01777).
Tmpfs(m("/dev/shm/"), 0, 01777).
Tmpfs(m("/run/user/"), 4096, 0755).
Bind(m("/tmp/hakurei.0/runtime/1"), m("/run/user/1971"), std.BindWritable).
Bind(m("/tmp/hakurei.0/tmpdir/1"), m("/tmp/"), std.BindWritable).

View File

@ -38,7 +38,7 @@ static void hakurei_shim_sigaction(int sig, siginfo_t *si, void *ucontext) {
void hakurei_shim_setup_cont_signal(pid_t ppid, int fd) {
if (hakurei_shim_param_ppid != -1 || hakurei_shim_fd != -1)
*(int *)NULL = 0; /* unreachable */
*(volatile int *)NULL = 0; /* unreachable */
struct sigaction new_action = {0}, old_action = {0};
if (sigaction(SIGCONT, NULL, &old_action) != 0)

View File

@ -66,7 +66,7 @@ func TestShimEntrypoint(t *testing.T) {
Proc(fhs.AbsProc).
Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777).
Tmpfs(fhs.AbsDevShm, 0, 01777).
// spRuntimeOp
Tmpfs(fhs.AbsRunUser, 1<<12, 0755).

View File

@ -16,11 +16,11 @@ import (
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst"
"hakurei.app/internal/acl"
"hakurei.app/internal/dbus"
"hakurei.app/internal/system"
"hakurei.app/internal/validate"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/system/dbus"
)
const varRunNscd = fhs.Var + "run/nscd"
@ -116,7 +116,7 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
state.params.Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice)
}
// /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it
state.params.Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777)
state.params.Tmpfs(fhs.AbsDevShm, 0, 01777)
return nil
}

View File

@ -14,9 +14,9 @@ import (
"hakurei.app/container/std"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/system/dbus"
"hakurei.app/internal/acl"
"hakurei.app/internal/dbus"
"hakurei.app/internal/system"
)
func TestSpParamsOp(t *testing.T) {
@ -72,7 +72,7 @@ func TestSpParamsOp(t *testing.T) {
Root(m("/var/lib/hakurei/base/org.debian"), std.BindWritable).
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
DevWritable(fhs.AbsDev, true).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
Tmpfs(fhs.AbsDevShm, 0, 01777),
}, paramsWantEnv(config, map[string]string{
"TERM": "xterm",
}, func(t *testing.T, state *outcomeStateParams) {
@ -110,7 +110,7 @@ func TestSpParamsOp(t *testing.T) {
Root(m("/var/lib/hakurei/base/org.debian"), std.BindWritable).
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
Bind(fhs.AbsDev, fhs.AbsDev, std.BindWritable|std.BindDevice).
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
Tmpfs(fhs.AbsDevShm, 0, 01777),
}, paramsWantEnv(config, map[string]string{
"TERM": "xterm",
}, func(t *testing.T, state *outcomeStateParams) {

View File

@ -5,8 +5,8 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/system/acl"
"hakurei.app/system/dbus"
"hakurei.app/internal/acl"
"hakurei.app/internal/dbus"
)
func init() { gob.Register(new(spDBusOp)) }

View File

@ -6,12 +6,12 @@ import (
"hakurei.app/container"
"hakurei.app/container/stub"
"hakurei.app/helper"
"hakurei.app/hst"
"hakurei.app/internal/acl"
"hakurei.app/internal/dbus"
"hakurei.app/internal/helper"
"hakurei.app/internal/system"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/system/dbus"
)
func TestSpDBusOp(t *testing.T) {

View File

@ -11,8 +11,8 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
"hakurei.app/internal/system"
)
func TestSpPulseOp(t *testing.T) {

View File

@ -7,8 +7,8 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/container/std"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
"hakurei.app/internal/system"
)
const (

View File

@ -8,8 +8,8 @@ import (
"hakurei.app/container/std"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
"hakurei.app/internal/system"
)
func TestSpRuntimeOp(t *testing.T) {

View File

@ -7,8 +7,8 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/container/std"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
"hakurei.app/internal/system"
)
func init() { gob.Register(spTmpdirOp{}) }

View File

@ -8,8 +8,8 @@ import (
"hakurei.app/container/std"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
"hakurei.app/internal/system"
)
func TestSpTmpdirOp(t *testing.T) {

View File

@ -5,8 +5,8 @@ import (
"hakurei.app/container/check"
"hakurei.app/hst"
"hakurei.app/system/acl"
"hakurei.app/system/wayland"
"hakurei.app/internal/acl"
"hakurei.app/internal/wayland"
)
func init() { gob.Register(new(spWaylandOp)) }
@ -25,8 +25,8 @@ func (s *spWaylandOp) toSystem(state *outcomeStateSys) error {
// outer wayland socket (usually `/run/user/%d/wayland-%d`)
var socketPath *check.Absolute
if name, ok := state.k.lookupEnv(wayland.WaylandDisplay); !ok {
state.msg.Verbose(wayland.WaylandDisplay + " is not set, assuming " + wayland.FallbackName)
if name, ok := state.k.lookupEnv(wayland.Display); !ok {
state.msg.Verbose(wayland.Display + " is not set, assuming " + wayland.FallbackName)
socketPath = state.sc.RuntimePath.Append(wayland.FallbackName)
} else if a, err := check.NewAbs(name); err != nil {
socketPath = state.sc.RuntimePath.Append(name)
@ -53,7 +53,7 @@ func (s *spWaylandOp) toSystem(state *outcomeStateSys) error {
func (s *spWaylandOp) toContainer(state *outcomeStateParams) error {
innerPath := state.runtimeDir.Append(wayland.FallbackName)
state.env[wayland.WaylandDisplay] = wayland.FallbackName
state.env[wayland.Display] = wayland.FallbackName
if s.SocketPath == nil {
state.params.Bind(state.instancePath().Append("wayland"), innerPath, 0)
} else {

View File

@ -6,9 +6,9 @@ import (
"hakurei.app/container"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/system"
"hakurei.app/system/acl"
"hakurei.app/system/wayland"
"hakurei.app/internal/acl"
"hakurei.app/internal/system"
"hakurei.app/internal/wayland"
)
func TestSpWaylandOp(t *testing.T) {
@ -47,7 +47,7 @@ func TestSpWaylandOp(t *testing.T) {
Ops: new(container.Ops).
Bind(m(wantInstancePrefix+"/wayland"), m("/run/user/1000/wayland-0"), 0),
}, paramsWantEnv(config, map[string]string{
wayland.WaylandDisplay: wayland.FallbackName,
wayland.Display: wayland.FallbackName,
}, nil), nil},
{"success direct", func(isShim, _ bool) outcomeOp {
@ -75,7 +75,7 @@ func TestSpWaylandOp(t *testing.T) {
Ops: new(container.Ops).
Bind(m("/proc/nonexistent/wayland"), m("/run/user/1000/wayland-0"), 0),
}, paramsWantEnv(config, map[string]string{
wayland.WaylandDisplay: wayland.FallbackName,
wayland.Display: wayland.FallbackName,
}, nil), nil},
{"success", func(bool, bool) outcomeOp {
@ -98,7 +98,7 @@ func TestSpWaylandOp(t *testing.T) {
Ops: new(container.Ops).
Bind(m(wantInstancePrefix+"/wayland"), m("/run/user/1000/wayland-0"), 0),
}, paramsWantEnv(config, map[string]string{
wayland.WaylandDisplay: wayland.FallbackName,
wayland.Display: wayland.FallbackName,
}, nil), nil},
})
}

View File

@ -11,7 +11,7 @@ import (
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
)
var absX11SocketDir = fhs.AbsTmp.Append(".X11-unix")

View File

@ -7,7 +7,7 @@ import (
"hakurei.app/container"
"hakurei.app/container/stub"
"hakurei.app/hst"
"hakurei.app/system/acl"
"hakurei.app/internal/acl"
)
func TestSpX11Op(t *testing.T) {

View File

@ -27,7 +27,7 @@ func TestEntryData(t *testing.T) {
return buf.String()
}
}
templateStateGob := mustEncodeGob(newTemplateState())
templateStateGob := mustEncodeGob(NewTemplateState())
testCases := []struct {
name string
@ -45,11 +45,11 @@ func TestEntryData(t *testing.T) {
Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "invalid configuration"}},
{"inconsistent enablement", "\x00\xff\xca\xfe\x00\x00\xff\x00" + templateStateGob, newTemplateState(), &hst.AppError{
{"inconsistent enablement", "\x00\xff\xca\xfe\x00\x00\xff\x00" + templateStateGob, NewTemplateState(), &hst.AppError{
Step: "validate state enablement", Err: os.ErrInvalid,
Msg: "state entry aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa has unexpected enablement byte 0xd, 0xff"}},
{"template", "\x00\xff\xca\xfe\x00\x00\x0d\xf2" + templateStateGob, newTemplateState(), nil},
{"template", "\x00\xff\xca\xfe\x00\x00\x0d\xf2" + templateStateGob, NewTemplateState(), nil},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
@ -105,7 +105,7 @@ func TestEntryData(t *testing.T) {
t.Run("encode fault", func(t *testing.T) {
t.Parallel()
s := newTemplateState()
s := NewTemplateState()
t.Run("gob", func(t *testing.T) {
var want = &hst.AppError{Step: "encode state body", Err: stub.UniqueError(0xcafe)}
@ -123,8 +123,8 @@ func TestEntryData(t *testing.T) {
})
}
// newTemplateState returns the address of a new template [hst.State] struct.
func newTemplateState() *hst.State {
// NewTemplateState returns the address of a new template [hst.State] struct.
func NewTemplateState() *hst.State {
return &hst.State{
ID: hst.ID(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))),
PID: 0xcafe,

View File

@ -10,7 +10,7 @@ import (
"strings"
"syscall"
"testing"
_ "unsafe"
_ "unsafe" // for go:linkname
"hakurei.app/container/check"
"hakurei.app/container/stub"
@ -18,18 +18,23 @@ import (
"hakurei.app/internal/store"
)
//go:linkname newTemplateState hakurei.app/internal/store.newTemplateState
func newTemplateState() *hst.State
// Made available here for direct validation of state entry files.
//
//go:linkname entryDecode hakurei.app/internal/store.entryDecode
func entryDecode(r io.Reader, p *hst.State) (hst.Enablement, error)
// Made available here for direct access to known segment handles.
//
//go:linkname newHandle hakurei.app/internal/store.newHandle
func newHandle(base *check.Absolute, identity int) *store.Handle
// Made available here to check open error handling behaviour.
//
//go:linkname open hakurei.app/internal/store.(*EntryHandle).open
func open(eh *store.EntryHandle, flag int, perm os.FileMode) (*os.File, error)
// Made available here to check the saveload cycle.
//
//go:linkname save hakurei.app/internal/store.(*EntryHandle).save
func save(eh *store.EntryHandle, state *hst.State) error
@ -91,9 +96,9 @@ func TestStateEntryHandle(t *testing.T) {
t.Run("saveload", func(t *testing.T) {
t.Parallel()
eh := store.EntryHandle{Pathname: check.MustAbs(t.TempDir()).Append("entry"),
ID: newTemplateState().ID}
ID: store.NewTemplateState().ID}
if err := save(&eh, newTemplateState()); err != nil {
if err := save(&eh, store.NewTemplateState()); err != nil {
t.Fatalf("save: error = %v", err)
}
@ -112,7 +117,7 @@ func TestStateEntryHandle(t *testing.T) {
t.Fatal(f.Close())
}
if want := newTemplateState(); !reflect.DeepEqual(&got, want) {
if want := store.NewTemplateState(); !reflect.DeepEqual(&got, want) {
t.Errorf("entryDecode: %#v, want %#v", &got, want)
}
})
@ -122,7 +127,7 @@ func TestStateEntryHandle(t *testing.T) {
if et, err := eh.Load(nil); err != nil {
t.Fatalf("load: error = %v", err)
} else if want := newTemplateState().Enablements.Unwrap(); et != want {
} else if want := store.NewTemplateState().Enablements.Unwrap(); et != want {
t.Errorf("load: et = %x, want %x", et, want)
}
})
@ -133,7 +138,7 @@ func TestStateEntryHandle(t *testing.T) {
var got hst.State
if _, err := eh.Load(&got); err != nil {
t.Fatalf("load: error = %v", err)
} else if want := newTemplateState(); !reflect.DeepEqual(&got, want) {
} else if want := store.NewTemplateState(); !reflect.DeepEqual(&got, want) {
t.Errorf("load: %#v, want %#v", &got, want)
}
})

View File

@ -12,13 +12,15 @@ import (
"syscall"
"testing"
"time"
_ "unsafe"
_ "unsafe" // for go:linkname
"hakurei.app/container/check"
"hakurei.app/hst"
"hakurei.app/internal/store"
)
// Made available here to check bigLock error handling behaviour.
//
//go:linkname bigLock hakurei.app/internal/store.(*Store).bigLock
func bigLock(s *store.Store) (unlock func(), err error)

Some files were not shown because too many files have changed in this diff Show More