3 Commits

Author SHA1 Message Date
mae
d89715c20b cmd/irdump: formatted disassembly 2026-02-08 21:06:22 +09:00
mae
c7ba7f2a31 cmd/irdump: basic disassembler 2026-02-08 21:06:22 +09:00
mae
5db302110f cmd/irdump: create cli 2026-02-08 21:06:22 +09:00
326 changed files with 8878 additions and 39794 deletions

View File

@@ -89,6 +89,23 @@ jobs:
path: result/* path: result/*
retention-days: 1 retention-days: 1
hpkg:
name: Hpkg
runs-on: nix
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run NixOS test
run: nix build --out-link "result" --print-out-paths --print-build-logs .#checks.x86_64-linux.hpkg
- name: Upload test output
uses: actions/upload-artifact@v3
with:
name: "hpkg-vm-output"
path: result/*
retention-days: 1
check: check:
name: Flake checks name: Flake checks
needs: needs:
@@ -97,6 +114,7 @@ jobs:
- sandbox - sandbox
- sandbox-race - sandbox-race
- sharefs - sharefs
- hpkg
runs-on: nix runs-on: nix
steps: steps:
- name: Checkout - name: Checkout

5
.github/workflows/README vendored Normal file
View File

@@ -0,0 +1,5 @@
DO NOT ADD NEW ACTIONS HERE
This port is solely for releasing to the github mirror and serves no purpose during development.
All development happens at https://git.gensokyo.uk/security/hakurei. If you wish to contribute,
request for an account on git.gensokyo.uk.

46
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
name: Create release
runs-on: ubuntu-latest
permissions:
packages: write
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
uses: nixbuild/nix-quick-install-action@v32
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and cache Nix store
uses: nix-community/cache-nix-action@v6
with:
primary-key: build-${{ runner.os }}-${{ hashFiles('**/*.nix') }}
restore-prefixes-first-match: build-${{ runner.os }}-
gc-max-store-size-linux: 1G
purge: true
purge-prefixes: build-${{ runner.os }}-
purge-created: 60
purge-primary-key: never
- name: Build for release
run: nix build --print-out-paths --print-build-logs .#dist
- name: Release
uses: softprops/action-gh-release@v2
with:
files: |-
result/hakurei-**

48
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Test
on:
- push
jobs:
dist:
name: Create distribution
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Nix
uses: nixbuild/nix-quick-install-action@v32
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and cache Nix store
uses: nix-community/cache-nix-action@v6
with:
primary-key: build-${{ runner.os }}-${{ hashFiles('**/*.nix') }}
restore-prefixes-first-match: build-${{ runner.os }}-
gc-max-store-size-linux: 1G
purge: true
purge-prefixes: build-${{ runner.os }}-
purge-created: 60
purge-primary-key: never
- name: Build for test
id: build-test
run: >-
export HAKUREI_REV="$(git rev-parse --short HEAD)" &&
sed -i.old 's/version = /version = "0.0.0-'$HAKUREI_REV'"; # version = /' package.nix &&
nix build --print-out-paths --print-build-logs .#dist &&
mv package.nix.old package.nix &&
echo "rev=$HAKUREI_REV" >> $GITHUB_OUTPUT
- name: Upload test build
uses: actions/upload-artifact@v4
with:
name: "hakurei-${{ steps.build-test.outputs.rev }}"
path: result/*
retention-days: 1

1
.gitignore vendored
View File

@@ -28,7 +28,6 @@ go.work.sum
# go generate # go generate
/cmd/hakurei/LICENSE /cmd/hakurei/LICENSE
/internal/pkg/testdata/testtool /internal/pkg/testdata/testtool
/internal/rosa/hakurei_current.tar.gz
# release # release
/dist/hakurei-* /dist/hakurei-*

187
README.md
View File

@@ -1,5 +1,5 @@
<p align="center"> <p align="center">
<a href="https://git.gensokyo.uk/rosa/hakurei"> <a href="https://git.gensokyo.uk/security/hakurei">
<picture> <picture>
<img src="https://basement.gensokyo.uk/images/yukari1.png" width="200px" alt="Yukari"> <img src="https://basement.gensokyo.uk/images/yukari1.png" width="200px" alt="Yukari">
</picture> </picture>
@@ -8,58 +8,171 @@
<p align="center"> <p align="center">
<a href="https://pkg.go.dev/hakurei.app"><img src="https://pkg.go.dev/badge/hakurei.app.svg" alt="Go Reference" /></a> <a href="https://pkg.go.dev/hakurei.app"><img src="https://pkg.go.dev/badge/hakurei.app.svg" alt="Go Reference" /></a>
<a href="https://git.gensokyo.uk/rosa/hakurei/actions"><img src="https://git.gensokyo.uk/rosa/hakurei/actions/workflows/test.yml/badge.svg?branch=staging&style=flat-square" alt="Gitea Workflow Status" /></a> <a href="https://git.gensokyo.uk/security/hakurei/actions"><img src="https://git.gensokyo.uk/security/hakurei/actions/workflows/test.yml/badge.svg?branch=staging&style=flat-square" alt="Gitea Workflow Status" /></a>
<br/> <br/>
<a href="https://git.gensokyo.uk/rosa/hakurei/releases"><img src="https://img.shields.io/gitea/v/release/rosa/hakurei?gitea_url=https%3A%2F%2Fgit.gensokyo.uk&color=purple" alt="Release" /></a> <a href="https://git.gensokyo.uk/security/hakurei/releases"><img src="https://img.shields.io/gitea/v/release/security/hakurei?gitea_url=https%3A%2F%2Fgit.gensokyo.uk&color=purple" alt="Release" /></a>
<a href="https://goreportcard.com/report/hakurei.app"><img src="https://goreportcard.com/badge/hakurei.app" alt="Go Report Card" /></a> <a href="https://goreportcard.com/report/hakurei.app"><img src="https://goreportcard.com/badge/hakurei.app" alt="Go Report Card" /></a>
<a href="https://hakurei.app"><img src="https://img.shields.io/website?url=https%3A%2F%2Fhakurei.app" alt="Website" /></a> <a href="https://hakurei.app"><img src="https://img.shields.io/website?url=https%3A%2F%2Fhakurei.app" alt="Website" /></a>
</p> </p>
Hakurei is a tool for running sandboxed desktop applications as dedicated Hakurei is a tool for running sandboxed graphical applications as dedicated subordinate users on the Linux kernel.
subordinate users on the Linux kernel. It implements the application container It implements the application container of [planterette (WIP)](https://git.gensokyo.uk/security/planterette),
of [planterette (WIP)](https://git.gensokyo.uk/rosa/planterette), a a self-contained Android-like package manager with modern security features.
self-contained Android-like package manager with modern security features.
Interaction with hakurei happens entirely through structures described by ## NixOS Module usage
package [hst](https://pkg.go.dev/hakurei.app/hst). No native API is available
due to internal details of uid isolation.
## Notable Packages The NixOS module currently requires home-manager to configure subordinate users. Full module documentation can be found [here](options.md).
Package [container](https://pkg.go.dev/hakurei.app/container) is general purpose To use the module, import it into your configuration with
container tooling. It is used by the hakurei shim process running as the target
subordinate user to set up the application container. It has a single dependency,
[libseccomp](https://github.com/seccomp/libseccomp), to create BPF programs
for the [system call filter](https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html).
Package [internal/pkg](https://pkg.go.dev/hakurei.app/internal/pkg) provides ```nix
infrastructure for hermetic builds. This replaces the legacy nix-based testing {
framework and serves as the build system of Rosa OS, currently developed under inputs = {
package [internal/rosa](https://pkg.go.dev/hakurei.app/internal/rosa). nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
## Dependencies hakurei = {
url = "git+https://git.gensokyo.uk/security/hakurei";
`container` depends on: # Optional but recommended to limit the size of your system closure.
inputs.nixpkgs.follows = "nixpkgs";
};
};
- [libseccomp](https://github.com/seccomp/libseccomp) to generate BPF programs. outputs = { self, nixpkgs, hakurei, ... }:
{
nixosConfigurations.hakurei = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
hakurei.nixosModules.hakurei
];
};
};
}
```
`cmd/hakurei` depends on: This adds the `environment.hakurei` option:
- [acl](https://savannah.nongnu.org/projects/acl/) to export sockets to ```nix
subordinate users. { pkgs, ... }:
- [wayland](https://gitlab.freedesktop.org/wayland/wayland) to set up
[security-context-v1](https://wayland.app/protocols/security-context-v1).
- [xcb](https://xcb.freedesktop.org/) to grant and revoke subordinate users
access to the X server.
`cmd/sharefs` depends on: {
environment.hakurei = {
enable = true;
stateDir = "/var/lib/hakurei";
users = {
alice = 0;
nixos = 10;
};
- [fuse](https://github.com/libfuse/libfuse) to implement the filesystem. commonPaths = [
{
src = "/sdcard";
write = true;
}
];
New dependencies will generally not be added. Patches adding new dependencies extraHomeConfig = {
are very likely to be rejected. home.stateVersion = "23.05";
};
## NixOS Module (deprecated) apps = {
"org.chromium.Chromium" = {
name = "chromium";
identity = 1;
packages = [ pkgs.chromium ];
userns = true;
mapRealUid = true;
dbus = {
system = {
filter = true;
talk = [
"org.bluez"
"org.freedesktop.Avahi"
"org.freedesktop.UPower"
];
};
session =
f:
f {
talk = [
"org.freedesktop.FileManager1"
"org.freedesktop.Notifications"
"org.freedesktop.ScreenSaver"
"org.freedesktop.secrets"
"org.kde.kwalletd5"
"org.kde.kwalletd6"
];
own = [
"org.chromium.Chromium.*"
"org.mpris.MediaPlayer2.org.chromium.Chromium.*"
"org.mpris.MediaPlayer2.chromium.*"
];
call = { };
broadcast = { };
};
};
};
The NixOS module is in maintenance mode and will be removed once planterette is "org.claws_mail.Claws-Mail" = {
feature-complete. Full module documentation can be found [here](options.md). name = "claws-mail";
identity = 2;
packages = [ pkgs.claws-mail ];
gpu = false;
capability.pulse = false;
};
"org.weechat" = {
name = "weechat";
identity = 3;
shareUid = true;
packages = [ pkgs.weechat ];
capability = {
wayland = false;
x11 = false;
dbus = true;
pulse = false;
};
};
"dev.vencord.Vesktop" = {
name = "discord";
identity = 3;
shareUid = true;
packages = [ pkgs.vesktop ];
share = pkgs.vesktop;
command = "vesktop --ozone-platform-hint=wayland";
userns = true;
mapRealUid = true;
capability.x11 = true;
dbus = {
session =
f:
f {
talk = [ "org.kde.StatusNotifierWatcher" ];
own = [ ];
call = { };
broadcast = { };
};
system.filter = true;
};
};
"io.looking-glass" = {
name = "looking-glass-client";
identity = 4;
useCommonPaths = false;
groups = [ "plugdev" ];
extraPaths = [
{
src = "/dev/shm/looking-glass";
write = true;
}
];
extraConfig = {
programs.looking-glass-client.enable = true;
};
};
};
};
}
```

View File

@@ -1,127 +0,0 @@
package main
import (
"log"
"os"
"runtime"
"strings"
. "syscall"
)
func main() {
runtime.LockOSThread()
log.SetFlags(0)
log.SetPrefix("earlyinit: ")
var (
option map[string]string
flags []string
)
if len(os.Args) > 1 {
option = make(map[string]string)
for _, s := range os.Args[1:] {
key, value, ok := strings.Cut(s, "=")
if !ok {
flags = append(flags, s)
continue
}
option[key] = value
}
}
if err := Mount(
"devtmpfs",
"/dev/",
"devtmpfs",
MS_NOSUID|MS_NOEXEC,
"",
); err != nil {
log.Fatalf("cannot mount devtmpfs: %v", err)
}
// The kernel might be unable to set up the console. When that happens,
// printk is called with "Warning: unable to open an initial console."
// and the init runs with no files. The checkfds runtime function
// populates 0-2 by opening /dev/null for them.
//
// This check replaces 1 and 2 with /dev/kmsg to improve the chance
// of output being visible to the user.
if fi, err := os.Stdout.Stat(); err == nil {
if stat, ok := fi.Sys().(*Stat_t); ok {
if stat.Rdev == 0x103 {
var fd int
if fd, err = Open(
"/dev/kmsg",
O_WRONLY|O_CLOEXEC,
0,
); err != nil {
log.Fatalf("cannot open kmsg: %v", err)
}
if err = Dup3(fd, Stdout, 0); err != nil {
log.Fatalf("cannot open stdout: %v", err)
}
if err = Dup3(fd, Stderr, 0); err != nil {
log.Fatalf("cannot open stderr: %v", err)
}
if err = Close(fd); err != nil {
log.Printf("cannot close kmsg: %v", err)
}
}
}
}
// staying in rootfs, these are no longer used
must(os.Remove("/root"))
must(os.Remove("/init"))
must(os.Mkdir("/proc", 0))
mustSyscall("mount proc", Mount(
"proc",
"/proc",
"proc",
MS_NOSUID|MS_NOEXEC|MS_NODEV,
"hidepid=1",
))
must(os.Mkdir("/sys", 0))
mustSyscall("mount sysfs", Mount(
"sysfs",
"/sys",
"sysfs",
0,
"",
))
// after top level has been set up
mustSyscall("remount root", Mount(
"",
"/",
"",
MS_REMOUNT|MS_BIND|
MS_RDONLY|MS_NODEV|MS_NOSUID|MS_NOEXEC,
"",
))
must(os.WriteFile(
"/sys/module/firmware_class/parameters/path",
[]byte("/system/lib/firmware"),
0,
))
}
// mustSyscall calls [log.Fatalln] if err is non-nil.
func mustSyscall(action string, err error) {
if err != nil {
log.Fatalln("cannot "+action+":", err)
}
}
// must calls [log.Fatal] with err if it is non-nil.
func must(err error) {
if err != nil {
log.Fatal(err)
}
}

View File

@@ -13,10 +13,9 @@ import (
"time" "time"
_ "unsafe" // for go:linkname _ "unsafe" // for go:linkname
"hakurei.app/check"
"hakurei.app/command" "hakurei.app/command"
"hakurei.app/ext" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/dbus" "hakurei.app/internal/dbus"
"hakurei.app/internal/env" "hakurei.app/internal/env"
@@ -90,9 +89,6 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
flagHomeDir string flagHomeDir string
flagUserName string flagUserName string
flagSchedPolicy string
flagSchedPriority int
flagPrivateRuntime, flagPrivateTmpdir bool flagPrivateRuntime, flagPrivateTmpdir bool
flagWayland, flagX11, flagDBus, flagPipeWire, flagPulse bool flagWayland, flagX11, flagDBus, flagPipeWire, flagPulse bool
@@ -135,7 +131,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
log.Fatal(optionalErrorUnwrap(err)) log.Fatal(optionalErrorUnwrap(err))
return err return err
} else if progPath, err = check.NewAbs(p); err != nil { } else if progPath, err = check.NewAbs(p); err != nil {
log.Fatal(err) log.Fatal(err.Error())
return err return err
} }
} }
@@ -154,7 +150,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
et |= hst.EPipeWire et |= hst.EPipeWire
} }
config := hst.Config{ config := &hst.Config{
ID: flagID, ID: flagID,
Identity: flagIdentity, Identity: flagIdentity,
Groups: flagGroups, Groups: flagGroups,
@@ -181,13 +177,6 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
}, },
} }
if err := config.SchedPolicy.UnmarshalText(
[]byte(flagSchedPolicy),
); err != nil {
log.Fatal(err)
}
config.SchedPriority = ext.Int(flagSchedPriority)
// bind GPU stuff // bind GPU stuff
if et&(hst.EX11|hst.EWayland) != 0 { if et&(hst.EX11|hst.EWayland) != 0 {
config.Container.Filesystem = append(config.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{ config.Container.Filesystem = append(config.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{
@@ -225,7 +214,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
homeDir = passwd.HomeDir homeDir = passwd.HomeDir
} }
if a, err := check.NewAbs(homeDir); err != nil { if a, err := check.NewAbs(homeDir); err != nil {
log.Fatal(err) log.Fatal(err.Error())
return err return err
} else { } else {
config.Container.Home = a config.Container.Home = a
@@ -245,11 +234,11 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
config.SessionBus = dbus.NewConfig(flagID, true, flagDBusMpris) config.SessionBus = dbus.NewConfig(flagID, true, flagDBusMpris)
} else { } else {
if f, err := os.Open(flagDBusConfigSession); err != nil { if f, err := os.Open(flagDBusConfigSession); err != nil {
log.Fatal(err) log.Fatal(err.Error())
} else { } else {
decodeJSON(log.Fatal, "load session bus proxy config", f, &config.SessionBus) decodeJSON(log.Fatal, "load session bus proxy config", f, &config.SessionBus)
if err = f.Close(); err != nil { if err = f.Close(); err != nil {
log.Fatal(err) log.Fatal(err.Error())
} }
} }
} }
@@ -257,11 +246,11 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
// system bus proxy is optional // system bus proxy is optional
if flagDBusConfigSystem != "nil" { if flagDBusConfigSystem != "nil" {
if f, err := os.Open(flagDBusConfigSystem); err != nil { if f, err := os.Open(flagDBusConfigSystem); err != nil {
log.Fatal(err) log.Fatal(err.Error())
} else { } else {
decodeJSON(log.Fatal, "load system bus proxy config", f, &config.SystemBus) decodeJSON(log.Fatal, "load system bus proxy config", f, &config.SystemBus)
if err = f.Close(); err != nil { if err = f.Close(); err != nil {
log.Fatal(err) log.Fatal(err.Error())
} }
} }
} }
@@ -277,7 +266,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
} }
} }
outcome.Main(ctx, msg, &config, -1) outcome.Main(ctx, msg, config, -1)
panic("unreachable") panic("unreachable")
}). }).
Flag(&flagDBusConfigSession, "dbus-config", command.StringFlag("builtin"), Flag(&flagDBusConfigSession, "dbus-config", command.StringFlag("builtin"),
@@ -298,10 +287,6 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
"Container home directory"). "Container home directory").
Flag(&flagUserName, "u", command.StringFlag("chronos"), Flag(&flagUserName, "u", command.StringFlag("chronos"),
"Passwd user name within sandbox"). "Passwd user name within sandbox").
Flag(&flagSchedPolicy, "policy", command.StringFlag(""),
"Scheduling policy to set for the container").
Flag(&flagSchedPriority, "priority", command.IntFlag(0),
"Scheduling priority to set for the container").
Flag(&flagPrivateRuntime, "private-runtime", command.BoolFlag(false), Flag(&flagPrivateRuntime, "private-runtime", command.BoolFlag(false),
"Do not share XDG_RUNTIME_DIR between containers under the same identity"). "Do not share XDG_RUNTIME_DIR between containers under the same identity").
Flag(&flagPrivateTmpdir, "private-tmpdir", command.BoolFlag(false), Flag(&flagPrivateTmpdir, "private-tmpdir", command.BoolFlag(false),

View File

@@ -36,7 +36,7 @@ Commands:
}, },
{ {
"run", []string{"run", "-h"}, ` "run", []string{"run", "-h"}, `
Usage: hakurei run [-h | --help] [--dbus-config <value>] [--dbus-system <value>] [--mpris] [--dbus-log] [--id <value>] [-a <int>] [-g <value>] [-d <value>] [-u <value>] [--policy <value>] [--priority <int>] [--private-runtime] [--private-tmpdir] [--wayland] [-X] [--dbus] [--pipewire] [--pulse] COMMAND [OPTIONS] Usage: hakurei run [-h | --help] [--dbus-config <value>] [--dbus-system <value>] [--mpris] [--dbus-log] [--id <value>] [-a <int>] [-g <value>] [-d <value>] [-u <value>] [--private-runtime] [--private-tmpdir] [--wayland] [-X] [--dbus] [--pipewire] [--pulse] COMMAND [OPTIONS]
Flags: Flags:
-X Enable direct connection to X11 -X Enable direct connection to X11
@@ -60,10 +60,6 @@ Flags:
Allow owning MPRIS D-Bus path, has no effect if custom config is available Allow owning MPRIS D-Bus path, has no effect if custom config is available
-pipewire -pipewire
Enable connection to PipeWire via SecurityContext Enable connection to PipeWire via SecurityContext
-policy string
Scheduling policy to set for the container
-priority int
Scheduling priority to set for the container
-private-runtime -private-runtime
Do not share XDG_RUNTIME_DIR between containers under the same identity Do not share XDG_RUNTIME_DIR between containers under the same identity
-private-tmpdir -private-tmpdir

View File

@@ -5,7 +5,7 @@ import (
"strings" "strings"
"testing" "testing"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestDecodeJSON(t *testing.T) { func TestDecodeJSON(t *testing.T) {

View File

@@ -13,7 +13,6 @@ import (
"syscall" "syscall"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/ext"
"hakurei.app/message" "hakurei.app/message"
) )
@@ -36,8 +35,8 @@ func main() {
msg := message.New(log.Default()) msg := message.New(log.Default())
early := earlyHardeningErrs{ early := earlyHardeningErrs{
yamaLSM: ext.SetPtracer(0), yamaLSM: container.SetPtracer(0),
dumpable: ext.SetDumpable(ext.SUID_DUMP_DISABLE), dumpable: container.SetDumpable(container.SUID_DUMP_DISABLE),
} }
if os.Geteuid() == 0 { if os.Geteuid() == 0 {

View File

@@ -6,7 +6,7 @@ import (
"testing" "testing"
"time" "time"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/store" "hakurei.app/internal/store"
"hakurei.app/message" "hakurei.app/message"

View File

@@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "time"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/store" "hakurei.app/internal/store"
"hakurei.app/message" "hakurei.app/message"

7
cmd/hpkg/README Normal file
View File

@@ -0,0 +1,7 @@
This program is a proof of concept and is now deprecated. It is only kept
around for API demonstration purposes and to make the most out of the test
suite.
This program is replaced by planterette, which can be found at
https://git.gensokyo.uk/security/planterette. Development effort should be
focused there instead.

173
cmd/hpkg/app.go Normal file
View File

@@ -0,0 +1,173 @@
package main
import (
"encoding/json"
"log"
"os"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
)
type appInfo struct {
Name string `json:"name"`
Version string `json:"version"`
// passed through to [hst.Config]
ID string `json:"id"`
// passed through to [hst.Config]
Identity int `json:"identity"`
// passed through to [hst.Config]
Groups []string `json:"groups,omitempty"`
// passed through to [hst.Config]
Devel bool `json:"devel,omitempty"`
// passed through to [hst.Config]
Userns bool `json:"userns,omitempty"`
// passed through to [hst.Config]
HostNet bool `json:"net,omitempty"`
// passed through to [hst.Config]
HostAbstract bool `json:"abstract,omitempty"`
// passed through to [hst.Config]
Device bool `json:"dev,omitempty"`
// passed through to [hst.Config]
Tty bool `json:"tty,omitempty"`
// passed through to [hst.Config]
MapRealUID bool `json:"map_real_uid,omitempty"`
// passed through to [hst.Config]
DirectWayland bool `json:"direct_wayland,omitempty"`
// passed through to [hst.Config]
SystemBus *hst.BusConfig `json:"system_bus,omitempty"`
// passed through to [hst.Config]
SessionBus *hst.BusConfig `json:"session_bus,omitempty"`
// passed through to [hst.Config]
Enablements *hst.Enablements `json:"enablements,omitempty"`
// passed through to [hst.Config]
Multiarch bool `json:"multiarch,omitempty"`
// passed through to [hst.Config]
Bluetooth bool `json:"bluetooth,omitempty"`
// allow gpu access within sandbox
GPU bool `json:"gpu"`
// store path to nixGL mesa wrappers
Mesa string `json:"mesa,omitempty"`
// store path to nixGL source
NixGL string `json:"nix_gl,omitempty"`
// store path to activate-and-exec script
Launcher *check.Absolute `json:"launcher"`
// store path to /run/current-system
CurrentSystem *check.Absolute `json:"current_system"`
// store path to home-manager activation package
ActivationPackage string `json:"activation_package"`
}
func (app *appInfo) toHst(pathSet *appPathSet, pathname *check.Absolute, argv []string, flagDropShell bool) *hst.Config {
config := &hst.Config{
ID: app.ID,
Enablements: app.Enablements,
SystemBus: app.SystemBus,
SessionBus: app.SessionBus,
DirectWayland: app.DirectWayland,
Identity: app.Identity,
Groups: app.Groups,
Container: &hst.ContainerConfig{
Hostname: formatHostname(app.Name),
Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath.Append("store"), Target: pathNixStore}},
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSBind{Source: pathSet.metaPath, Target: hst.AbsPrivateTmp.Append("app")}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsEtc.Append("resolv.conf"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}},
},
Username: "hakurei",
Shell: pathShell,
Home: pathDataData.Append(app.ID),
Path: pathname,
Args: argv,
},
ExtraPerms: []hst.ExtraPermConfig{
{Path: dataHome, Execute: true},
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
},
}
if app.Devel {
config.Container.Flags |= hst.FDevel
}
if app.Userns {
config.Container.Flags |= hst.FUserns
}
if app.HostNet {
config.Container.Flags |= hst.FHostNet
}
if app.HostAbstract {
config.Container.Flags |= hst.FHostAbstract
}
if app.Device {
config.Container.Flags |= hst.FDevice
}
if app.Tty || flagDropShell {
config.Container.Flags |= hst.FTty
}
if app.MapRealUID {
config.Container.Flags |= hst.FMapRealUID
}
if app.Multiarch {
config.Container.Flags |= hst.FMultiarch
}
config.Container.Flags |= hst.FShareRuntime | hst.FShareTmpdir
return config
}
func loadAppInfo(name string, beforeFail func()) *appInfo {
bundle := new(appInfo)
if f, err := os.Open(name); err != nil {
beforeFail()
log.Fatalf("cannot open bundle: %v", err)
} else if err = json.NewDecoder(f).Decode(&bundle); err != nil {
beforeFail()
log.Fatalf("cannot parse bundle metadata: %v", err)
} else if err = f.Close(); err != nil {
log.Printf("cannot close bundle metadata: %v", err)
// not fatal
}
if bundle.ID == "" {
beforeFail()
log.Fatal("application identifier must not be empty")
}
if bundle.Launcher == nil {
beforeFail()
log.Fatal("launcher must not be empty")
}
if bundle.CurrentSystem == nil {
beforeFail()
log.Fatal("current-system must not be empty")
}
return bundle
}
func formatHostname(name string) string {
if h, err := os.Hostname(); err != nil {
log.Printf("cannot get hostname: %v", err)
return "hakurei-" + name
} else {
return h + "-" + name
}
}

256
cmd/hpkg/build.nix Normal file
View File

@@ -0,0 +1,256 @@
{
nixpkgsFor,
system,
nixpkgs,
home-manager,
}:
{
lib,
stdenv,
closureInfo,
writeScript,
runtimeShell,
writeText,
symlinkJoin,
vmTools,
runCommand,
fetchFromGitHub,
zstd,
nix,
sqlite,
name ? throw "name is required",
version ? throw "version is required",
pname ? "${name}-${version}",
modules ? [ ],
nixosModules ? [ ],
script ? ''
exec "$SHELL" "$@"
'',
id ? name,
identity ? throw "identity is required",
groups ? [ ],
userns ? false,
net ? true,
dev ? false,
no_new_session ? false,
map_real_uid ? false,
direct_wayland ? false,
system_bus ? null,
session_bus ? null,
allow_wayland ? true,
allow_x11 ? false,
allow_dbus ? true,
allow_audio ? true,
gpu ? allow_wayland || allow_x11,
}:
let
inherit (lib) optionals;
homeManagerConfiguration = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgsFor.${system};
modules = modules ++ [
{
home = {
username = "hakurei";
homeDirectory = "/data/data/${id}";
stateVersion = "22.11";
};
}
];
};
launcher = writeScript "hakurei-${pname}" ''
#!${runtimeShell} -el
${script}
'';
extraNixOSConfig =
{ pkgs, ... }:
{
environment = {
etc.nixpkgs.source = nixpkgs.outPath;
systemPackages = [ pkgs.nix ];
};
imports = nixosModules;
};
nixos = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
extraNixOSConfig
{ nix.settings.experimental-features = [ "flakes" ]; }
{ nix.settings.experimental-features = [ "nix-command" ]; }
{ boot.isContainer = true; }
{ system.stateVersion = "22.11"; }
];
};
etc = vmTools.runInLinuxVM (
runCommand "etc" { } ''
mkdir -p /etc
${nixos.config.system.build.etcActivationCommands}
# remove unused files
rm -rf /etc/sudoers
mkdir -p $out
tar -C /etc -cf "$out/etc.tar" .
''
);
extendSessionDefault = id: ext: {
filter = true;
talk = [ "org.freedesktop.Notifications" ] ++ ext.talk;
own =
(optionals (id != null) [
"${id}.*"
"org.mpris.MediaPlayer2.${id}.*"
])
++ ext.own;
inherit (ext) call broadcast;
};
nixGL = fetchFromGitHub {
owner = "nix-community";
repo = "nixGL";
rev = "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a";
hash = "sha256-lnzZQYG0+EXl/6NkGpyIz+FEOc/DSEG57AP1VsdeNrM=";
};
mesaWrappers =
let
isIntelX86Platform = system == "x86_64-linux";
nixGLPackages = import (nixGL + "/default.nix") {
pkgs = nixpkgs.legacyPackages.${system};
enable32bits = isIntelX86Platform;
enableIntelX86Extensions = isIntelX86Platform;
};
in
symlinkJoin {
name = "nixGL-mesa";
paths = with nixGLPackages; [
nixGLIntel
nixVulkanIntel
];
};
info = builtins.toJSON {
inherit
name
version
id
identity
launcher
groups
userns
net
dev
no_new_session
map_real_uid
direct_wayland
system_bus
gpu
;
session_bus =
if session_bus != null then
(session_bus (extendSessionDefault id))
else
(extendSessionDefault id {
talk = [ ];
own = [ ];
call = { };
broadcast = { };
});
enablements = {
wayland = allow_wayland;
x11 = allow_x11;
dbus = allow_dbus;
pipewire = allow_audio;
};
mesa = if gpu then mesaWrappers else null;
nix_gl = if gpu then nixGL else null;
current_system = nixos.config.system.build.toplevel;
activation_package = homeManagerConfiguration.activationPackage;
};
in
stdenv.mkDerivation {
name = "${pname}.pkg";
inherit version;
__structuredAttrs = true;
nativeBuildInputs = [
zstd
nix
sqlite
];
buildCommand = ''
NIX_ROOT="$(mktemp -d)"
export USER="nobody"
# create bootstrap store
bootstrapClosureInfo="${
closureInfo {
rootPaths = [
nix
nixos.config.system.build.toplevel
];
}
}"
echo "copying bootstrap store paths..."
mkdir -p "$NIX_ROOT/nix/store"
xargs -n 1 -a "$bootstrapClosureInfo/store-paths" cp -at "$NIX_ROOT/nix/store/"
NIX_REMOTE="local?root=$NIX_ROOT" nix-store --load-db < "$bootstrapClosureInfo/registration"
NIX_REMOTE="local?root=$NIX_ROOT" nix-store --optimise
sqlite3 "$NIX_ROOT/nix/var/nix/db/db.sqlite" "UPDATE ValidPaths SET registrationTime = ''${SOURCE_DATE_EPOCH}"
chmod -R +r "$NIX_ROOT/nix/var"
# create binary cache
closureInfo="${
closureInfo {
rootPaths = [
homeManagerConfiguration.activationPackage
launcher
]
++ optionals gpu [
mesaWrappers
nixGL
];
}
}"
echo "copying application paths..."
TMP_STORE="$(mktemp -d)"
mkdir -p "$TMP_STORE/nix/store"
xargs -n 1 -a "$closureInfo/store-paths" cp -at "$TMP_STORE/nix/store/"
NIX_REMOTE="local?root=$TMP_STORE" nix-store --load-db < "$closureInfo/registration"
sqlite3 "$TMP_STORE/nix/var/nix/db/db.sqlite" "UPDATE ValidPaths SET registrationTime = ''${SOURCE_DATE_EPOCH}"
NIX_REMOTE="local?root=$TMP_STORE" nix --offline --extra-experimental-features nix-command \
--verbose --log-format raw-with-logs \
copy --all --no-check-sigs --to \
"file://$NIX_ROOT/res?compression=zstd&compression-level=19&parallel-compression=true"
# package /etc
mkdir -p "$NIX_ROOT/etc"
tar -C "$NIX_ROOT/etc" -xf "${etc}/etc.tar"
# write metadata
cp "${writeText "bundle.json" info}" "$NIX_ROOT/bundle.json"
# create an intermediate file to improve zstd performance
INTER="$(mktemp)"
tar -C "$NIX_ROOT" -cf "$INTER" .
zstd -T0 -19 -fo "$out" "$INTER"
'';
}

335
cmd/hpkg/main.go Normal file
View File

@@ -0,0 +1,335 @@
package main
import (
"context"
"encoding/json"
"errors"
"log"
"os"
"os/signal"
"path"
"syscall"
"hakurei.app/command"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
var (
errSuccess = errors.New("success")
)
func main() {
log.SetPrefix("hpkg: ")
log.SetFlags(0)
msg := message.New(log.Default())
if err := os.Setenv("SHELL", pathShell.String()); err != nil {
log.Fatalf("cannot set $SHELL: %v", err)
}
if os.Geteuid() == 0 {
log.Fatal("this program must not run as root")
}
ctx, stop := signal.NotifyContext(context.Background(),
syscall.SIGINT, syscall.SIGTERM)
defer stop() // unreachable
var (
flagVerbose bool
flagDropShell bool
)
c := command.New(os.Stderr, log.Printf, "hpkg", func([]string) error { msg.SwapVerbose(flagVerbose); return nil }).
Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console").
Flag(&flagDropShell, "s", command.BoolFlag(false), "Drop to a shell in place of next hakurei action")
{
var (
flagDropShellActivate bool
)
c.NewCommand("install", "Install an application from its package", func(args []string) error {
if len(args) != 1 {
log.Println("invalid argument")
return syscall.EINVAL
}
pkgPath := args[0]
if !path.IsAbs(pkgPath) {
if dir, err := os.Getwd(); err != nil {
log.Printf("cannot get current directory: %v", err)
return err
} else {
pkgPath = path.Join(dir, pkgPath)
}
}
/*
Look up paths to programs started by hpkg.
This is done here to ease error handling as cleanup is not yet required.
*/
var (
_ = lookPath("zstd")
tar = lookPath("tar")
chmod = lookPath("chmod")
rm = lookPath("rm")
)
/*
Extract package and set up for cleanup.
*/
var workDir *check.Absolute
if p, err := os.MkdirTemp("", "hpkg.*"); err != nil {
log.Printf("cannot create temporary directory: %v", err)
return err
} else if workDir, err = check.NewAbs(p); err != nil {
log.Printf("invalid temporary directory: %v", err)
return err
}
cleanup := func() {
// should be faster than a native implementation
mustRun(msg, chmod, "-R", "+w", workDir.String())
mustRun(msg, rm, "-rf", workDir.String())
}
beforeRunFail.Store(&cleanup)
mustRun(msg, tar, "-C", workDir.String(), "-xf", pkgPath)
/*
Parse bundle and app metadata, do pre-install checks.
*/
bundle := loadAppInfo(path.Join(workDir.String(), "bundle.json"), cleanup)
pathSet := pathSetByApp(bundle.ID)
a := bundle
if s, err := os.Stat(pathSet.metaPath.String()); err != nil {
if !os.IsNotExist(err) {
cleanup()
log.Printf("cannot access %q: %v", pathSet.metaPath, err)
return err
}
// did not modify app, clean installation condition met later
} else if s.IsDir() {
cleanup()
log.Printf("metadata path %q is not a file", pathSet.metaPath)
return syscall.EBADMSG
} else {
a = loadAppInfo(pathSet.metaPath.String(), cleanup)
if a.ID != bundle.ID {
cleanup()
log.Printf("app %q claims to have identifier %q",
bundle.ID, a.ID)
return syscall.EBADE
}
// sec: should verify credentials
}
if a != bundle {
// do not try to re-install
if a.NixGL == bundle.NixGL &&
a.CurrentSystem == bundle.CurrentSystem &&
a.Launcher == bundle.Launcher &&
a.ActivationPackage == bundle.ActivationPackage {
cleanup()
log.Printf("package %q is identical to local application %q",
pkgPath, a.ID)
return errSuccess
}
// identity determines uid
if a.Identity != bundle.Identity {
cleanup()
log.Printf("package %q identity %d differs from installed %d",
pkgPath, bundle.Identity, a.Identity)
return syscall.EBADE
}
// sec: should compare version string
msg.Verbosef("installing application %q version %q over local %q",
bundle.ID, bundle.Version, a.Version)
} else {
msg.Verbosef("application %q clean installation", bundle.ID)
// sec: should install credentials
}
/*
Setup steps for files owned by the target user.
*/
withCacheDir(ctx, msg, "install", []string{
// export inner bundle path in the environment
"export BUNDLE=" + hst.PrivateTmp + "/bundle",
// replace inner /etc
"mkdir -p etc",
"chmod -R +w etc",
"rm -rf etc",
"cp -dRf $BUNDLE/etc etc",
// replace inner /nix
"mkdir -p nix",
"chmod -R +w nix",
"rm -rf nix",
"cp -dRf /nix nix",
// copy from binary cache
"nix copy --offline --no-check-sigs --all --from file://$BUNDLE/res --to $PWD",
// deduplicate nix store
"nix store --offline --store $PWD optimise",
// make cache directory world-readable for autoetc
"chmod 0755 .",
}, workDir, bundle, pathSet, flagDropShell, cleanup)
if bundle.GPU {
withCacheDir(ctx, msg, "mesa-wrappers", []string{
// link nixGL mesa wrappers
"mkdir -p nix/.nixGL",
"ln -s " + bundle.Mesa + "/bin/nixGLIntel nix/.nixGL/nixGL",
"ln -s " + bundle.Mesa + "/bin/nixVulkanIntel nix/.nixGL/nixVulkan",
}, workDir, bundle, pathSet, false, cleanup)
}
/*
Activate home-manager generation.
*/
withNixDaemon(ctx, msg, "activate", []string{
// clean up broken links
"mkdir -p .local/state/{nix,home-manager}",
"chmod -R +w .local/state/{nix,home-manager}",
"rm -rf .local/state/{nix,home-manager}",
// run activation script
bundle.ActivationPackage + "/activate",
}, false, func(config *hst.Config) *hst.Config { return config },
bundle, pathSet, flagDropShellActivate, cleanup)
/*
Installation complete. Write metadata to block re-installs or downgrades.
*/
// serialise metadata to ensure consistency
if f, err := os.OpenFile(pathSet.metaPath.String()+"~", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err != nil {
cleanup()
log.Printf("cannot create metadata file: %v", err)
return err
} else if err = json.NewEncoder(f).Encode(bundle); err != nil {
cleanup()
log.Printf("cannot write metadata: %v", err)
return err
} else if err = f.Close(); err != nil {
log.Printf("cannot close metadata file: %v", err)
// not fatal
}
if err := os.Rename(pathSet.metaPath.String()+"~", pathSet.metaPath.String()); err != nil {
cleanup()
log.Printf("cannot rename metadata file: %v", err)
return err
}
cleanup()
return errSuccess
}).
Flag(&flagDropShellActivate, "s", command.BoolFlag(false), "Drop to a shell on activation")
}
{
var (
flagDropShellNixGL bool
flagAutoDrivers bool
)
c.NewCommand("start", "Start an application", func(args []string) error {
if len(args) < 1 {
log.Println("invalid argument")
return syscall.EINVAL
}
/*
Parse app metadata.
*/
id := args[0]
pathSet := pathSetByApp(id)
a := loadAppInfo(pathSet.metaPath.String(), func() {})
if a.ID != id {
log.Printf("app %q claims to have identifier %q", id, a.ID)
return syscall.EBADE
}
/*
Prepare nixGL.
*/
if a.GPU && flagAutoDrivers {
withNixDaemon(ctx, msg, "nix-gl", []string{
"mkdir -p /nix/.nixGL/auto",
"rm -rf /nix/.nixGL/auto",
"export NIXPKGS_ALLOW_UNFREE=1",
"nix build --impure " +
"--out-link /nix/.nixGL/auto/opengl " +
"--override-input nixpkgs path:/etc/nixpkgs " +
"path:" + a.NixGL,
"nix build --impure " +
"--out-link /nix/.nixGL/auto/vulkan " +
"--override-input nixpkgs path:/etc/nixpkgs " +
"path:" + a.NixGL + "#nixVulkanNvidia",
}, true, func(config *hst.Config) *hst.Config {
config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsEtc.Append("resolv.conf"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices"), Optional: true}},
}...)
appendGPUFilesystem(config)
return config
}, a, pathSet, flagDropShellNixGL, func() {})
}
/*
Create app configuration.
*/
pathname := a.Launcher
argv := make([]string, 1, len(args))
if flagDropShell {
pathname = pathShell
argv[0] = bash
} else {
argv[0] = a.Launcher.String()
}
argv = append(argv, args[1:]...)
config := a.toHst(pathSet, pathname, argv, flagDropShell)
/*
Expose GPU devices.
*/
if a.GPU {
config.Container.Filesystem = append(config.Container.Filesystem,
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath.Append(".nixGL"), Target: hst.AbsPrivateTmp.Append("nixGL")}})
appendGPUFilesystem(config)
}
/*
Spawn app.
*/
mustRunApp(ctx, msg, config, func() {})
return errSuccess
}).
Flag(&flagDropShellNixGL, "s", command.BoolFlag(false), "Drop to a shell on nixGL build").
Flag(&flagAutoDrivers, "auto-drivers", command.BoolFlag(false), "Attempt automatic opengl driver detection")
}
c.MustParse(os.Args[1:], func(err error) {
msg.Verbosef("command returned %v", err)
if errors.Is(err, errSuccess) {
msg.BeforeExit()
os.Exit(0)
}
})
log.Fatal("unreachable")
}

117
cmd/hpkg/paths.go Normal file
View File

@@ -0,0 +1,117 @@
package main
import (
"log"
"os"
"os/exec"
"strconv"
"sync/atomic"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
const bash = "bash"
var (
dataHome *check.Absolute
)
func init() {
// dataHome
if a, err := check.NewAbs(os.Getenv("HAKUREI_DATA_HOME")); err == nil {
dataHome = a
} else {
dataHome = fhs.AbsVarLib.Append("hakurei/" + strconv.Itoa(os.Getuid()))
}
}
var (
pathBin = fhs.AbsRoot.Append("bin")
pathNix = check.MustAbs("/nix/")
pathNixStore = pathNix.Append("store/")
pathCurrentSystem = fhs.AbsRun.Append("current-system")
pathSwBin = pathCurrentSystem.Append("sw/bin/")
pathShell = pathSwBin.Append(bash)
pathData = check.MustAbs("/data")
pathDataData = pathData.Append("data")
)
func lookPath(file string) string {
if p, err := exec.LookPath(file); err != nil {
log.Fatalf("%s: command not found", file)
return ""
} else {
return p
}
}
var beforeRunFail = new(atomic.Pointer[func()])
func mustRun(msg message.Msg, name string, arg ...string) {
msg.Verbosef("spawning process: %q %q", name, arg)
cmd := exec.Command(name, arg...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
if f := beforeRunFail.Swap(nil); f != nil {
(*f)()
}
log.Fatalf("%s: %v", name, err)
}
}
type appPathSet struct {
// ${dataHome}/${id}
baseDir *check.Absolute
// ${baseDir}/app
metaPath *check.Absolute
// ${baseDir}/files
homeDir *check.Absolute
// ${baseDir}/cache
cacheDir *check.Absolute
// ${baseDir}/cache/nix
nixPath *check.Absolute
}
func pathSetByApp(id string) *appPathSet {
pathSet := new(appPathSet)
pathSet.baseDir = dataHome.Append(id)
pathSet.metaPath = pathSet.baseDir.Append("app")
pathSet.homeDir = pathSet.baseDir.Append("files")
pathSet.cacheDir = pathSet.baseDir.Append("cache")
pathSet.nixPath = pathSet.cacheDir.Append("nix")
return pathSet
}
func appendGPUFilesystem(config *hst.Config) {
config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{
// flatpak commit 763a686d874dd668f0236f911de00b80766ffe79
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("dri"), Device: true, Optional: true}},
// mali
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("mali"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("mali0"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("umplock"), Device: true, Optional: true}},
// nvidia
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidiactl"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-modeset"), Device: true, Optional: true}},
// nvidia OpenCL/CUDA
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-uvm"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-uvm-tools"), Device: true, Optional: true}},
// flatpak commit d2dff2875bb3b7e2cd92d8204088d743fd07f3ff
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia0"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia1"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia2"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia3"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia4"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia5"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia6"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia7"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia8"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia9"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia10"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia11"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia12"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia13"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia14"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia15"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia16"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia17"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia18"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia19"), Device: true, Optional: true}},
}...)
}

61
cmd/hpkg/proc.go Normal file
View File

@@ -0,0 +1,61 @@
package main
import (
"context"
"encoding/json"
"errors"
"io"
"log"
"os"
"os/exec"
"hakurei.app/hst"
"hakurei.app/internal/info"
"hakurei.app/message"
)
var hakureiPathVal = info.MustHakureiPath().String()
func mustRunApp(ctx context.Context, msg message.Msg, config *hst.Config, beforeFail func()) {
var (
cmd *exec.Cmd
st io.WriteCloser
)
if r, w, err := os.Pipe(); err != nil {
beforeFail()
log.Fatalf("cannot pipe: %v", err)
} else {
if msg.IsVerbose() {
cmd = exec.CommandContext(ctx, hakureiPathVal, "-v", "app", "3")
} else {
cmd = exec.CommandContext(ctx, hakureiPathVal, "app", "3")
}
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
cmd.ExtraFiles = []*os.File{r}
st = w
}
go func() {
if err := json.NewEncoder(st).Encode(config); err != nil {
beforeFail()
log.Fatalf("cannot send configuration: %v", err)
}
}()
if err := cmd.Start(); err != nil {
beforeFail()
log.Fatalf("cannot start hakurei: %v", err)
}
if err := cmd.Wait(); err != nil {
var exitError *exec.ExitError
if errors.As(err, &exitError) {
beforeFail()
msg.BeforeExit()
os.Exit(exitError.ExitCode())
} else {
beforeFail()
log.Fatalf("cannot wait: %v", err)
}
}
}

View File

@@ -0,0 +1,62 @@
{ pkgs, ... }:
{
users.users = {
alice = {
isNormalUser = true;
description = "Alice Foobar";
password = "foobar";
uid = 1000;
};
};
home-manager.users.alice.home.stateVersion = "24.11";
# Automatically login on tty1 as a normal user:
services.getty.autologinUser = "alice";
environment = {
variables = {
SWAYSOCK = "/tmp/sway-ipc.sock";
WLR_RENDERER = "pixman";
};
};
# Automatically configure and start Sway when logging in on tty1:
programs.bash.loginShellInit = ''
if [ "$(tty)" = "/dev/tty1" ]; then
set -e
mkdir -p ~/.config/sway
(sed s/Mod4/Mod1/ /etc/sway/config &&
echo 'output * bg ${pkgs.nixos-artwork.wallpapers.simple-light-gray.gnomeFilePath} fill' &&
echo 'output Virtual-1 res 1680x1050') > ~/.config/sway/config
sway --validate
systemd-cat --identifier=session sway && touch /tmp/sway-exit-ok
fi
'';
programs.sway.enable = true;
virtualisation = {
diskSize = 6 * 1024;
qemu.options = [
# Need to switch to a different GPU driver than the default one (-vga std) so that Sway can launch:
"-vga none -device virtio-gpu-pci"
# Increase zstd performance:
"-smp 8"
];
};
environment.hakurei = {
enable = true;
stateDir = "/var/lib/hakurei";
users.alice = 0;
extraHomeConfig = {
home.stateVersion = "23.05";
};
};
}

34
cmd/hpkg/test/default.nix Normal file
View File

@@ -0,0 +1,34 @@
{
testers,
callPackage,
system,
self,
}:
let
buildPackage = self.buildPackage.${system};
in
testers.nixosTest {
name = "hpkg";
nodes.machine = {
environment.etc = {
"foot.pkg".source = callPackage ./foot.nix { inherit buildPackage; };
};
imports = [
./configuration.nix
self.nixosModules.hakurei
self.inputs.home-manager.nixosModules.home-manager
];
};
# adapted from nixos sway integration tests
# testScriptWithTypes:49: error: Cannot call function of unknown type
# (machine.succeed if succeed else machine.execute)(
# ^
# Found 1 error in 1 file (checked 1 source file)
skipTypeCheck = true;
testScript = builtins.readFile ./test.py;
}

48
cmd/hpkg/test/foot.nix Normal file
View File

@@ -0,0 +1,48 @@
{
lib,
buildPackage,
foot,
wayland-utils,
inconsolata,
}:
buildPackage {
name = "foot";
inherit (foot) version;
identity = 2;
id = "org.codeberg.dnkl.foot";
modules = [
{
home.packages = [
foot
# For wayland-info:
wayland-utils
];
}
];
nixosModules = [
{
# To help with OCR:
environment.etc."xdg/foot/foot.ini".text = lib.generators.toINI { } {
main = {
font = "inconsolata:size=14";
};
colors = rec {
foreground = "000000";
background = "ffffff";
regular2 = foreground;
};
};
fonts.packages = [ inconsolata ];
}
];
script = ''
exec foot "$@"
'';
}

110
cmd/hpkg/test/test.py Normal file
View File

@@ -0,0 +1,110 @@
import json
import shlex
q = shlex.quote
NODE_GROUPS = ["nodes", "floating_nodes"]
def swaymsg(command: str = "", succeed=True, type="command"):
assert command != "" or type != "command", "Must specify command or type"
shell = q(f"swaymsg -t {q(type)} -- {q(command)}")
with machine.nested(
f"sending swaymsg {shell!r}" + " (allowed to fail)" * (not succeed)
):
ret = (machine.succeed if succeed else machine.execute)(
f"su - alice -c {shell}"
)
# execute also returns a status code, but disregard.
if not succeed:
_, ret = ret
if not succeed and not ret:
return None
parsed = json.loads(ret)
return parsed
def walk(tree):
yield tree
for group in NODE_GROUPS:
for node in tree.get(group, []):
yield from walk(node)
def wait_for_window(pattern):
def func(last_chance):
nodes = (node["name"] for node in walk(swaymsg(type="get_tree")))
if last_chance:
nodes = list(nodes)
machine.log(f"Last call! Current list of windows: {nodes}")
return any(pattern in name for name in nodes)
retry(func)
def collect_state_ui(name):
swaymsg(f"exec hakurei ps > '/tmp/{name}.ps'")
machine.copy_from_vm(f"/tmp/{name}.ps", "")
swaymsg(f"exec hakurei --json ps > '/tmp/{name}.json'")
machine.copy_from_vm(f"/tmp/{name}.json", "")
machine.screenshot(name)
def check_state(name, enablements):
instances = json.loads(machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei --json ps"))
if len(instances) != 1:
raise Exception(f"unexpected state length {len(instances)}")
instance = instances[0]
if len(instance['container']['args']) != 1 or not (instance['container']['args'][0].startswith("/nix/store/")) or f"hakurei-{name}-" not in (instance['container']['args'][0]):
raise Exception(f"unexpected args {instance['container']['args']}")
if instance['enablements'] != enablements:
raise Exception(f"unexpected enablements {instance['enablements']}")
start_all()
machine.wait_for_unit("multi-user.target")
# To check hakurei's version:
print(machine.succeed("sudo -u alice -i hakurei version"))
# Wait for Sway to complete startup:
machine.wait_for_file("/run/user/1000/wayland-1")
machine.wait_for_file("/tmp/sway-ipc.sock")
# Prepare hpkg directory:
machine.succeed("install -dm 0700 -o alice -g users /var/lib/hakurei/1000")
# Install hpkg app:
swaymsg("exec hpkg -v install /etc/foot.pkg && touch /tmp/hpkg-install-ok")
machine.wait_for_file("/tmp/hpkg-install-ok")
# Start app (foot) with Wayland enablement:
swaymsg("exec hpkg -v start org.codeberg.dnkl.foot")
wait_for_window("hakurei@machine-foot")
machine.send_chars("clear; wayland-info && touch /tmp/success-client\n")
machine.wait_for_file("/tmp/hakurei.0/tmpdir/2/success-client")
collect_state_ui("app_wayland")
check_state("foot", {"wayland": True, "dbus": True, "pipewire": True})
# Verify acl on XDG_RUNTIME_DIR:
print(machine.succeed("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10002"))
machine.send_chars("exit\n")
machine.wait_until_fails("pgrep foot")
# Verify acl cleanup on XDG_RUNTIME_DIR:
machine.wait_until_fails("getfacl --absolute-names --omit-header --numeric /tmp/hakurei.0/runtime | grep 10002")
# Exit Sway and verify process exit status 0:
swaymsg("exit", succeed=False)
machine.wait_for_file("/tmp/sway-exit-ok")
# Print hakurei share and rundir contents:
print(machine.succeed("find /tmp/hakurei.0 "
+ "-path '/tmp/hakurei.0/runtime/*/*' -prune -o "
+ "-path '/tmp/hakurei.0/tmpdir/*/*' -prune -o "
+ "-print"))
print(machine.fail("ls /run/user/1000/hakurei"))

130
cmd/hpkg/with.go Normal file
View File

@@ -0,0 +1,130 @@
package main
import (
"context"
"os"
"strings"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst"
"hakurei.app/message"
)
func withNixDaemon(
ctx context.Context,
msg message.Msg,
action string, command []string, net bool, updateConfig func(config *hst.Config) *hst.Config,
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
) {
flags := hst.FMultiarch | hst.FUserns // nix sandbox requires userns
if net {
flags |= hst.FHostNet
}
if dropShell {
flags |= hst.FTty
}
mustRunAppDropShell(ctx, msg, updateConfig(&hst.Config{
ID: app.ID,
ExtraPerms: []hst.ExtraPermConfig{
{Path: dataHome, Execute: true},
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
},
Identity: app.Identity,
Container: &hst.ContainerConfig{
Hostname: formatHostname(app.Name) + "-" + action,
Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath, Target: pathNix, Write: true}},
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}},
},
Username: "hakurei",
Shell: pathShell,
Home: pathDataData.Append(app.ID),
Path: pathShell,
Args: []string{bash, "-lc", "rm -f /nix/var/nix/daemon-socket/socket && " +
// start nix-daemon
"nix-daemon --store / & " +
// wait for socket to appear
"(while [ ! -S /nix/var/nix/daemon-socket/socket ]; do sleep 0.01; done) && " +
// create directory so nix stops complaining
"mkdir -p /nix/var/nix/profiles/per-user/root/channels && " +
strings.Join(command, " && ") +
// terminate nix-daemon
" && pkill nix-daemon",
},
Flags: flags,
},
}), dropShell, beforeFail)
}
func withCacheDir(
ctx context.Context,
msg message.Msg,
action string, command []string, workDir *check.Absolute,
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func(),
) {
flags := hst.FMultiarch
if dropShell {
flags |= hst.FTty
}
mustRunAppDropShell(ctx, msg, &hst.Config{
ID: app.ID,
ExtraPerms: []hst.ExtraPermConfig{
{Path: dataHome, Execute: true},
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
{Path: workDir, Execute: true},
},
Identity: app.Identity,
Container: &hst.ContainerConfig{
Hostname: formatHostname(app.Name) + "-" + action,
Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: workDir.Append(fhs.Etc), Special: true}},
{FilesystemConfig: &hst.FSBind{Source: workDir.Append("nix"), Target: pathNix}},
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSBind{Source: workDir, Target: hst.AbsPrivateTmp.Append("bundle")}},
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID, "cache"), Source: pathSet.cacheDir, Write: true, Ensure: true}},
},
Username: "nixos",
Shell: pathShell,
Home: pathDataData.Append(app.ID, "cache"),
Path: pathShell,
Args: []string{bash, "-lc", strings.Join(command, " && ")},
Flags: flags,
},
}, dropShell, beforeFail)
}
func mustRunAppDropShell(ctx context.Context, msg message.Msg, config *hst.Config, dropShell bool, beforeFail func()) {
if dropShell {
if config.Container != nil {
config.Container.Args = []string{bash, "-l"}
}
mustRunApp(ctx, msg, config, beforeFail)
beforeFail()
msg.BeforeExit()
os.Exit(0)
}
mustRunApp(ctx, msg, config, beforeFail)
}

76
cmd/irdump/main.go Normal file
View File

@@ -0,0 +1,76 @@
package main
import (
"errors"
"log"
"os"
"hakurei.app/command"
"hakurei.app/internal/pkg"
)
func main() {
log.SetFlags(0)
log.SetPrefix("irdump: ")
var (
flagOutput string
flagReal bool
flagHeader bool
flagForce bool
flagRaw bool
)
c := command.New(os.Stderr, log.Printf, "irdump", func(args []string) (err error) {
var input *os.File
if len(args) != 1 {
return errors.New("irdump requires 1 argument")
}
if input, err = os.Open(args[0]); err != nil {
return
}
defer input.Close()
var output *os.File
if flagOutput == "" {
output = os.Stdout
} else {
defer output.Close()
if output, err = os.Create(flagOutput); err != nil {
return
}
}
var out string
if out, err = pkg.Disassemble(input, flagReal, flagHeader, flagForce, flagRaw); err != nil {
return
}
if _, err = output.WriteString(out); err != nil {
return
}
return
}).Flag(
&flagOutput,
"o", command.StringFlag(""),
"Output file for asm (leave empty for stdout)",
).Flag(
&flagReal,
"r", command.BoolFlag(false),
"skip label generation; idents print real value",
).Flag(
&flagHeader,
"H", command.BoolFlag(false),
"display artifact headers",
).Flag(
&flagForce,
"f", command.BoolFlag(false),
"force display (skip validations)",
).Flag(
&flagRaw,
"R", command.BoolFlag(false),
"don't format output",
)
c.MustParse(os.Args[1:], func(err error) {
log.Fatal(err)
})
}

View File

@@ -4,27 +4,17 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall" "syscall"
"time"
"unique" "unique"
"hakurei.app/check"
"hakurei.app/command" "hakurei.app/command"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/seccomp" "hakurei.app/container/check"
"hakurei.app/container/std"
"hakurei.app/ext"
"hakurei.app/fhs"
"hakurei.app/internal/pkg" "hakurei.app/internal/pkg"
"hakurei.app/internal/rosa" "hakurei.app/internal/rosa"
"hakurei.app/message" "hakurei.app/message"
@@ -61,16 +51,10 @@ func main() {
flagCures int flagCures int
flagBase string flagBase string
flagTShift int flagTShift int
flagIdle bool
) )
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) (err error) { c := command.New(os.Stderr, log.Printf, "mbf", func([]string) (err error) {
msg.SwapVerbose(!flagQuiet) msg.SwapVerbose(!flagQuiet)
flagBase = os.ExpandEnv(flagBase)
if flagBase == "" {
flagBase = "cache"
}
var base *check.Absolute var base *check.Absolute
if flagBase, err = filepath.Abs(flagBase); err != nil { if flagBase, err = filepath.Abs(flagBase); err != nil {
return return
@@ -86,11 +70,6 @@ func main() {
cache.SetThreshold(1 << flagTShift) cache.SetThreshold(1 << flagTShift)
} }
} }
if flagIdle {
pkg.SetSchedIdle = true
}
return return
}).Flag( }).Flag(
&flagQuiet, &flagQuiet,
@@ -102,16 +81,12 @@ func main() {
"Maximum number of dependencies to cure at any given time", "Maximum number of dependencies to cure at any given time",
).Flag( ).Flag(
&flagBase, &flagBase,
"d", command.StringFlag("$MBF_CACHE_DIR"), "d", command.StringFlag("cache"),
"Directory to store cured artifacts", "Directory to store cured artifacts",
).Flag( ).Flag(
&flagTShift, &flagTShift,
"tshift", command.IntFlag(-1), "tshift", command.IntFlag(-1),
"Dependency graph size exponent, to the power of 2", "Dependency graph size exponent, to the power of 2",
).Flag(
&flagIdle,
"sched-idle", command.BoolFlag(false),
"Set SCHED_IDLE scheduling policy",
) )
{ {
@@ -134,309 +109,50 @@ func main() {
) )
} }
{
var (
flagStatus bool
flagReport string
)
c.NewCommand(
"info",
"Display out-of-band metadata of an artifact",
func(args []string) (err error) {
if len(args) == 0 {
return errors.New("info requires at least 1 argument")
}
var r *rosa.Report
if flagReport != "" {
if r, err = rosa.OpenReport(flagReport); err != nil {
return err
}
defer func() {
if closeErr := r.Close(); err == nil {
err = closeErr
}
}()
defer r.HandleAccess(&err)()
}
for i, name := range args {
if p, ok := rosa.ResolveName(name); !ok {
return fmt.Errorf("unknown artifact %q", name)
} else {
var suffix string
if version := rosa.Std.Version(p); version != rosa.Unversioned {
suffix += "-" + version
}
fmt.Println("name : " + name + suffix)
meta := rosa.GetMetadata(p)
fmt.Println("description : " + meta.Description)
if meta.Website != "" {
fmt.Println("website : " +
strings.TrimSuffix(meta.Website, "/"))
}
if len(meta.Dependencies) > 0 {
fmt.Print("depends on :")
for _, d := range meta.Dependencies {
s := rosa.GetMetadata(d).Name
if version := rosa.Std.Version(d); version != rosa.Unversioned {
s += "-" + version
}
fmt.Print(" " + s)
}
fmt.Println()
}
const statusPrefix = "status : "
if flagStatus {
if r == nil {
var f io.ReadSeekCloser
f, err = cache.OpenStatus(rosa.Std.Load(p))
if err != nil {
if errors.Is(err, os.ErrNotExist) {
fmt.Println(
statusPrefix + "not yet cured",
)
} else {
return
}
} else {
fmt.Print(statusPrefix)
_, err = io.Copy(os.Stdout, f)
if err = errors.Join(err, f.Close()); err != nil {
return
}
}
} else {
status, n := r.ArtifactOf(cache.Ident(rosa.Std.Load(p)))
if status == nil {
fmt.Println(
statusPrefix + "not in report",
)
} else {
fmt.Println("size :", n)
fmt.Print(statusPrefix)
if _, err = os.Stdout.Write(status); err != nil {
return
}
}
}
}
if i != len(args)-1 {
fmt.Println()
}
}
}
return nil
},
).
Flag(
&flagStatus,
"status", command.BoolFlag(false),
"Display cure status if available",
).
Flag(
&flagReport,
"report", command.StringFlag(""),
"Load cure status from this report file instead of cache",
)
}
c.NewCommand( c.NewCommand(
"report", "stage3",
"Generate an artifact cure report for the current cache", "Check for toolchain 3-stage non-determinism",
func(args []string) (err error) { func(args []string) (err error) {
var w *os.File _, _, _, stage1 := (rosa.Std - 2).NewLLVM()
switch len(args) { _, _, _, stage2 := (rosa.Std - 1).NewLLVM()
case 0: _, _, _, stage3 := rosa.Std.NewLLVM()
w = os.Stdout var (
pathname *check.Absolute
checksum [2]unique.Handle[pkg.Checksum]
)
case 1: if pathname, _, err = cache.Cure(stage1); err != nil {
if w, err = os.OpenFile( return err
args[0], }
os.O_CREATE|os.O_EXCL|syscall.O_WRONLY, log.Println("stage1:", pathname)
0400,
); err != nil { if pathname, checksum[0], err = cache.Cure(stage2); err != nil {
return return err
}
log.Println("stage2:", pathname)
if pathname, checksum[1], err = cache.Cure(stage3); err != nil {
return err
}
log.Println("stage3:", pathname)
if checksum[0] != checksum[1] {
err = &pkg.ChecksumMismatchError{
Got: checksum[0].Value(),
Want: checksum[1].Value(),
} }
defer func() { } else {
closeErr := w.Close() log.Println(
if err == nil { "stage2 is identical to stage3",
err = closeErr "("+pkg.Encode(checksum[0].Value())+")",
} )
}()
default:
return errors.New("report requires 1 argument")
} }
return
if ext.Isatty(int(w.Fd())) {
return errors.New("output appears to be a terminal")
}
return rosa.WriteReport(msg, w, cache)
}, },
) )
{
var flagJobs int
c.NewCommand("updates", command.UsageInternal, func([]string) error {
var (
errsMu sync.Mutex
errs []error
n atomic.Uint64
)
w := make(chan rosa.PArtifact)
var wg sync.WaitGroup
for range max(flagJobs, 1) {
wg.Go(func() {
for p := range w {
meta := rosa.GetMetadata(p)
if meta.ID == 0 {
continue
}
v, err := meta.GetVersions(ctx)
if err != nil {
errsMu.Lock()
errs = append(errs, err)
errsMu.Unlock()
continue
}
if current, latest :=
rosa.Std.Version(p),
meta.GetLatest(v); current != latest {
n.Add(1)
log.Printf("%s %s < %s", meta.Name, current, latest)
continue
}
msg.Verbosef("%s is up to date", meta.Name)
}
})
}
done:
for i := range rosa.PresetEnd {
select {
case w <- rosa.PArtifact(i):
break
case <-ctx.Done():
break done
}
}
close(w)
wg.Wait()
if v := n.Load(); v > 0 {
errs = append(errs, errors.New(strconv.Itoa(int(v))+
" package(s) are out of date"))
}
return errors.Join(errs...)
}).
Flag(
&flagJobs,
"j", command.IntFlag(32),
"Maximum number of simultaneous connections",
)
}
{ {
var ( var (
flagGentoo string flagDump string
flagChecksum string
flagStage0 bool
)
c.NewCommand(
"stage3",
"Check for toolchain 3-stage non-determinism",
func(args []string) (err error) {
t := rosa.Std
if flagGentoo != "" {
t -= 3 // magic number to discourage misuse
var checksum pkg.Checksum
if len(flagChecksum) != 0 {
if err = pkg.Decode(&checksum, flagChecksum); err != nil {
return
}
}
rosa.SetGentooStage3(flagGentoo, checksum)
}
_, _, _, stage1 := (t - 2).NewLLVM()
_, _, _, stage2 := (t - 1).NewLLVM()
_, _, _, stage3 := t.NewLLVM()
var (
pathname *check.Absolute
checksum [2]unique.Handle[pkg.Checksum]
)
if pathname, _, err = cache.Cure(stage1); err != nil {
return err
}
log.Println("stage1:", pathname)
if pathname, checksum[0], err = cache.Cure(stage2); err != nil {
return err
}
log.Println("stage2:", pathname)
if pathname, checksum[1], err = cache.Cure(stage3); err != nil {
return err
}
log.Println("stage3:", pathname)
if checksum[0] != checksum[1] {
err = &pkg.ChecksumMismatchError{
Got: checksum[0].Value(),
Want: checksum[1].Value(),
}
} else {
log.Println(
"stage2 is identical to stage3",
"("+pkg.Encode(checksum[0].Value())+")",
)
}
if flagStage0 {
if pathname, _, err = cache.Cure(
t.Load(rosa.Stage0),
); err != nil {
return err
}
log.Println(pathname)
}
return
},
).
Flag(
&flagGentoo,
"gentoo", command.StringFlag(""),
"Bootstrap from a Gentoo stage3 tarball",
).
Flag(
&flagChecksum,
"checksum", command.StringFlag(""),
"Checksum of Gentoo stage3 tarball",
).
Flag(
&flagStage0,
"stage0", command.BoolFlag(false),
"Create bootstrap stage0 tarball",
)
}
{
var (
flagDump string
flagExport string
) )
c.NewCommand( c.NewCommand(
"cure", "cure",
@@ -446,37 +162,13 @@ func main() {
return errors.New("cure requires 1 argument") return errors.New("cure requires 1 argument")
} }
if p, ok := rosa.ResolveName(args[0]); !ok { if p, ok := rosa.ResolveName(args[0]); !ok {
return fmt.Errorf("unknown artifact %q", args[0]) return fmt.Errorf("unsupported artifact %q", args[0])
} else if flagDump == "" { } else if flagDump == "" {
pathname, _, err := cache.Cure(rosa.Std.Load(p)) pathname, _, err := cache.Cure(rosa.Std.Load(p))
if err != nil { if err == nil {
return err log.Println(pathname)
} }
log.Println(pathname) return err
if flagExport != "" {
msg.Verbosef("exporting %s to %s...", args[0], flagExport)
var f *os.File
if f, err = os.OpenFile(
flagExport,
os.O_WRONLY|os.O_CREATE|os.O_EXCL,
0400,
); err != nil {
return err
} else if _, err = pkg.Flatten(
os.DirFS(pathname.String()),
".",
f,
); err != nil {
_ = f.Close()
return err
} else if err = f.Close(); err != nil {
return err
}
}
return nil
} else { } else {
f, err := os.OpenFile( f, err := os.OpenFile(
flagDump, flagDump,
@@ -500,173 +192,13 @@ func main() {
&flagDump, &flagDump,
"dump", command.StringFlag(""), "dump", command.StringFlag(""),
"Write IR to specified pathname and terminate", "Write IR to specified pathname and terminate",
).
Flag(
&flagExport,
"export", command.StringFlag(""),
"Export cured artifact to specified pathname",
) )
} }
{
var (
flagNet bool
flagSession bool
flagWithToolchain bool
)
c.NewCommand(
"shell",
"Interactive shell in the specified Rosa OS environment",
func(args []string) error {
presets := make([]rosa.PArtifact, len(args))
for i, arg := range args {
p, ok := rosa.ResolveName(arg)
if !ok {
return fmt.Errorf("unknown artifact %q", arg)
}
presets[i] = p
}
root := make(rosa.Collect, 0, 6+len(args))
root = rosa.Std.AppendPresets(root, presets...)
if flagWithToolchain {
musl, compilerRT, runtimes, clang := (rosa.Std - 1).NewLLVM()
root = append(root, musl, compilerRT, runtimes, clang)
} else {
root = append(root, rosa.Std.Load(rosa.Musl))
}
root = append(root,
rosa.Std.Load(rosa.Mksh),
rosa.Std.Load(rosa.Toybox),
)
if _, _, err := cache.Cure(&root); err == nil {
return errors.New("unreachable")
} else if !errors.Is(err, rosa.Collected{}) {
return err
}
type cureRes struct {
pathname *check.Absolute
checksum unique.Handle[pkg.Checksum]
}
cured := make(map[pkg.Artifact]cureRes)
for _, a := range root {
pathname, checksum, err := cache.Cure(a)
if err != nil {
return err
}
cured[a] = cureRes{pathname, checksum}
}
layers := pkg.PromoteLayers(root, func(a pkg.Artifact) (
*check.Absolute,
unique.Handle[pkg.Checksum],
) {
res := cured[a]
return res.pathname, res.checksum
}, func(i int, d pkg.Artifact) {
r := pkg.Encode(cache.Ident(d).Value())
if s, ok := d.(fmt.Stringer); ok {
if name := s.String(); name != "" {
r += "-" + name
}
}
msg.Verbosef("promoted layer %d as %s", i, r)
})
z := container.New(ctx, msg)
z.WaitDelay = 3 * time.Second
z.SeccompPresets = pkg.SeccompPresets
z.SeccompFlags |= seccomp.AllowMultiarch
z.ParentPerm = 0700
z.HostNet = flagNet
z.RetainSession = flagSession
z.Hostname = "localhost"
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
var tempdir *check.Absolute
if s, err := filepath.Abs(os.TempDir()); err != nil {
return err
} else if tempdir, err = check.NewAbs(s); err != nil {
return err
}
z.Dir = fhs.AbsRoot
z.Env = []string{
"SHELL=/system/bin/mksh",
"PATH=/system/bin",
"HOME=/",
}
z.Path = rosa.AbsSystem.Append("bin", "mksh")
z.Args = []string{"mksh"}
z.
OverlayEphemeral(fhs.AbsRoot, layers...).
Place(
fhs.AbsEtc.Append("hosts"),
[]byte("127.0.0.1 localhost\n"),
).
Place(
fhs.AbsEtc.Append("passwd"),
[]byte("media_rw:x:1023:1023::/:/system/bin/sh\n"+
"nobody:x:65534:65534::/proc/nonexistent:/system/bin/false\n"),
).
Place(
fhs.AbsEtc.Append("group"),
[]byte("media_rw:x:1023:\nnobody:x:65534:\n"),
).
Bind(tempdir, fhs.AbsTmp, std.BindWritable).
Proc(fhs.AbsProc).Dev(fhs.AbsDev, true)
if err := z.Start(); err != nil {
return err
}
if err := z.Serve(); err != nil {
return err
}
return z.Wait()
},
).
Flag(
&flagNet,
"net", command.BoolFlag(false),
"Share host net namespace",
).
Flag(
&flagSession,
"session", command.BoolFlag(false),
"Retain session",
).
Flag(
&flagWithToolchain,
"with-toolchain", command.BoolFlag(false),
"Include the stage3 LLVM toolchain",
)
}
c.Command(
"help",
"Show this help message",
func([]string) error { c.PrintHelp(); return nil },
)
c.MustParse(os.Args[1:], func(err error) { c.MustParse(os.Args[1:], func(err error) {
if cache != nil { if cache != nil {
cache.Close() cache.Close()
} }
if w, ok := err.(interface{ Unwrap() []error }); !ok { log.Fatal(err)
log.Fatal(err)
} else {
errs := w.Unwrap()
for i, e := range errs {
if i == len(errs)-1 {
log.Fatal(e)
}
log.Println(e)
}
}
}) })
} }

View File

@@ -31,10 +31,9 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"hakurei.app/check"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/helper/proc" "hakurei.app/internal/helper/proc"
"hakurei.app/internal/info" "hakurei.app/internal/info"
@@ -442,7 +441,12 @@ func _main(s ...string) (exitCode int) {
// keep fuse_parse_cmdline happy in the container // keep fuse_parse_cmdline happy in the container
z.Tmpfs(check.MustAbs(container.Nonexistent), 1<<10, 0755) z.Tmpfs(check.MustAbs(container.Nonexistent), 1<<10, 0755)
z.Path = fhs.AbsProcSelfExe if a, err := check.NewAbs(container.MustExecutable(msg)); err != nil {
log.Println(err)
return 5
} else {
z.Path = a
}
z.Args = s z.Args = s
z.ForwardCancel = true z.ForwardCancel = true
z.SeccompPresets |= std.PresetStrict z.SeccompPresets |= std.PresetStrict

View File

@@ -6,7 +6,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
) )
func TestParseOpts(t *testing.T) { func TestParseOpts(t *testing.T) {

View File

@@ -4,13 +4,14 @@ import (
"encoding/gob" "encoding/gob"
"fmt" "fmt"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
) )
func init() { gob.Register(new(AutoEtcOp)) } func init() { gob.Register(new(AutoEtcOp)) }
// Etc is a helper for appending [AutoEtcOp] to [Ops]. // Etc appends an [Op] that expands host /etc into a toplevel symlink mirror with /etc semantics.
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
func (f *Ops) Etc(host *check.Absolute, prefix string) *Ops { func (f *Ops) Etc(host *check.Absolute, prefix string) *Ops {
e := &AutoEtcOp{prefix} e := &AutoEtcOp{prefix}
f.Mkdir(fhs.AbsEtc, 0755) f.Mkdir(fhs.AbsEtc, 0755)
@@ -19,9 +20,6 @@ func (f *Ops) Etc(host *check.Absolute, prefix string) *Ops {
return f return f
} }
// AutoEtcOp expands host /etc into a toplevel symlink mirror with /etc semantics.
//
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
type AutoEtcOp struct{ Prefix string } type AutoEtcOp struct{ Prefix string }
func (e *AutoEtcOp) Valid() bool { return e != nil } func (e *AutoEtcOp) Valid() bool { return e != nil }

View File

@@ -5,8 +5,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestAutoEtcOp(t *testing.T) { func TestAutoEtcOp(t *testing.T) {

View File

@@ -4,22 +4,20 @@ import (
"encoding/gob" "encoding/gob"
"fmt" "fmt"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
"hakurei.app/message" "hakurei.app/message"
) )
func init() { gob.Register(new(AutoRootOp)) } func init() { gob.Register(new(AutoRootOp)) }
// Root is a helper for appending [AutoRootOp] to [Ops]. // Root appends an [Op] that expands a directory into a toplevel bind mount mirror on container root.
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
func (f *Ops) Root(host *check.Absolute, flags int) *Ops { func (f *Ops) Root(host *check.Absolute, flags int) *Ops {
*f = append(*f, &AutoRootOp{host, flags, nil}) *f = append(*f, &AutoRootOp{host, flags, nil})
return f return f
} }
// AutoRootOp expands a directory into a toplevel bind mount mirror on container root.
//
// This is not a generic setup op. It is implemented here to reduce ipc overhead.
type AutoRootOp struct { type AutoRootOp struct {
Host *check.Absolute Host *check.Absolute
// passed through to bindMount // passed through to bindMount

View File

@@ -5,9 +5,9 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
"hakurei.app/message" "hakurei.app/message"
) )

View File

@@ -3,8 +3,6 @@ package container
import ( import (
"syscall" "syscall"
"unsafe" "unsafe"
"hakurei.app/ext"
) )
const ( const (
@@ -52,16 +50,10 @@ func capset(hdrp *capHeader, datap *[2]capData) error {
} }
// capBoundingSetDrop drops a capability from the calling thread's capability bounding set. // capBoundingSetDrop drops a capability from the calling thread's capability bounding set.
func capBoundingSetDrop(cap uintptr) error { func capBoundingSetDrop(cap uintptr) error { return Prctl(syscall.PR_CAPBSET_DROP, cap, 0) }
return ext.Prctl(syscall.PR_CAPBSET_DROP, cap, 0)
}
// capAmbientClearAll clears the ambient capability set of the calling thread. // capAmbientClearAll clears the ambient capability set of the calling thread.
func capAmbientClearAll() error { func capAmbientClearAll() error { return Prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0) }
return ext.Prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0)
}
// capAmbientRaise adds to the ambient capability set of the calling thread. // capAmbientRaise adds to the ambient capability set of the calling thread.
func capAmbientRaise(cap uintptr) error { func capAmbientRaise(cap uintptr) error { return Prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap) }
return ext.Prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap)
}

View File

@@ -11,12 +11,12 @@ import (
"testing" "testing"
_ "unsafe" // for go:linkname _ "unsafe" // for go:linkname
. "hakurei.app/check" . "hakurei.app/container/check"
) )
// unsafeAbs returns check.Absolute on any string value. // unsafeAbs returns check.Absolute on any string value.
// //
//go:linkname unsafeAbs hakurei.app/check.unsafeAbs //go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs
func unsafeAbs(pathname string) *Absolute func unsafeAbs(pathname string) *Absolute
func TestAbsoluteError(t *testing.T) { func TestAbsoluteError(t *testing.T) {

View File

@@ -11,8 +11,7 @@ const (
SpecialOverlayPath = ":" SpecialOverlayPath = ":"
) )
// EscapeOverlayDataSegment escapes a string for formatting into the data // EscapeOverlayDataSegment escapes a string for formatting into the data argument of an overlay mount call.
// argument of an overlay mount system call.
func EscapeOverlayDataSegment(s string) string { func EscapeOverlayDataSegment(s string) string {
if s == "" { if s == "" {
return "" return ""

View File

@@ -3,7 +3,7 @@ package check_test
import ( import (
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
) )
func TestEscapeOverlayDataSegment(t *testing.T) { func TestEscapeOverlayDataSegment(t *testing.T) {

View File

@@ -1,5 +1,4 @@
// Package container implements unprivileged Linux containers with built-in // Package container implements unprivileged Linux containers with built-in support for syscall filtering.
// support for syscall filtering.
package container package container
import ( import (
@@ -16,11 +15,10 @@ import (
. "syscall" . "syscall"
"time" "time"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/ext"
"hakurei.app/fhs"
"hakurei.app/message" "hakurei.app/message"
) )
@@ -39,34 +37,24 @@ type (
Container struct { Container struct {
// Whether the container init should stay alive after its parent terminates. // Whether the container init should stay alive after its parent terminates.
AllowOrphan bool AllowOrphan bool
// Whether to set SchedPolicy and SchedPriority via sched_setscheduler(2).
SetScheduler bool
// Scheduling policy to set via sched_setscheduler(2).
SchedPolicy ext.SchedPolicy
// Scheduling priority to set via sched_setscheduler(2). The zero value
// implies the minimum value supported by the current SchedPolicy.
SchedPriority ext.Int
// Cgroup fd, nil to disable. // Cgroup fd, nil to disable.
Cgroup *int Cgroup *int
// ExtraFiles passed through to initial process in the container, with // ExtraFiles passed through to initial process in the container,
// behaviour identical to its [exec.Cmd] counterpart. // with behaviour identical to its [exec.Cmd] counterpart.
ExtraFiles []*os.File ExtraFiles []*os.File
// Write end of a pipe connected to the init to deliver [Params]. // param pipe for shim and init
setup *os.File setup *os.File
// Cancels the context passed to the underlying cmd. // cancels cmd
cancel context.CancelFunc cancel context.CancelFunc
// Closed after Wait returns. Keeps the spawning thread alive. // closed after Wait returns
wait chan struct{} wait chan struct{}
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer
Stderr io.Writer Stderr io.Writer
// Custom cancellation behaviour for the underlying [exec.Cmd]. Must Cancel func(cmd *exec.Cmd) error
// deliver [CancelSignal] before returning.
Cancel func(cmd *exec.Cmd) error
// Copied to the underlying [exec.Cmd].
WaitDelay time.Duration WaitDelay time.Duration
cmd *exec.Cmd cmd *exec.Cmd
@@ -186,24 +174,31 @@ var (
closeOnExecErr error closeOnExecErr error
) )
// ensureCloseOnExec ensures all currently open file descriptors have the // ensureCloseOnExec ensures all currently open file descriptors have the syscall.FD_CLOEXEC flag set.
// 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.
// 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 { func ensureCloseOnExec() error {
closeOnExecOnce.Do(func() { closeOnExecErr = doCloseOnExec() }) 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 { if closeOnExecErr == nil {
return nil return nil
} }
return &StartError{ return &StartError{Fatal: true, Step: "set FD_CLOEXEC on all open files", Err: closeOnExecErr, Passthrough: true}
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. // Start starts the container init. The init process blocks until Serve is called.
@@ -288,11 +283,7 @@ func (p *Container) Start() error {
// place setup pipe before user supplied extra files, this is later restored by init // place setup pipe before user supplied extra files, this is later restored by init
if fd, f, err := Setup(&p.cmd.ExtraFiles); err != nil { if fd, f, err := Setup(&p.cmd.ExtraFiles); err != nil {
return &StartError{ return &StartError{true, "set up params stream", err, false, false}
Fatal: true,
Step: "set up params stream",
Err: err,
}
} else { } else {
p.setup = f p.setup = f
p.cmd.Env = []string{setupEnv + "=" + strconv.Itoa(fd)} p.cmd.Env = []string{setupEnv + "=" + strconv.Itoa(fd)}
@@ -304,16 +295,10 @@ func (p *Container) Start() error {
runtime.LockOSThread() runtime.LockOSThread()
p.wait = make(chan struct{}) p.wait = make(chan struct{})
// setup depending on per-thread state must happen here done <- func() error { // setup depending on per-thread state must happen here
done <- func() error { // PR_SET_NO_NEW_PRIVS: depends on per-thread state but acts on all processes created from that thread
// PR_SET_NO_NEW_PRIVS: thread-directed but acts on all processes
// created from the calling thread
if err := SetNoNewPrivs(); err != nil { if err := SetNoNewPrivs(); err != nil {
return &StartError{ return &StartError{true, "prctl(PR_SET_NO_NEW_PRIVS)", err, false, false}
Fatal: true,
Step: "prctl(PR_SET_NO_NEW_PRIVS)",
Err: err,
}
} }
// landlock: depends on per-thread state but acts on a process group // landlock: depends on per-thread state but acts on a process group
@@ -325,40 +310,28 @@ func (p *Container) Start() error {
if abi, err := LandlockGetABI(); err != nil { if abi, err := LandlockGetABI(); err != nil {
if p.HostAbstract { if p.HostAbstract {
// landlock can be skipped here as it restricts access // landlock can be skipped here as it restricts access to resources
// to resources already covered by namespaces (pid) // already covered by namespaces (pid)
goto landlockOut goto landlockOut
} }
return &StartError{Step: "get landlock ABI", Err: err} return &StartError{false, "get landlock ABI", err, false, false}
} else if abi < 6 { } else if abi < 6 {
if p.HostAbstract { if p.HostAbstract {
// see above comment // see above comment
goto landlockOut goto landlockOut
} }
return &StartError{ return &StartError{false, "kernel version too old for LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET", ENOSYS, true, false}
Step: "kernel too old for LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET",
Err: ENOSYS,
Origin: true,
}
} else { } else {
p.msg.Verbosef("landlock abi version %d", abi) p.msg.Verbosef("landlock abi version %d", abi)
} }
if rulesetFd, err := rulesetAttr.Create(0); err != nil { if rulesetFd, err := rulesetAttr.Create(0); err != nil {
return &StartError{ return &StartError{true, "create landlock ruleset", err, false, false}
Fatal: true,
Step: "create landlock ruleset",
Err: err,
}
} else { } else {
p.msg.Verbosef("enforcing landlock ruleset %s", rulesetAttr) p.msg.Verbosef("enforcing landlock ruleset %s", rulesetAttr)
if err = LandlockRestrictSelf(rulesetFd, 0); err != nil { if err = LandlockRestrictSelf(rulesetFd, 0); err != nil {
_ = Close(rulesetFd) _ = Close(rulesetFd)
return &StartError{ return &StartError{true, "enforce landlock ruleset", err, false, false}
Fatal: true,
Step: "enforce landlock ruleset",
Err: err,
}
} }
if err = Close(rulesetFd); err != nil { if err = Close(rulesetFd); err != nil {
p.msg.Verbosef("cannot close landlock ruleset: %v", err) p.msg.Verbosef("cannot close landlock ruleset: %v", err)
@@ -369,52 +342,9 @@ func (p *Container) Start() error {
landlockOut: landlockOut:
} }
// sched_setscheduler: thread-directed but acts on all processes
// created from the calling thread
if p.SetScheduler {
if p.SchedPolicy < 0 || p.SchedPolicy > ext.SCHED_LAST {
return &StartError{
Fatal: false,
Step: "set scheduling policy",
Err: EINVAL,
}
}
var param schedParam
if priority, err := p.SchedPolicy.GetPriorityMin(); err != nil {
return &StartError{
Fatal: true,
Step: "get minimum priority",
Err: err,
}
} else {
param.priority = max(priority, p.SchedPriority)
}
p.msg.Verbosef(
"setting scheduling policy %s priority %d",
p.SchedPolicy, param.priority,
)
if err := schedSetscheduler(
0, // calling thread
p.SchedPolicy,
&param,
); err != nil {
return &StartError{
Fatal: true,
Step: "set scheduling policy",
Err: err,
}
}
}
p.msg.Verbose("starting container init") p.msg.Verbose("starting container init")
if err := p.cmd.Start(); err != nil { if err := p.cmd.Start(); err != nil {
return &StartError{ return &StartError{false, "start container init", err, false, true}
Step: "start container init",
Err: err,
Passthrough: true,
}
} }
return nil return nil
}() }()
@@ -426,7 +356,6 @@ func (p *Container) Start() error {
} }
// Serve serves [Container.Params] to the container init. // Serve serves [Container.Params] to the container init.
//
// Serve must only be called once. // Serve must only be called once.
func (p *Container) Serve() error { func (p *Container) Serve() error {
if p.setup == nil { if p.setup == nil {
@@ -436,21 +365,12 @@ func (p *Container) Serve() error {
setup := p.setup setup := p.setup
p.setup = nil p.setup = nil
if err := setup.SetDeadline(time.Now().Add(initSetupTimeout)); err != nil { if err := setup.SetDeadline(time.Now().Add(initSetupTimeout)); err != nil {
return &StartError{ return &StartError{true, "set init pipe deadline", err, false, true}
Fatal: true,
Step: "set init pipe deadline",
Err: err,
Passthrough: true,
}
} }
if p.Path == nil { if p.Path == nil {
p.cancel() p.cancel()
return &StartError{ return &StartError{false, "invalid executable pathname", EINVAL, true, false}
Step: "invalid executable pathname",
Err: EINVAL,
Origin: true,
}
} }
// do not transmit nil // do not transmit nil
@@ -475,8 +395,7 @@ func (p *Container) Serve() error {
return err return err
} }
// Wait blocks until the container init process to exit and releases any // Wait waits for the container init process to exit and releases any resources associated with the [Container].
// resources associated with the [Container].
func (p *Container) Wait() error { func (p *Container) Wait() error {
if p.cmd == nil || p.cmd.Process == nil { if p.cmd == nil || p.cmd.Process == nil {
return EINVAL return EINVAL
@@ -521,13 +440,11 @@ func (p *Container) StderrPipe() (r io.ReadCloser, err error) {
} }
func (p *Container) String() string { func (p *Container) String() string {
return fmt.Sprintf( return fmt.Sprintf("argv: %q, filter: %v, rules: %d, flags: %#x, presets: %#x",
"argv: %q, filter: %v, rules: %d, flags: %#x, presets: %#x", p.Args, !p.SeccompDisable, len(p.SeccompRules), int(p.SeccompFlags), int(p.SeccompPresets))
p.Args, !p.SeccompDisable, len(p.SeccompRules), int(p.SeccompFlags), int(p.SeccompPresets),
)
} }
// ProcessState returns the address of os.ProcessState held by the underlying [exec.Cmd]. // ProcessState returns the address to os.ProcessState held by the underlying [exec.Cmd].
func (p *Container) ProcessState() *os.ProcessState { func (p *Container) ProcessState() *os.ProcessState {
if p.cmd == nil { if p.cmd == nil {
return nil return nil
@@ -535,8 +452,7 @@ func (p *Container) ProcessState() *os.ProcessState {
return p.cmd.ProcessState return p.cmd.ProcessState
} }
// New returns the address to a new instance of [Container]. This value requires // New returns the address to a new instance of [Container] that requires further initialisation before use.
// further initialisation before use.
func New(ctx context.Context, msg message.Msg) *Container { func New(ctx context.Context, msg message.Msg) *Container {
if msg == nil { if msg == nil {
msg = message.New(nil) msg = message.New(nil)
@@ -545,18 +461,12 @@ func New(ctx context.Context, msg message.Msg) *Container {
p := &Container{ctx: ctx, msg: msg, Params: Params{Ops: new(Ops)}} p := &Container{ctx: ctx, msg: msg, Params: Params{Ops: new(Ops)}}
c, cancel := context.WithCancel(ctx) c, cancel := context.WithCancel(ctx)
p.cancel = cancel p.cancel = cancel
p.cmd = exec.CommandContext(c, fhs.ProcSelfExe) p.cmd = exec.CommandContext(c, MustExecutable(msg))
return p return p
} }
// NewCommand calls [New] and initialises the [Params.Path] and [Params.Args] fields. // NewCommand calls [New] and initialises the [Params.Path] and [Params.Args] fields.
func NewCommand( func NewCommand(ctx context.Context, msg message.Msg, pathname *check.Absolute, name string, args ...string) *Container {
ctx context.Context,
msg message.Msg,
pathname *check.Absolute,
name string,
args ...string,
) *Container {
z := New(ctx, msg) z := New(ctx, msg)
z.Path = pathname z.Path = pathname
z.Args = append([]string{name}, args...) z.Args = append([]string{name}, args...)

View File

@@ -18,17 +18,16 @@ import (
"testing" "testing"
"time" "time"
"hakurei.app/check"
"hakurei.app/command" "hakurei.app/command"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/ext" "hakurei.app/container/vfs"
"hakurei.app/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/ldd" "hakurei.app/ldd"
"hakurei.app/message" "hakurei.app/message"
"hakurei.app/vfs"
) )
// Note: this package requires cgo, which is unavailable in the Go playground. // Note: this package requires cgo, which is unavailable in the Go playground.
@@ -259,7 +258,7 @@ var containerTestCases = []struct {
1000, 100, nil, 0, std.PresetExt}, 1000, 100, nil, 0, std.PresetExt},
{"custom rules", true, true, true, false, {"custom rules", true, true, true, false,
emptyOps, emptyMnt, emptyOps, emptyMnt,
1, 31, []std.NativeRule{{Syscall: ext.SyscallNum(syscall.SYS_SETUID), Errno: std.ScmpErrno(syscall.EPERM)}}, 0, std.PresetExt}, 1, 31, []std.NativeRule{{Syscall: std.ScmpSyscall(syscall.SYS_SETUID), Errno: std.ScmpErrno(syscall.EPERM)}}, 0, std.PresetExt},
{"tmpfs", true, false, false, true, {"tmpfs", true, false, false, true,
earlyOps(new(container.Ops). earlyOps(new(container.Ops).
@@ -774,13 +773,14 @@ func TestMain(m *testing.M) {
func helperNewContainerLibPaths(ctx context.Context, libPaths *[]*check.Absolute, args ...string) (c *container.Container) { func helperNewContainerLibPaths(ctx context.Context, libPaths *[]*check.Absolute, args ...string) (c *container.Container) {
msg := message.New(nil) msg := message.New(nil)
msg.SwapVerbose(testing.Verbose()) msg.SwapVerbose(testing.Verbose())
executable := check.MustAbs(container.MustExecutable(msg))
c = container.NewCommand(ctx, msg, absHelperInnerPath, "helper", args...) c = container.NewCommand(ctx, msg, absHelperInnerPath, "helper", args...)
c.Env = append(c.Env, envDoCheck+"=1") c.Env = append(c.Env, envDoCheck+"=1")
c.Bind(fhs.AbsProcSelfExe, absHelperInnerPath, 0) c.Bind(executable, absHelperInnerPath, 0)
// in case test has cgo enabled // in case test has cgo enabled
if entries, err := ldd.Resolve(ctx, msg, nil); err != nil { if entries, err := ldd.Resolve(ctx, msg, executable); err != nil {
log.Fatalf("ldd: %v", err) log.Fatalf("ldd: %v", err)
} else { } else {
*libPaths = ldd.Path(entries) *libPaths = ldd.Path(entries)

View File

@@ -3,7 +3,6 @@ package container
import ( import (
"io" "io"
"io/fs" "io/fs"
"net"
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
@@ -13,8 +12,6 @@ import (
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/ext"
"hakurei.app/internal/netlink"
"hakurei.app/message" "hakurei.app/message"
) )
@@ -24,8 +21,7 @@ type osFile interface {
fs.File fs.File
} }
// syscallDispatcher provides methods that make state-dependent system calls as // syscallDispatcher provides methods that make state-dependent system calls as part of their behaviour.
// part of their behaviour.
type syscallDispatcher interface { type syscallDispatcher interface {
// new starts a goroutine with a new instance of syscallDispatcher. // new starts a goroutine with a new instance of syscallDispatcher.
// A syscallDispatcher must never be used in any goroutine other than the one owning it, // A syscallDispatcher must never be used in any goroutine other than the one owning it,
@@ -144,8 +140,8 @@ func (k direct) new(f func(k syscallDispatcher)) { go f(k) }
func (direct) lockOSThread() { runtime.LockOSThread() } func (direct) lockOSThread() { runtime.LockOSThread() }
func (direct) setPtracer(pid uintptr) error { return ext.SetPtracer(pid) } func (direct) setPtracer(pid uintptr) error { return SetPtracer(pid) }
func (direct) setDumpable(dumpable uintptr) error { return ext.SetDumpable(dumpable) } func (direct) setDumpable(dumpable uintptr) error { return SetDumpable(dumpable) }
func (direct) setNoNewPrivs() error { return SetNoNewPrivs() } func (direct) setNoNewPrivs() error { return SetNoNewPrivs() }
func (direct) lastcap(msg message.Msg) uintptr { return LastCap(msg) } func (direct) lastcap(msg message.Msg) uintptr { return LastCap(msg) }
@@ -153,7 +149,7 @@ func (direct) capset(hdrp *capHeader, datap *[2]capData) error { return capset(h
func (direct) capBoundingSetDrop(cap uintptr) error { return capBoundingSetDrop(cap) } func (direct) capBoundingSetDrop(cap uintptr) error { return capBoundingSetDrop(cap) }
func (direct) capAmbientClearAll() error { return capAmbientClearAll() } func (direct) capAmbientClearAll() error { return capAmbientClearAll() }
func (direct) capAmbientRaise(cap uintptr) error { return capAmbientRaise(cap) } func (direct) capAmbientRaise(cap uintptr) error { return capAmbientRaise(cap) }
func (direct) isatty(fd int) bool { return ext.Isatty(fd) } func (direct) isatty(fd int) bool { return Isatty(fd) }
func (direct) receive(key string, e any, fdp *uintptr) (func() error, error) { func (direct) receive(key string, e any, fdp *uintptr) (func() error, error) {
return Receive(key, e, fdp) return Receive(key, e, fdp)
} }
@@ -170,47 +166,7 @@ func (k direct) mountTmpfs(fsname, target string, flags uintptr, size int, perm
func (direct) ensureFile(name string, perm, pperm os.FileMode) error { func (direct) ensureFile(name string, perm, pperm os.FileMode) error {
return ensureFile(name, perm, pperm) return ensureFile(name, perm, pperm)
} }
func (direct) mustLoopback(msg message.Msg) { func (direct) mustLoopback(msg message.Msg) { mustLoopback(msg) }
var lo int
if ifi, err := net.InterfaceByName("lo"); err != nil {
msg.GetLogger().Fatalln(err)
} else {
lo = ifi.Index
}
c, err := netlink.DialRoute()
if err != nil {
msg.GetLogger().Fatalln(err)
}
must := func(err error) {
if err == nil {
return
}
if closeErr := c.Close(); closeErr != nil {
msg.Verbosef("cannot close RTNETLINK: %v", closeErr)
}
switch err.(type) {
case *os.SyscallError:
msg.GetLogger().Fatalf("cannot %v", err)
case syscall.Errno:
msg.GetLogger().Fatalf("RTNETLINK answers: %v", err)
default:
msg.GetLogger().Fatalf("RTNETLINK answers with malformed message")
}
}
must(c.SendNewaddrLo(uint32(lo)))
must(c.SendIfInfomsg(syscall.RTM_NEWLINK, 0, &syscall.IfInfomsg{
Family: syscall.AF_UNSPEC,
Index: int32(lo),
Flags: syscall.IFF_UP,
Change: syscall.IFF_UP,
}))
must(c.Close())
}
func (direct) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error { func (direct) seccompLoad(rules []std.NativeRule, flags seccomp.ExportFlag) error {
return seccomp.Load(rules, flags) return seccomp.Load(rules, flags)

View File

@@ -18,7 +18,7 @@ import (
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
"hakurei.app/message" "hakurei.app/message"
) )
@@ -238,11 +238,8 @@ func sliceAddr[S any](s []S) *[]S { return &s }
func newCheckedFile(t *testing.T, name, wantData string, closeErr error) osFile { func newCheckedFile(t *testing.T, name, wantData string, closeErr error) osFile {
f := &checkedOsFile{t: t, name: name, want: wantData, closeErr: closeErr} f := &checkedOsFile{t: t, name: name, want: wantData, closeErr: closeErr}
// check happens in Close, and cleanup is not guaranteed to run, so relying // check happens in Close, and cleanup is not guaranteed to run, so relying on it for sloppy implementations will cause sporadic test results
// on it for sloppy implementations will cause sporadic test results f.cleanup = runtime.AddCleanup(f, func(name string) { f.t.Fatalf("checkedOsFile %s became unreachable without a call to Close", name) }, f.name)
f.cleanup = runtime.AddCleanup(f, func(name string) {
panic("checkedOsFile " + name + " became unreachable without a call to Close")
}, name)
return f return f
} }

View File

@@ -5,9 +5,9 @@ import (
"os" "os"
"syscall" "syscall"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/container/vfs"
"hakurei.app/message" "hakurei.app/message"
"hakurei.app/vfs"
) )
// messageFromError returns a printable error message for a supported concrete type. // messageFromError returns a printable error message for a supported concrete type.
@@ -43,8 +43,7 @@ func messageFromError(err error) (m string, ok bool) {
} }
// messagePrefix checks and prefixes the error message of a non-pointer error. // messagePrefix checks and prefixes the error message of a non-pointer error.
// While this is usable for pointer errors, such use should be avoided as nil // While this is usable for pointer errors, such use should be avoided as nil check is omitted.
// check is omitted.
func messagePrefix[T error](prefix string, err error) (string, bool) { func messagePrefix[T error](prefix string, err error) (string, bool) {
var targetError T var targetError T
if errors.As(err, &targetError) { if errors.As(err, &targetError) {

View File

@@ -8,9 +8,9 @@ import (
"syscall" "syscall"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
"hakurei.app/vfs" "hakurei.app/container/vfs"
) )
func TestMessageFromError(t *testing.T) { func TestMessageFromError(t *testing.T) {

34
container/executable.go Normal file
View File

@@ -0,0 +1,34 @@
package container
import (
"fmt"
"log"
"os"
"sync"
"hakurei.app/message"
)
var (
executable string
executableOnce sync.Once
)
func copyExecutable(msg message.Msg) {
if name, err := os.Executable(); err != nil {
m := fmt.Sprintf("cannot read executable path: %v", err)
if msg != nil {
msg.BeforeExit()
msg.GetLogger().Fatal(m)
} else {
log.Fatal(m)
}
} else {
executable = name
}
}
func MustExecutable(msg message.Msg) string {
executableOnce.Do(func() { copyExecutable(msg) })
return executable
}

View File

@@ -0,0 +1,18 @@
package container_test
import (
"os"
"testing"
"hakurei.app/container"
"hakurei.app/message"
)
func TestExecutable(t *testing.T) {
t.Parallel()
for i := 0; i < 16; i++ {
if got := container.MustExecutable(message.New(nil)); got != os.Args[0] {
t.Errorf("MustExecutable: %q, want %q", got, os.Args[0])
}
}
}

View File

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

View File

@@ -9,8 +9,7 @@ const (
// Tmp points to the place for small temporary files. // Tmp points to the place for small temporary files.
Tmp = "/tmp/" Tmp = "/tmp/"
// Run points to a "tmpfs" file system for system packages to place runtime // Run points to a "tmpfs" file system for system packages to place runtime data, socket files, and similar.
// data, socket files, and similar.
Run = "/run/" Run = "/run/"
// RunUser points to a directory containing per-user runtime directories, // RunUser points to a directory containing per-user runtime directories,
// each usually individually mounted "tmpfs" instances. // each usually individually mounted "tmpfs" instances.
@@ -18,12 +17,10 @@ const (
// Usr points to vendor-supplied operating system resources. // Usr points to vendor-supplied operating system resources.
Usr = "/usr/" Usr = "/usr/"
// UsrBin points to binaries and executables for user commands that shall // UsrBin points to binaries and executables for user commands that shall appear in the $PATH search path.
// appear in the $PATH search path.
UsrBin = Usr + "bin/" UsrBin = Usr + "bin/"
// Var points to persistent, variable system data. Writable during normal // Var points to persistent, variable system data. Writable during normal system operation.
// system operation.
Var = "/var/" Var = "/var/"
// VarLib points to persistent system data. // VarLib points to persistent system data.
VarLib = Var + "lib/" VarLib = Var + "lib/"
@@ -32,20 +29,12 @@ const (
// Dev points to the root directory for device nodes. // Dev points to the root directory for device nodes.
Dev = "/dev/" Dev = "/dev/"
// DevShm is the place for POSIX shared memory segments, as created via // DevShm is the place for POSIX shared memory segments, as created via shm_open(3).
// shm_open(3).
DevShm = "/dev/shm/" DevShm = "/dev/shm/"
// Proc points to a virtual kernel file system exposing the process list and // Proc points to a virtual kernel file system exposing the process list and other functionality.
// other functionality.
Proc = "/proc/" Proc = "/proc/"
// ProcSys points to a hierarchy below /proc/ that exposes a number of // ProcSys points to a hierarchy below /proc/ that exposes a number of kernel tunables.
// kernel tunables.
ProcSys = Proc + "sys/" ProcSys = Proc + "sys/"
// ProcSelf resolves to the process's own /proc/pid directory. // Sys points to a virtual kernel file system exposing discovered devices and other functionality.
ProcSelf = Proc + "self/"
// ProcSelfExe is a symbolic link to program pathname.
ProcSelfExe = ProcSelf + "exe"
// Sys points to a virtual kernel file system exposing discovered devices
// and other functionality.
Sys = "/sys/" Sys = "/sys/"
) )

View File

@@ -15,9 +15,8 @@ import (
. "syscall" . "syscall"
"time" "time"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/ext"
"hakurei.app/fhs"
"hakurei.app/message" "hakurei.app/message"
) )
@@ -34,12 +33,12 @@ const (
- This path is only accessible by init and root: - This path is only accessible by init and root:
The container init sets SUID_DUMP_DISABLE and terminates if that fails. The container init sets SUID_DUMP_DISABLE and terminates if that fails.
It should be noted that none of this should become relevant at any point It should be noted that none of this should become relevant at any point since the resulting
since the resulting intermediate root tmpfs should be effectively anonymous. */ intermediate root tmpfs should be effectively anonymous. */
intermediateHostPath = fhs.Proc + "self/fd" intermediateHostPath = fhs.Proc + "self/fd"
// setupEnv is the name of the environment variable holding the string // setupEnv is the name of the environment variable holding the string representation of
// representation of the read end file descriptor of the setup params pipe. // the read end file descriptor of the setup params pipe.
setupEnv = "HAKUREI_SETUP" setupEnv = "HAKUREI_SETUP"
// exitUnexpectedWait4 is the exit code if wait4 returns an unexpected errno. // exitUnexpectedWait4 is the exit code if wait4 returns an unexpected errno.
@@ -60,8 +59,7 @@ type (
// late is called right before starting the initial process. // late is called right before starting the initial process.
late(state *setupState, k syscallDispatcher) error late(state *setupState, k syscallDispatcher) error
// prefix returns a log message prefix, and whether this Op prints no // prefix returns a log message prefix, and whether this Op prints no identifying message on its own.
// identifying message on its own.
prefix() (string, bool) prefix() (string, bool)
Is(op Op) bool Is(op Op) bool
@@ -73,11 +71,9 @@ type (
setupState struct { setupState struct {
nonrepeatable uintptr nonrepeatable uintptr
// Whether early reaping has concluded. Must only be accessed in the // Whether early reaping has concluded. Must only be accessed in the wait4 loop.
// wait4 loop.
processConcluded bool processConcluded bool
// Process to syscall.WaitStatus populated in the wait4 loop. Freed // Process to syscall.WaitStatus populated in the wait4 loop. Freed after early reaping concludes.
// after early reaping concludes.
process map[int]WaitStatus process map[int]WaitStatus
// Synchronises access to process. // Synchronises access to process.
processMu sync.RWMutex processMu sync.RWMutex
@@ -179,7 +175,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
} }
// write uid/gid map here so parent does not need to set dumpable // write uid/gid map here so parent does not need to set dumpable
if err := k.setDumpable(ext.SUID_DUMP_USER); err != nil { if err := k.setDumpable(SUID_DUMP_USER); err != nil {
k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err) k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err)
} }
if err := k.writeFile(fhs.Proc+"self/uid_map", if err := k.writeFile(fhs.Proc+"self/uid_map",
@@ -197,7 +193,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
0); err != nil { 0); err != nil {
k.fatalf(msg, "%v", err) k.fatalf(msg, "%v", err)
} }
if err := k.setDumpable(ext.SUID_DUMP_DISABLE); err != nil { if err := k.setDumpable(SUID_DUMP_DISABLE); err != nil {
k.fatalf(msg, "cannot set SUID_DUMP_DISABLE: %v", err) k.fatalf(msg, "cannot set SUID_DUMP_DISABLE: %v", err)
} }
@@ -220,10 +216,9 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
defer cancel() defer cancel()
/* early is called right before pivot_root into intermediate root; /* early is called right before pivot_root into intermediate root;
this step is mostly for gathering information that would otherwise be this step is mostly for gathering information that would otherwise be difficult to obtain
difficult to obtain via library functions after pivot_root, and via library functions after pivot_root, and implementations are expected to avoid changing
implementations are expected to avoid changing the state of the mount the state of the mount namespace */
namespace */
for i, op := range *params.Ops { for i, op := range *params.Ops {
if op == nil || !op.Valid() { if op == nil || !op.Valid() {
k.fatalf(msg, "invalid op at index %d", i) k.fatalf(msg, "invalid op at index %d", i)
@@ -263,10 +258,10 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
k.fatalf(msg, "cannot enter intermediate root: %v", err) k.fatalf(msg, "cannot enter intermediate root: %v", err)
} }
/* apply is called right after pivot_root and entering the new root. This /* apply is called right after pivot_root and entering the new root;
step sets up the container filesystem, and implementations are expected to this step sets up the container filesystem, and implementations are expected to keep the host root
keep the host root and sysroot mount points intact but otherwise can do and sysroot mount points intact but otherwise can do whatever they need to;
whatever they need to. Calling chdir is allowed but discouraged. */ chdir is allowed but discouraged */
for i, op := range *params.Ops { for i, op := range *params.Ops {
// ops already checked during early setup // ops already checked during early setup
if prefix, ok := op.prefix(); ok { if prefix, ok := op.prefix(); ok {
@@ -291,7 +286,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
{ {
var fd int var fd int
if err := ext.IgnoringEINTR(func() (err error) { if err := IgnoringEINTR(func() (err error) {
fd, err = k.open(fhs.Root, O_DIRECTORY|O_RDONLY, 0) fd, err = k.open(fhs.Root, O_DIRECTORY|O_RDONLY, 0)
return return
}); err != nil { }); err != nil {

View File

@@ -7,10 +7,10 @@ import (
"testing" "testing"
"time" "time"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestInitEntrypoint(t *testing.T) { func TestInitEntrypoint(t *testing.T) {

View File

@@ -6,22 +6,20 @@ import (
"os" "os"
"syscall" "syscall"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/container/std" "hakurei.app/container/std"
) )
func init() { gob.Register(new(BindMountOp)) } func init() { gob.Register(new(BindMountOp)) }
// Bind is a helper for appending [BindMountOp] to [Ops]. // Bind appends an [Op] that bind mounts host path [BindMountOp.Source] on container path [BindMountOp.Target].
func (f *Ops) Bind(source, target *check.Absolute, flags int) *Ops { func (f *Ops) Bind(source, target *check.Absolute, flags int) *Ops {
*f = append(*f, &BindMountOp{nil, source, target, flags}) *f = append(*f, &BindMountOp{nil, source, target, flags})
return f return f
} }
// BindMountOp creates a bind mount from host path Source to container path Target. // BindMountOp bind mounts host path Source on container path Target.
// // Note that Flags uses bits declared in this package and should not be set with constants in [syscall].
// Note that Flags uses bits declared in the [std] package and should not be set
// with constants in [syscall].
type BindMountOp struct { type BindMountOp struct {
sourceFinal, Source, Target *check.Absolute sourceFinal, Source, Target *check.Absolute

View File

@@ -6,9 +6,9 @@ import (
"syscall" "syscall"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestBindMountOp(t *testing.T) { func TestBindMountOp(t *testing.T) {

View File

@@ -12,8 +12,8 @@ import (
"syscall" "syscall"
"time" "time"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
) )
func init() { gob.Register(new(DaemonOp)) } func init() { gob.Register(new(DaemonOp)) }
@@ -24,7 +24,8 @@ const (
daemonTimeout = 5 * time.Second daemonTimeout = 5 * time.Second
) )
// Daemon is a helper for appending [DaemonOp] to [Ops]. // Daemon appends an [Op] that starts a daemon in the container and blocks until
// [DaemonOp.Target] appears.
func (f *Ops) Daemon(target, path *check.Absolute, args ...string) *Ops { func (f *Ops) Daemon(target, path *check.Absolute, args ...string) *Ops {
*f = append(*f, &DaemonOp{target, path, args}) *f = append(*f, &DaemonOp{target, path, args})
return f return f

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
"hakurei.app/message" "hakurei.app/message"
) )

View File

@@ -6,8 +6,8 @@ import (
"path" "path"
. "syscall" . "syscall"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
) )
func init() { gob.Register(new(MountDevOp)) } func init() { gob.Register(new(MountDevOp)) }
@@ -19,9 +19,7 @@ func (f *Ops) Dev(target *check.Absolute, mqueue bool) *Ops {
} }
// DevWritable appends an [Op] that mounts a writable subset of host /dev. // DevWritable appends an [Op] that mounts a writable subset of host /dev.
// // There is usually no good reason to write to /dev, so this should always be followed by a [RemountOp].
// There is usually no good reason to write to /dev, so this should always be
// followed by a [RemountOp].
func (f *Ops) DevWritable(target *check.Absolute, mqueue bool) *Ops { func (f *Ops) DevWritable(target *check.Absolute, mqueue bool) *Ops {
*f = append(*f, &MountDevOp{target, mqueue, true}) *f = append(*f, &MountDevOp{target, mqueue, true})
return f return f

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestMountDevOp(t *testing.T) { func TestMountDevOp(t *testing.T) {

View File

@@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"os" "os"
"hakurei.app/check" "hakurei.app/container/check"
) )
func init() { gob.Register(new(MkdirOp)) } func init() { gob.Register(new(MkdirOp)) }
// Mkdir is a helper for appending [MkdirOp] to [Ops]. // Mkdir appends an [Op] that creates a directory in the container filesystem.
func (f *Ops) Mkdir(name *check.Absolute, perm os.FileMode) *Ops { func (f *Ops) Mkdir(name *check.Absolute, perm os.FileMode) *Ops {
*f = append(*f, &MkdirOp{name, perm}) *f = append(*f, &MkdirOp{name, perm})
return f return f

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestMkdirOp(t *testing.T) { func TestMkdirOp(t *testing.T) {

View File

@@ -6,8 +6,8 @@ import (
"slices" "slices"
"strings" "strings"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
) )
const ( const (
@@ -54,11 +54,8 @@ func (e *OverlayArgumentError) Error() string {
} }
} }
// Overlay is a helper for appending [MountOverlayOp] to [Ops]. // Overlay appends an [Op] that mounts the overlay pseudo filesystem on [MountOverlayOp.Target].
func (f *Ops) Overlay( func (f *Ops) Overlay(target, state, work *check.Absolute, layers ...*check.Absolute) *Ops {
target, state, work *check.Absolute,
layers ...*check.Absolute,
) *Ops {
*f = append(*f, &MountOverlayOp{ *f = append(*f, &MountOverlayOp{
Target: target, Target: target,
Lower: layers, Lower: layers,
@@ -68,12 +65,13 @@ func (f *Ops) Overlay(
return f return f
} }
// OverlayEphemeral appends a [MountOverlayOp] with an ephemeral upperdir and workdir. // OverlayEphemeral appends an [Op] that mounts the overlay pseudo filesystem on [MountOverlayOp.Target]
// with an ephemeral upperdir and workdir.
func (f *Ops) OverlayEphemeral(target *check.Absolute, layers ...*check.Absolute) *Ops { func (f *Ops) OverlayEphemeral(target *check.Absolute, layers ...*check.Absolute) *Ops {
return f.Overlay(target, fhs.AbsRoot, nil, layers...) return f.Overlay(target, fhs.AbsRoot, nil, layers...)
} }
// OverlayReadonly appends a readonly [MountOverlayOp]. // OverlayReadonly appends an [Op] that mounts the overlay pseudo filesystem readonly on [MountOverlayOp.Target]
func (f *Ops) OverlayReadonly(target *check.Absolute, layers ...*check.Absolute) *Ops { func (f *Ops) OverlayReadonly(target *check.Absolute, layers ...*check.Absolute) *Ops {
return f.Overlay(target, nil, nil, layers...) return f.Overlay(target, nil, nil, layers...)
} }
@@ -84,34 +82,25 @@ type MountOverlayOp struct {
// Any filesystem, does not need to be on a writable filesystem. // Any filesystem, does not need to be on a writable filesystem.
Lower []*check.Absolute Lower []*check.Absolute
// Formatted for [OptionOverlayLowerdir]. // formatted for [OptionOverlayLowerdir], resolved, prefixed and escaped during early
//
// Resolved, prefixed and escaped during early.
lower []string lower []string
// The upperdir is normally on a writable filesystem. // The upperdir is normally on a writable filesystem.
// //
// If Work is nil and Upper holds the special value [fhs.AbsRoot], an // If Work is nil and Upper holds the special value [fhs.AbsRoot],
// ephemeral upperdir and workdir will be set up. // an ephemeral upperdir and workdir will be set up.
// //
// If both Work and Upper are nil, upperdir and workdir is omitted and the // If both Work and Upper are nil, upperdir and workdir is omitted and the overlay is mounted readonly.
// overlay is mounted readonly.
Upper *check.Absolute Upper *check.Absolute
// Formatted for [OptionOverlayUpperdir]. // formatted for [OptionOverlayUpperdir], resolved, prefixed and escaped during early
//
// Resolved, prefixed and escaped during early.
upper string upper string
// The workdir needs to be an empty directory on the same filesystem as upperdir. // The workdir needs to be an empty directory on the same filesystem as upperdir.
Work *check.Absolute Work *check.Absolute
// Formatted for [OptionOverlayWorkdir]. // formatted for [OptionOverlayWorkdir], resolved, prefixed and escaped during early
//
// Resolved, prefixed and escaped during early.
work string work string
ephemeral bool ephemeral bool
// Used internally for mounting to the intermediate root. // used internally for mounting to the intermediate root
noPrefix bool noPrefix bool
} }

View File

@@ -5,8 +5,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestMountOverlayOp(t *testing.T) { func TestMountOverlayOp(t *testing.T) {

View File

@@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"syscall" "syscall"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/fhs" "hakurei.app/container/fhs"
) )
const ( const (
@@ -16,7 +16,7 @@ const (
func init() { gob.Register(new(TmpfileOp)) } func init() { gob.Register(new(TmpfileOp)) }
// Place is a helper for appending [TmpfileOp] to [Ops]. // Place appends an [Op] that places a file in container path [TmpfileOp.Path] containing [TmpfileOp.Data].
func (f *Ops) Place(name *check.Absolute, data []byte) *Ops { func (f *Ops) Place(name *check.Absolute, data []byte) *Ops {
*f = append(*f, &TmpfileOp{name, data}) *f = append(*f, &TmpfileOp{name, data})
return f return f

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestTmpfileOp(t *testing.T) { func TestTmpfileOp(t *testing.T) {
@@ -21,7 +21,7 @@ func TestTmpfileOp(t *testing.T) {
Path: samplePath, Path: samplePath,
Data: sampleData, Data: sampleData,
}, nil, nil, []stub.Call{ }, nil, nil, []stub.Call{
call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, (*checkedOsFile)(nil), stub.UniqueError(5)), call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), stub.UniqueError(5)),
}, stub.UniqueError(5)}, }, stub.UniqueError(5)},
{"Write", &Params{ParentPerm: 0700}, &TmpfileOp{ {"Write", &Params{ParentPerm: 0700}, &TmpfileOp{
@@ -35,14 +35,14 @@ func TestTmpfileOp(t *testing.T) {
Path: samplePath, Path: samplePath,
Data: sampleData, Data: sampleData,
}, nil, nil, []stub.Call{ }, nil, nil, []stub.Call{
call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.Close", sampleDataString, stub.UniqueError(3)), nil), call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, stub.UniqueError(3)), nil),
}, stub.UniqueError(3)}, }, stub.UniqueError(3)},
{"ensureFile", &Params{ParentPerm: 0700}, &TmpfileOp{ {"ensureFile", &Params{ParentPerm: 0700}, &TmpfileOp{
Path: samplePath, Path: samplePath,
Data: sampleData, Data: sampleData,
}, nil, nil, []stub.Call{ }, nil, nil, []stub.Call{
call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.ensureFile", sampleDataString, nil), nil), call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil),
call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, stub.UniqueError(2)), call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, stub.UniqueError(2)),
}, stub.UniqueError(2)}, }, stub.UniqueError(2)},
@@ -50,29 +50,29 @@ func TestTmpfileOp(t *testing.T) {
Path: samplePath, Path: samplePath,
Data: sampleData, Data: sampleData,
}, nil, nil, []stub.Call{ }, nil, nil, []stub.Call{
call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.bindMount", sampleDataString, nil), nil), call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil),
call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil), call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil),
call("bindMount", stub.ExpectArgs{"tmp.bindMount", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, stub.UniqueError(1)), call("bindMount", stub.ExpectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, stub.UniqueError(1)),
}, stub.UniqueError(1)}, }, stub.UniqueError(1)},
{"remove", &Params{ParentPerm: 0700}, &TmpfileOp{ {"remove", &Params{ParentPerm: 0700}, &TmpfileOp{
Path: samplePath, Path: samplePath,
Data: sampleData, Data: sampleData,
}, nil, nil, []stub.Call{ }, nil, nil, []stub.Call{
call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.remove", sampleDataString, nil), nil), call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil),
call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil), call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil),
call("bindMount", stub.ExpectArgs{"tmp.remove", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil), call("bindMount", stub.ExpectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil),
call("remove", stub.ExpectArgs{"tmp.remove"}, nil, stub.UniqueError(0)), call("remove", stub.ExpectArgs{"tmp.32768"}, nil, stub.UniqueError(0)),
}, stub.UniqueError(0)}, }, stub.UniqueError(0)},
{"success", &Params{ParentPerm: 0700}, &TmpfileOp{ {"success", &Params{ParentPerm: 0700}, &TmpfileOp{
Path: samplePath, Path: samplePath,
Data: sampleData, Data: sampleData,
}, nil, nil, []stub.Call{ }, nil, nil, []stub.Call{
call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.success", sampleDataString, nil), nil), call("createTemp", stub.ExpectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil),
call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil), call("ensureFile", stub.ExpectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil),
call("bindMount", stub.ExpectArgs{"tmp.success", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil), call("bindMount", stub.ExpectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil),
call("remove", stub.ExpectArgs{"tmp.success"}, nil, nil), call("remove", stub.ExpectArgs{"tmp.32768"}, nil, nil),
}, nil}, }, nil},
}) })

View File

@@ -5,12 +5,12 @@ import (
"fmt" "fmt"
. "syscall" . "syscall"
"hakurei.app/check" "hakurei.app/container/check"
) )
func init() { gob.Register(new(MountProcOp)) } func init() { gob.Register(new(MountProcOp)) }
// Proc is a helper for appending [MountProcOp] to [Ops]. // Proc appends an [Op] that mounts a private instance of proc.
func (f *Ops) Proc(target *check.Absolute) *Ops { func (f *Ops) Proc(target *check.Absolute) *Ops {
*f = append(*f, &MountProcOp{target}) *f = append(*f, &MountProcOp{target})
return f return f

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestMountProcOp(t *testing.T) { func TestMountProcOp(t *testing.T) {

View File

@@ -4,12 +4,12 @@ import (
"encoding/gob" "encoding/gob"
"fmt" "fmt"
"hakurei.app/check" "hakurei.app/container/check"
) )
func init() { gob.Register(new(RemountOp)) } func init() { gob.Register(new(RemountOp)) }
// Remount is a helper for appending [RemountOp] to [Ops]. // Remount appends an [Op] that applies [RemountOp.Flags] on container path [RemountOp.Target].
func (f *Ops) Remount(target *check.Absolute, flags uintptr) *Ops { func (f *Ops) Remount(target *check.Absolute, flags uintptr) *Ops {
*f = append(*f, &RemountOp{target, flags}) *f = append(*f, &RemountOp{target, flags})
return f return f

View File

@@ -4,8 +4,8 @@ import (
"syscall" "syscall"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestRemountOp(t *testing.T) { func TestRemountOp(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"path" "path"
"hakurei.app/check" "hakurei.app/container/check"
) )
func init() { gob.Register(new(SymlinkOp)) } func init() { gob.Register(new(SymlinkOp)) }

View File

@@ -4,8 +4,8 @@ import (
"os" "os"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestSymlinkOp(t *testing.T) { func TestSymlinkOp(t *testing.T) {

View File

@@ -8,7 +8,7 @@ import (
"strconv" "strconv"
. "syscall" . "syscall"
"hakurei.app/check" "hakurei.app/container/check"
) )
func init() { gob.Register(new(MountTmpfsOp)) } func init() { gob.Register(new(MountTmpfsOp)) }

View File

@@ -5,8 +5,8 @@ import (
"syscall" "syscall"
"testing" "testing"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestMountTmpfsOp(t *testing.T) { func TestMountTmpfsOp(t *testing.T) {

View File

@@ -5,7 +5,7 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"hakurei.app/ext" "hakurei.app/container/std"
) )
// include/uapi/linux/landlock.h // include/uapi/linux/landlock.h
@@ -38,7 +38,6 @@ const (
_LANDLOCK_ACCESS_FS_DELIM _LANDLOCK_ACCESS_FS_DELIM
) )
// String returns a space-separated string of [LandlockAccessFS] flags.
func (f LandlockAccessFS) String() string { func (f LandlockAccessFS) String() string {
switch f { switch f {
case LANDLOCK_ACCESS_FS_EXECUTE: case LANDLOCK_ACCESS_FS_EXECUTE:
@@ -117,7 +116,6 @@ const (
_LANDLOCK_ACCESS_NET_DELIM _LANDLOCK_ACCESS_NET_DELIM
) )
// String returns a space-separated string of [LandlockAccessNet] flags.
func (f LandlockAccessNet) String() string { func (f LandlockAccessNet) String() string {
switch f { switch f {
case LANDLOCK_ACCESS_NET_BIND_TCP: case LANDLOCK_ACCESS_NET_BIND_TCP:
@@ -154,7 +152,6 @@ const (
_LANDLOCK_SCOPE_DELIM _LANDLOCK_SCOPE_DELIM
) )
// String returns a space-separated string of [LandlockScope] flags.
func (f LandlockScope) String() string { func (f LandlockScope) String() string {
switch f { switch f {
case LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: case LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET:
@@ -187,12 +184,10 @@ type RulesetAttr struct {
HandledAccessFS LandlockAccessFS HandledAccessFS LandlockAccessFS
// Bitmask of handled network actions. // Bitmask of handled network actions.
HandledAccessNet LandlockAccessNet HandledAccessNet LandlockAccessNet
// Bitmask of scopes restricting a Landlock domain from accessing outside // Bitmask of scopes restricting a Landlock domain from accessing outside resources (e.g. IPCs).
// resources (e.g. IPCs).
Scoped LandlockScope Scoped LandlockScope
} }
// String returns a user-facing description of [RulesetAttr].
func (rulesetAttr *RulesetAttr) String() string { func (rulesetAttr *RulesetAttr) String() string {
if rulesetAttr == nil { if rulesetAttr == nil {
return "NULL" return "NULL"
@@ -213,7 +208,6 @@ func (rulesetAttr *RulesetAttr) String() string {
return strings.Join(elems, ", ") return strings.Join(elems, ", ")
} }
// Create loads the ruleset into the kernel.
func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) { func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) {
var pointer, size uintptr var pointer, size uintptr
// NULL needed for abi version // NULL needed for abi version
@@ -222,13 +216,10 @@ func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) {
size = unsafe.Sizeof(*rulesetAttr) size = unsafe.Sizeof(*rulesetAttr)
} }
rulesetFd, _, errno := syscall.Syscall( rulesetFd, _, errno := syscall.Syscall(std.SYS_LANDLOCK_CREATE_RULESET, pointer, size, flags)
ext.SYS_LANDLOCK_CREATE_RULESET,
pointer, size,
flags,
)
fd = int(rulesetFd) fd = int(rulesetFd)
err = errno err = errno
if fd < 0 { if fd < 0 {
return return
} }
@@ -239,19 +230,12 @@ func (rulesetAttr *RulesetAttr) Create(flags uintptr) (fd int, err error) {
return fd, nil return fd, nil
} }
// LandlockGetABI returns the ABI version supported by the kernel.
func LandlockGetABI() (int, error) { func LandlockGetABI() (int, error) {
return (*RulesetAttr)(nil).Create(LANDLOCK_CREATE_RULESET_VERSION) return (*RulesetAttr)(nil).Create(LANDLOCK_CREATE_RULESET_VERSION)
} }
// LandlockRestrictSelf applies a loaded ruleset to the calling thread.
func LandlockRestrictSelf(rulesetFd int, flags uintptr) error { func LandlockRestrictSelf(rulesetFd int, flags uintptr) error {
r, _, errno := syscall.Syscall( r, _, errno := syscall.Syscall(std.SYS_LANDLOCK_RESTRICT_SELF, uintptr(rulesetFd), flags, 0)
ext.SYS_LANDLOCK_RESTRICT_SELF,
uintptr(rulesetFd),
flags,
0,
)
if r != 0 { if r != 0 {
return errno return errno
} }

View File

@@ -6,9 +6,8 @@ import (
"os" "os"
. "syscall" . "syscall"
"hakurei.app/ext" "hakurei.app/container/vfs"
"hakurei.app/message" "hakurei.app/message"
"hakurei.app/vfs"
) )
/* /*
@@ -116,7 +115,7 @@ func (p *procPaths) remount(msg message.Msg, target string, flags uintptr) error
var targetKFinal string var targetKFinal string
{ {
var destFd int var destFd int
if err := ext.IgnoringEINTR(func() (err error) { if err := IgnoringEINTR(func() (err error) {
destFd, err = p.k.open(targetFinal, O_PATH|O_CLOEXEC, 0) destFd, err = p.k.open(targetFinal, O_PATH|O_CLOEXEC, 0)
return return
}); err != nil { }); err != nil {

View File

@@ -5,8 +5,8 @@ import (
"syscall" "syscall"
"testing" "testing"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
"hakurei.app/vfs" "hakurei.app/container/vfs"
) )
func TestBindMount(t *testing.T) { func TestBindMount(t *testing.T) {

269
container/netlink.go Normal file
View File

@@ -0,0 +1,269 @@
package container
import (
"encoding/binary"
"errors"
"net"
"os"
. "syscall"
"unsafe"
"hakurei.app/container/std"
"hakurei.app/message"
)
// rtnetlink represents a NETLINK_ROUTE socket.
type rtnetlink struct {
// Sent as part of rtnetlink messages.
pid uint32
// AF_NETLINK socket.
fd int
// Whether the socket is open.
ok bool
// Message sequence number.
seq uint32
}
// open creates the underlying NETLINK_ROUTE socket.
func (s *rtnetlink) open() (err error) {
if s.ok || s.fd < 0 {
return os.ErrInvalid
}
s.pid = uint32(Getpid())
if s.fd, err = Socket(
AF_NETLINK,
SOCK_RAW|SOCK_CLOEXEC,
NETLINK_ROUTE,
); err != nil {
return os.NewSyscallError("socket", err)
} else if err = Bind(s.fd, &SockaddrNetlink{
Family: AF_NETLINK,
Pid: s.pid,
}); err != nil {
_ = s.close()
return os.NewSyscallError("bind", err)
} else {
s.ok = true
return nil
}
}
// close closes the underlying NETLINK_ROUTE socket.
func (s *rtnetlink) close() error {
if !s.ok {
return os.ErrInvalid
}
s.ok = false
err := Close(s.fd)
s.fd = -1
return err
}
// roundtrip sends a netlink message and handles the reply.
func (s *rtnetlink) roundtrip(data []byte) error {
if !s.ok {
return os.ErrInvalid
}
defer func() { s.seq++ }()
if err := Sendto(s.fd, data, 0, &SockaddrNetlink{
Family: AF_NETLINK,
}); err != nil {
return os.NewSyscallError("sendto", err)
}
buf := make([]byte, Getpagesize())
done:
for {
p := buf
if n, _, err := Recvfrom(s.fd, p, 0); err != nil {
return os.NewSyscallError("recvfrom", err)
} else if n < NLMSG_HDRLEN {
return errors.ErrUnsupported
} else {
p = p[:n]
}
if msgs, err := ParseNetlinkMessage(p); err != nil {
return err
} else {
for _, m := range msgs {
if m.Header.Seq != s.seq || m.Header.Pid != s.pid {
return errors.ErrUnsupported
}
if m.Header.Type == NLMSG_DONE {
break done
}
if m.Header.Type == NLMSG_ERROR {
if len(m.Data) >= 4 {
errno := Errno(-std.ScmpInt(binary.NativeEndian.Uint32(m.Data)))
if errno == 0 {
return nil
}
return errno
}
return errors.ErrUnsupported
}
}
}
}
return nil
}
// mustRoundtrip calls roundtrip and terminates via msg for a non-nil error.
func (s *rtnetlink) mustRoundtrip(msg message.Msg, data []byte) {
err := s.roundtrip(data)
if err == nil {
return
}
if closeErr := Close(s.fd); closeErr != nil {
msg.Verbosef("cannot close: %v", err)
}
switch err.(type) {
case *os.SyscallError:
msg.GetLogger().Fatalf("cannot %v", err)
case Errno:
msg.GetLogger().Fatalf("RTNETLINK answers: %v", err)
default:
msg.GetLogger().Fatalln("RTNETLINK answers with unexpected message")
}
}
// newaddrLo represents a RTM_NEWADDR message with two addresses.
type newaddrLo struct {
header NlMsghdr
data IfAddrmsg
r0 RtAttr
a0 [4]byte // in_addr
r1 RtAttr
a1 [4]byte // in_addr
}
// sizeofNewaddrLo is the expected size of newaddrLo.
const sizeofNewaddrLo = NLMSG_HDRLEN + SizeofIfAddrmsg + (SizeofRtAttr+4)*2
// newaddrLo returns the address of a populated newaddrLo.
func (s *rtnetlink) newaddrLo(lo int) *newaddrLo {
return &newaddrLo{NlMsghdr{
Len: sizeofNewaddrLo,
Type: RTM_NEWADDR,
Flags: NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL,
Seq: s.seq,
Pid: s.pid,
}, IfAddrmsg{
Family: AF_INET,
Prefixlen: 8,
Flags: IFA_F_PERMANENT,
Scope: RT_SCOPE_HOST,
Index: uint32(lo),
}, RtAttr{
Len: uint16(SizeofRtAttr + len(newaddrLo{}.a0)),
Type: IFA_LOCAL,
}, [4]byte{127, 0, 0, 1}, RtAttr{
Len: uint16(SizeofRtAttr + len(newaddrLo{}.a1)),
Type: IFA_ADDRESS,
}, [4]byte{127, 0, 0, 1}}
}
func (msg *newaddrLo) toWireFormat() []byte {
var buf [sizeofNewaddrLo]byte
*(*uint32)(unsafe.Pointer(&buf[0:4][0])) = msg.header.Len
*(*uint16)(unsafe.Pointer(&buf[4:6][0])) = msg.header.Type
*(*uint16)(unsafe.Pointer(&buf[6:8][0])) = msg.header.Flags
*(*uint32)(unsafe.Pointer(&buf[8:12][0])) = msg.header.Seq
*(*uint32)(unsafe.Pointer(&buf[12:16][0])) = msg.header.Pid
buf[16] = msg.data.Family
buf[17] = msg.data.Prefixlen
buf[18] = msg.data.Flags
buf[19] = msg.data.Scope
*(*uint32)(unsafe.Pointer(&buf[20:24][0])) = msg.data.Index
*(*uint16)(unsafe.Pointer(&buf[24:26][0])) = msg.r0.Len
*(*uint16)(unsafe.Pointer(&buf[26:28][0])) = msg.r0.Type
copy(buf[28:32], msg.a0[:])
*(*uint16)(unsafe.Pointer(&buf[32:34][0])) = msg.r1.Len
*(*uint16)(unsafe.Pointer(&buf[34:36][0])) = msg.r1.Type
copy(buf[36:40], msg.a1[:])
return buf[:]
}
// newlinkLo represents a RTM_NEWLINK message.
type newlinkLo struct {
header NlMsghdr
data IfInfomsg
}
// sizeofNewlinkLo is the expected size of newlinkLo.
const sizeofNewlinkLo = NLMSG_HDRLEN + SizeofIfInfomsg
// newlinkLo returns the address of a populated newlinkLo.
func (s *rtnetlink) newlinkLo(lo int) *newlinkLo {
return &newlinkLo{NlMsghdr{
Len: sizeofNewlinkLo,
Type: RTM_NEWLINK,
Flags: NLM_F_REQUEST | NLM_F_ACK,
Seq: s.seq,
Pid: s.pid,
}, IfInfomsg{
Family: AF_UNSPEC,
Index: int32(lo),
Flags: IFF_UP,
Change: IFF_UP,
}}
}
func (msg *newlinkLo) toWireFormat() []byte {
var buf [sizeofNewlinkLo]byte
*(*uint32)(unsafe.Pointer(&buf[0:4][0])) = msg.header.Len
*(*uint16)(unsafe.Pointer(&buf[4:6][0])) = msg.header.Type
*(*uint16)(unsafe.Pointer(&buf[6:8][0])) = msg.header.Flags
*(*uint32)(unsafe.Pointer(&buf[8:12][0])) = msg.header.Seq
*(*uint32)(unsafe.Pointer(&buf[12:16][0])) = msg.header.Pid
buf[16] = msg.data.Family
*(*uint16)(unsafe.Pointer(&buf[18:20][0])) = msg.data.Type
*(*int32)(unsafe.Pointer(&buf[20:24][0])) = msg.data.Index
*(*uint32)(unsafe.Pointer(&buf[24:28][0])) = msg.data.Flags
*(*uint32)(unsafe.Pointer(&buf[28:32][0])) = msg.data.Change
return buf[:]
}
// mustLoopback creates the loopback address and brings the lo interface up.
// mustLoopback calls a fatal method of the underlying [log.Logger] of m with a
// user-facing error message if RTNETLINK behaves unexpectedly.
func mustLoopback(msg message.Msg) {
log := msg.GetLogger()
var lo int
if ifi, err := net.InterfaceByName("lo"); err != nil {
log.Fatalln(err)
} else {
lo = ifi.Index
}
var s rtnetlink
if err := s.open(); err != nil {
log.Fatalln(err)
}
defer func() {
if err := s.close(); err != nil {
msg.Verbosef("cannot close netlink: %v", err)
}
}()
s.mustRoundtrip(msg, s.newaddrLo(lo).toWireFormat())
s.mustRoundtrip(msg, s.newlinkLo(lo).toWireFormat())
}

72
container/netlink_test.go Normal file
View File

@@ -0,0 +1,72 @@
package container
import (
"testing"
"unsafe"
)
func TestSizeof(t *testing.T) {
if got := unsafe.Sizeof(newaddrLo{}); got != sizeofNewaddrLo {
t.Fatalf("newaddrLo: sizeof = %#x, want %#x", got, sizeofNewaddrLo)
}
if got := unsafe.Sizeof(newlinkLo{}); got != sizeofNewlinkLo {
t.Fatalf("newlinkLo: sizeof = %#x, want %#x", got, sizeofNewlinkLo)
}
}
func TestRtnetlinkMessage(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
msg interface{ toWireFormat() []byte }
want []byte
}{
{"newaddrLo", (&rtnetlink{pid: 1, seq: 0}).newaddrLo(1), []byte{
/* Len */ 0x28, 0, 0, 0,
/* Type */ 0x14, 0,
/* Flags */ 5, 6,
/* Seq */ 0, 0, 0, 0,
/* Pid */ 1, 0, 0, 0,
/* Family */ 2,
/* Prefixlen */ 8,
/* Flags */ 0x80,
/* Scope */ 0xfe,
/* Index */ 1, 0, 0, 0,
/* Len */ 8, 0,
/* Type */ 2, 0,
/* in_addr */ 127, 0, 0, 1,
/* Len */ 8, 0,
/* Type */ 1, 0,
/* in_addr */ 127, 0, 0, 1,
}},
{"newlinkLo", (&rtnetlink{pid: 1, seq: 1}).newlinkLo(1), []byte{
/* Len */ 0x20, 0, 0, 0,
/* Type */ 0x10, 0,
/* Flags */ 5, 0,
/* Seq */ 1, 0, 0, 0,
/* Pid */ 1, 0, 0, 0,
/* Family */ 0,
/* pad */ 0,
/* Type */ 0, 0,
/* Index */ 1, 0, 0, 0,
/* Flags */ 1, 0, 0, 0,
/* Change */ 1, 0, 0, 0,
}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if got := tc.msg.toWireFormat(); string(got) != string(tc.want) {
t.Fatalf("toWireFormat: %#v, want %#v", got, tc.want)
}
})
}
}

View File

@@ -9,16 +9,13 @@ import (
"strings" "strings"
"syscall" "syscall"
"hakurei.app/fhs" "hakurei.app/container/fhs"
"hakurei.app/vfs" "hakurei.app/container/vfs"
) )
const ( const (
// Nonexistent is a path that cannot exist. // Nonexistent is a path that cannot exist.
// // /proc is chosen because a system with covered /proc is unsupported by this package.
// This path can never be presented by the kernel if proc is mounted on
// /proc/. This can only exist if parts of /proc/ is covered, or proc is not
// mounted at all. Neither configuration is supported by this package.
Nonexistent = fhs.Proc + "nonexistent" Nonexistent = fhs.Proc + "nonexistent"
hostPath = fhs.Root + hostDir hostPath = fhs.Root + hostDir

View File

@@ -10,8 +10,8 @@ import (
"testing" "testing"
"unsafe" "unsafe"
"hakurei.app/check" "hakurei.app/container/check"
"hakurei.app/vfs" "hakurei.app/container/vfs"
) )
func TestToSysroot(t *testing.T) { func TestToSysroot(t *testing.T) {

View File

@@ -16,7 +16,6 @@ import (
"unsafe" "unsafe"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/ext"
) )
// ErrInvalidRules is returned for a zero-length rules slice. // ErrInvalidRules is returned for a zero-length rules slice.
@@ -89,22 +88,18 @@ var resPrefix = [...]string{
7: "seccomp_load failed", 7: "seccomp_load failed",
} }
// cbAllocateBuffer is the function signature for the function handle passed to // cbAllocateBuffer is the function signature for the function handle passed to hakurei_export_filter
// hakurei_scmp_make_filter which allocates the buffer that the resulting bpf // which allocates the buffer that the resulting bpf program is copied into, and writes its slice header
// program is copied into, and writes its slice header to a value held by the caller. // to a value held by the caller.
type cbAllocateBuffer = func(len C.size_t) (buf unsafe.Pointer) type cbAllocateBuffer = func(len C.size_t) (buf unsafe.Pointer)
// hakurei_scmp_allocate allocates a buffer of specified size known to the
// runtime through a callback passed in a [cgo.Handle].
//
//export hakurei_scmp_allocate //export hakurei_scmp_allocate
func hakurei_scmp_allocate(f C.uintptr_t, len C.size_t) (buf unsafe.Pointer) { func hakurei_scmp_allocate(f C.uintptr_t, len C.size_t) (buf unsafe.Pointer) {
return cgo.Handle(f).Value().(cbAllocateBuffer)(len) return cgo.Handle(f).Value().(cbAllocateBuffer)(len)
} }
// makeFilter generates a bpf program from a slice of [std.NativeRule] and // makeFilter generates a bpf program from a slice of [std.NativeRule] and writes the resulting byte slice to p.
// writes the resulting byte slice to p. The filter is installed to the current // The filter is installed to the current process if p is nil.
// process if p is nil.
func makeFilter(rules []std.NativeRule, flags ExportFlag, p *[]byte) error { func makeFilter(rules []std.NativeRule, flags ExportFlag, p *[]byte) error {
if len(rules) == 0 { if len(rules) == 0 {
return ErrInvalidRules return ErrInvalidRules
@@ -175,8 +170,8 @@ func Export(rules []std.NativeRule, flags ExportFlag) (data []byte, err error) {
return return
} }
// Load generates a bpf program from a slice of [std.NativeRule] and enforces it // Load generates a bpf program from a slice of [std.NativeRule] and enforces it on the current process.
// on the current process. Errors returned by libseccomp is wrapped in [LibraryError]. // Errors returned by libseccomp is wrapped in [LibraryError].
func Load(rules []std.NativeRule, flags ExportFlag) error { return makeFilter(rules, flags, nil) } func Load(rules []std.NativeRule, flags ExportFlag) error { return makeFilter(rules, flags, nil) }
type ( type (
@@ -220,9 +215,9 @@ const (
// syscallResolveName resolves a syscall number by name via seccomp_syscall_resolve_name. // 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. // This function is only for testing the lookup tables and included here for convenience.
func syscallResolveName(s string) (num ext.SyscallNum, ok bool) { func syscallResolveName(s string) (num std.ScmpSyscall, ok bool) {
v := C.CString(s) v := C.CString(s)
num = ext.SyscallNum(C.seccomp_syscall_resolve_name(v)) num = std.ScmpSyscall(C.seccomp_syscall_resolve_name(v))
C.free(unsafe.Pointer(v)) C.free(unsafe.Pointer(v))
ok = num != C.__NR_SCMP_ERROR ok = num != C.__NR_SCMP_ERROR
return return

View File

@@ -6,7 +6,6 @@ import (
. "syscall" . "syscall"
. "hakurei.app/container/std" . "hakurei.app/container/std"
. "hakurei.app/ext"
) )
func Preset(presets FilterPreset, flags ExportFlag) (rules []NativeRule) { func Preset(presets FilterPreset, flags ExportFlag) (rules []NativeRule) {

View File

@@ -6,13 +6,12 @@ import (
"unsafe" "unsafe"
"hakurei.app/container/std" "hakurei.app/container/std"
"hakurei.app/ext"
) )
func TestSyscallResolveName(t *testing.T) { func TestSyscallResolveName(t *testing.T) {
t.Parallel() t.Parallel()
for name, want := range ext.Syscalls() { for name, want := range std.Syscalls() {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Parallel() t.Parallel()
@@ -25,10 +24,8 @@ func TestSyscallResolveName(t *testing.T) {
} }
func TestRuleType(t *testing.T) { func TestRuleType(t *testing.T) {
assertKind[ext.Uint, scmpUint](t) assertKind[std.ScmpUint, scmpUint](t)
assertOverflow(t, ext.Uint(ext.MaxUint)) assertKind[std.ScmpInt, scmpInt](t)
assertKind[ext.Int, scmpInt](t)
assertOverflow(t, ext.Int(ext.MaxInt))
assertSize[std.NativeRule, syscallRule](t) assertSize[std.NativeRule, syscallRule](t)
assertKind[std.ScmpDatum, scmpDatum](t) assertKind[std.ScmpDatum, scmpDatum](t)
@@ -64,14 +61,3 @@ func assertKind[native, equivalent any](t *testing.T) {
t.Fatalf("%s: %s, want %s", nativeType.Name(), nativeType.Kind(), equivalentType.Kind()) t.Fatalf("%s: %s, want %s", nativeType.Name(), nativeType.Kind(), equivalentType.Kind())
} }
} }
// assertOverflow asserts that incrementing m overflows.
func assertOverflow[T ~int32 | ~uint32](t *testing.T, m T) {
t.Helper()
old := m
m++
if m > old {
t.Fatalf("unexpected value %#x", m)
}
}

View File

@@ -19,11 +19,11 @@ print <<EOF;
// $command // $command
// Code generated by the command above; DO NOT EDIT. // Code generated by the command above; DO NOT EDIT.
package ext package std
import . "syscall" import . "syscall"
var syscallNum = map[string]SyscallNum{ var syscallNum = map[string]ScmpSyscall{
EOF EOF
my $offset = 0; my $offset = 0;
@@ -45,7 +45,7 @@ sub fmt {
print " \"$name\": SNR_$name_upper,\n"; print " \"$name\": SNR_$name_upper,\n";
} }
elsif($state == 1){ elsif($state == 1){
print " SNR_$name_upper SyscallNum = SYS_$name_upper\n"; print " SNR_$name_upper ScmpSyscall = SYS_$name_upper\n";
} }
else{ else{
return; return;

View File

@@ -1,6 +1,6 @@
// Code generated from include/seccomp-syscalls.h; DO NOT EDIT. // Code generated from include/seccomp-syscalls.h; DO NOT EDIT.
package ext package std
/* /*
* pseudo syscall definitions * pseudo syscall definitions

View File

@@ -1,20 +1,30 @@
package std package std
import "hakurei.app/ext" import (
"encoding/json"
"strconv"
)
type ( type (
// ScmpUint is equivalent to C.uint.
ScmpUint uint32
// ScmpInt is equivalent to C.int.
ScmpInt int32
// ScmpSyscall represents a syscall number passed to libseccomp via [NativeRule.Syscall].
ScmpSyscall ScmpInt
// ScmpErrno represents an errno value passed to libseccomp via [NativeRule.Errno]. // ScmpErrno represents an errno value passed to libseccomp via [NativeRule.Errno].
ScmpErrno = ext.Int ScmpErrno ScmpInt
// ScmpCompare is equivalent to enum scmp_compare; // ScmpCompare is equivalent to enum scmp_compare;
ScmpCompare = ext.Uint ScmpCompare ScmpUint
// ScmpDatum is equivalent to scmp_datum_t. // ScmpDatum is equivalent to scmp_datum_t.
ScmpDatum = uint64 ScmpDatum uint64
// ScmpArgCmp is equivalent to struct scmp_arg_cmp. // ScmpArgCmp is equivalent to struct scmp_arg_cmp.
ScmpArgCmp struct { ScmpArgCmp struct {
// argument number, starting at 0 // argument number, starting at 0
Arg ext.Uint `json:"arg"` Arg ScmpUint `json:"arg"`
// the comparison op, e.g. SCMP_CMP_* // the comparison op, e.g. SCMP_CMP_*
Op ScmpCompare `json:"op"` Op ScmpCompare `json:"op"`
@@ -25,10 +35,42 @@ type (
// A NativeRule specifies an arch-specific action taken by seccomp under certain conditions. // A NativeRule specifies an arch-specific action taken by seccomp under certain conditions.
NativeRule struct { NativeRule struct {
// Syscall is the arch-dependent syscall number to act against. // Syscall is the arch-dependent syscall number to act against.
Syscall ext.SyscallNum `json:"syscall"` Syscall ScmpSyscall `json:"syscall"`
// Errno is the errno value to return when the condition is satisfied. // Errno is the errno value to return when the condition is satisfied.
Errno ScmpErrno `json:"errno"` Errno ScmpErrno `json:"errno"`
// Arg is the optional struct scmp_arg_cmp passed to libseccomp. // Arg is the optional struct scmp_arg_cmp passed to libseccomp.
Arg *ScmpArgCmp `json:"arg,omitempty"` Arg *ScmpArgCmp `json:"arg,omitempty"`
} }
) )
// 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 := *num
for name, cur := range Syscalls() {
if cur == n {
return json.Marshal(name)
}
}
return json.Marshal(n)
}
// SyscallNameError is returned when trying to unmarshal an invalid syscall name into [ScmpSyscall].
type SyscallNameError string
func (e SyscallNameError) Error() string { return "invalid syscall name " + strconv.Quote(string(e)) }
// UnmarshalJSON looks up the syscall number corresponding to name encoded in data
// by calling [SyscallResolveName].
func (num *ScmpSyscall) UnmarshalJSON(data []byte) error {
var name string
if err := json.Unmarshal(data, &name); err != nil {
return err
}
if n, ok := SyscallResolveName(name); !ok {
return SyscallNameError(name)
} else {
*num = n
return nil
}
}

View File

@@ -1,4 +1,4 @@
package ext_test package std_test
import ( import (
"encoding/json" "encoding/json"
@@ -7,39 +7,39 @@ import (
"reflect" "reflect"
"testing" "testing"
"hakurei.app/ext" "hakurei.app/container/std"
) )
func TestSyscall(t *testing.T) { func TestScmpSyscall(t *testing.T) {
t.Parallel() t.Parallel()
testCases := []struct { testCases := []struct {
name string name string
data string data string
want ext.SyscallNum want std.ScmpSyscall
err error err error
}{ }{
{"epoll_create1", `"epoll_create1"`, ext.SNR_EPOLL_CREATE1, nil}, {"epoll_create1", `"epoll_create1"`, std.SNR_EPOLL_CREATE1, nil},
{"clone3", `"clone3"`, ext.SNR_CLONE3, nil}, {"clone3", `"clone3"`, std.SNR_CLONE3, nil},
{"oob", `-2147483647`, -math.MaxInt32, {"oob", `-2147483647`, -math.MaxInt32,
&json.UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[string](), Offset: 11}}, &json.UnmarshalTypeError{Value: "number", Type: reflect.TypeFor[string](), Offset: 11}},
{"name", `"nonexistent_syscall"`, -math.MaxInt32, {"name", `"nonexistent_syscall"`, -math.MaxInt32,
ext.SyscallNameError("nonexistent_syscall")}, std.SyscallNameError("nonexistent_syscall")},
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
t.Run("decode", func(t *testing.T) { t.Run("decode", func(t *testing.T) {
var got ext.SyscallNum var got std.ScmpSyscall
if err := json.Unmarshal([]byte(tc.data), &got); !reflect.DeepEqual(err, tc.err) { if err := json.Unmarshal([]byte(tc.data), &got); !reflect.DeepEqual(err, tc.err) {
t.Fatalf("Unmarshal: error = %#v, want %#v", err, tc.err) t.Fatalf("Unmarshal: error = %#v, want %#v", err, tc.err)
} else if err == nil && got != tc.want { } else if err == nil && got != tc.want {
t.Errorf("Unmarshal: %v, want %v", got, tc.want) t.Errorf("Unmarshal: %v, want %v", got, tc.want)
} }
}) })
if errors.As(tc.err, new(ext.SyscallNameError)) { if errors.As(tc.err, new(std.SyscallNameError)) {
return return
} }
@@ -55,22 +55,8 @@ func TestSyscall(t *testing.T) {
t.Run("error", func(t *testing.T) { t.Run("error", func(t *testing.T) {
const want = `invalid syscall name "\x00"` const want = `invalid syscall name "\x00"`
if got := ext.SyscallNameError("\x00").Error(); got != want { if got := std.SyscallNameError("\x00").Error(); got != want {
t.Fatalf("Error: %q, want %q", got, want) t.Fatalf("Error: %q, want %q", got, want)
} }
}) })
} }
func TestSyscallResolveName(t *testing.T) {
t.Parallel()
for name, want := range ext.Syscalls() {
t.Run(name, func(t *testing.T) {
t.Parallel()
if got, ok := ext.SyscallResolveName(name); !ok || got != want {
t.Errorf("SyscallResolveName(%q) = %d, want %d", name, got, want)
}
})
}
}

28
container/std/syscall.go Normal file
View File

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

View File

@@ -0,0 +1,13 @@
package std
var syscallNumExtra = map[string]ScmpSyscall{
"kexec_file_load": SNR_KEXEC_FILE_LOAD,
"subpage_prot": SNR_SUBPAGE_PROT,
"switch_endian": SNR_SWITCH_ENDIAN,
}
const (
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

@@ -0,0 +1,41 @@
package std
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 (
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

@@ -0,0 +1,55 @@
package std
import "syscall"
const (
SYS_NEWFSTATAT = syscall.SYS_FSTATAT
)
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 (
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
)

View File

@@ -0,0 +1,55 @@
package std
import "syscall"
const (
SYS_NEWFSTATAT = syscall.SYS_FSTATAT
)
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 (
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

View File

@@ -0,0 +1,837 @@
// mksysnum_linux.pl /usr/include/asm/unistd_64.h
// Code generated by the command above; DO NOT EDIT.
package std
import . "syscall"
var syscallNum = map[string]ScmpSyscall{
"read": SNR_READ,
"write": SNR_WRITE,
"open": SNR_OPEN,
"close": SNR_CLOSE,
"stat": SNR_STAT,
"fstat": SNR_FSTAT,
"lstat": SNR_LSTAT,
"poll": SNR_POLL,
"lseek": SNR_LSEEK,
"mmap": SNR_MMAP,
"mprotect": SNR_MPROTECT,
"munmap": SNR_MUNMAP,
"brk": SNR_BRK,
"rt_sigaction": SNR_RT_SIGACTION,
"rt_sigprocmask": SNR_RT_SIGPROCMASK,
"rt_sigreturn": SNR_RT_SIGRETURN,
"ioctl": SNR_IOCTL,
"pread64": SNR_PREAD64,
"pwrite64": SNR_PWRITE64,
"readv": SNR_READV,
"writev": SNR_WRITEV,
"access": SNR_ACCESS,
"pipe": SNR_PIPE,
"select": SNR_SELECT,
"sched_yield": SNR_SCHED_YIELD,
"mremap": SNR_MREMAP,
"msync": SNR_MSYNC,
"mincore": SNR_MINCORE,
"madvise": SNR_MADVISE,
"shmget": SNR_SHMGET,
"shmat": SNR_SHMAT,
"shmctl": SNR_SHMCTL,
"dup": SNR_DUP,
"dup2": SNR_DUP2,
"pause": SNR_PAUSE,
"nanosleep": SNR_NANOSLEEP,
"getitimer": SNR_GETITIMER,
"alarm": SNR_ALARM,
"setitimer": SNR_SETITIMER,
"getpid": SNR_GETPID,
"sendfile": SNR_SENDFILE,
"socket": SNR_SOCKET,
"connect": SNR_CONNECT,
"accept": SNR_ACCEPT,
"sendto": SNR_SENDTO,
"recvfrom": SNR_RECVFROM,
"sendmsg": SNR_SENDMSG,
"recvmsg": SNR_RECVMSG,
"shutdown": SNR_SHUTDOWN,
"bind": SNR_BIND,
"listen": SNR_LISTEN,
"getsockname": SNR_GETSOCKNAME,
"getpeername": SNR_GETPEERNAME,
"socketpair": SNR_SOCKETPAIR,
"setsockopt": SNR_SETSOCKOPT,
"getsockopt": SNR_GETSOCKOPT,
"clone": SNR_CLONE,
"fork": SNR_FORK,
"vfork": SNR_VFORK,
"execve": SNR_EXECVE,
"exit": SNR_EXIT,
"wait4": SNR_WAIT4,
"kill": SNR_KILL,
"uname": SNR_UNAME,
"semget": SNR_SEMGET,
"semop": SNR_SEMOP,
"semctl": SNR_SEMCTL,
"shmdt": SNR_SHMDT,
"msgget": SNR_MSGGET,
"msgsnd": SNR_MSGSND,
"msgrcv": SNR_MSGRCV,
"msgctl": SNR_MSGCTL,
"fcntl": SNR_FCNTL,
"flock": SNR_FLOCK,
"fsync": SNR_FSYNC,
"fdatasync": SNR_FDATASYNC,
"truncate": SNR_TRUNCATE,
"ftruncate": SNR_FTRUNCATE,
"getdents": SNR_GETDENTS,
"getcwd": SNR_GETCWD,
"chdir": SNR_CHDIR,
"fchdir": SNR_FCHDIR,
"rename": SNR_RENAME,
"mkdir": SNR_MKDIR,
"rmdir": SNR_RMDIR,
"creat": SNR_CREAT,
"link": SNR_LINK,
"unlink": SNR_UNLINK,
"symlink": SNR_SYMLINK,
"readlink": SNR_READLINK,
"chmod": SNR_CHMOD,
"fchmod": SNR_FCHMOD,
"chown": SNR_CHOWN,
"fchown": SNR_FCHOWN,
"lchown": SNR_LCHOWN,
"umask": SNR_UMASK,
"gettimeofday": SNR_GETTIMEOFDAY,
"getrlimit": SNR_GETRLIMIT,
"getrusage": SNR_GETRUSAGE,
"sysinfo": SNR_SYSINFO,
"times": SNR_TIMES,
"ptrace": SNR_PTRACE,
"getuid": SNR_GETUID,
"syslog": SNR_SYSLOG,
"getgid": SNR_GETGID,
"setuid": SNR_SETUID,
"setgid": SNR_SETGID,
"geteuid": SNR_GETEUID,
"getegid": SNR_GETEGID,
"setpgid": SNR_SETPGID,
"getppid": SNR_GETPPID,
"getpgrp": SNR_GETPGRP,
"setsid": SNR_SETSID,
"setreuid": SNR_SETREUID,
"setregid": SNR_SETREGID,
"getgroups": SNR_GETGROUPS,
"setgroups": SNR_SETGROUPS,
"setresuid": SNR_SETRESUID,
"getresuid": SNR_GETRESUID,
"setresgid": SNR_SETRESGID,
"getresgid": SNR_GETRESGID,
"getpgid": SNR_GETPGID,
"setfsuid": SNR_SETFSUID,
"setfsgid": SNR_SETFSGID,
"getsid": SNR_GETSID,
"capget": SNR_CAPGET,
"capset": SNR_CAPSET,
"rt_sigpending": SNR_RT_SIGPENDING,
"rt_sigtimedwait": SNR_RT_SIGTIMEDWAIT,
"rt_sigqueueinfo": SNR_RT_SIGQUEUEINFO,
"rt_sigsuspend": SNR_RT_SIGSUSPEND,
"sigaltstack": SNR_SIGALTSTACK,
"utime": SNR_UTIME,
"mknod": SNR_MKNOD,
"uselib": SNR_USELIB,
"personality": SNR_PERSONALITY,
"ustat": SNR_USTAT,
"statfs": SNR_STATFS,
"fstatfs": SNR_FSTATFS,
"sysfs": SNR_SYSFS,
"getpriority": SNR_GETPRIORITY,
"setpriority": SNR_SETPRIORITY,
"sched_setparam": SNR_SCHED_SETPARAM,
"sched_getparam": SNR_SCHED_GETPARAM,
"sched_setscheduler": SNR_SCHED_SETSCHEDULER,
"sched_getscheduler": SNR_SCHED_GETSCHEDULER,
"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,
"mlock": SNR_MLOCK,
"munlock": SNR_MUNLOCK,
"mlockall": SNR_MLOCKALL,
"munlockall": SNR_MUNLOCKALL,
"vhangup": SNR_VHANGUP,
"modify_ldt": SNR_MODIFY_LDT,
"pivot_root": SNR_PIVOT_ROOT,
"_sysctl": SNR__SYSCTL,
"prctl": SNR_PRCTL,
"arch_prctl": SNR_ARCH_PRCTL,
"adjtimex": SNR_ADJTIMEX,
"setrlimit": SNR_SETRLIMIT,
"chroot": SNR_CHROOT,
"sync": SNR_SYNC,
"acct": SNR_ACCT,
"settimeofday": SNR_SETTIMEOFDAY,
"mount": SNR_MOUNT,
"umount2": SNR_UMOUNT2,
"swapon": SNR_SWAPON,
"swapoff": SNR_SWAPOFF,
"reboot": SNR_REBOOT,
"sethostname": SNR_SETHOSTNAME,
"setdomainname": SNR_SETDOMAINNAME,
"iopl": SNR_IOPL,
"ioperm": SNR_IOPERM,
"create_module": SNR_CREATE_MODULE,
"init_module": SNR_INIT_MODULE,
"delete_module": SNR_DELETE_MODULE,
"get_kernel_syms": SNR_GET_KERNEL_SYMS,
"query_module": SNR_QUERY_MODULE,
"quotactl": SNR_QUOTACTL,
"nfsservctl": SNR_NFSSERVCTL,
"getpmsg": SNR_GETPMSG,
"putpmsg": SNR_PUTPMSG,
"afs_syscall": SNR_AFS_SYSCALL,
"tuxcall": SNR_TUXCALL,
"security": SNR_SECURITY,
"gettid": SNR_GETTID,
"readahead": SNR_READAHEAD,
"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,
"tkill": SNR_TKILL,
"time": SNR_TIME,
"futex": SNR_FUTEX,
"sched_setaffinity": SNR_SCHED_SETAFFINITY,
"sched_getaffinity": SNR_SCHED_GETAFFINITY,
"set_thread_area": SNR_SET_THREAD_AREA,
"io_setup": SNR_IO_SETUP,
"io_destroy": SNR_IO_DESTROY,
"io_getevents": SNR_IO_GETEVENTS,
"io_submit": SNR_IO_SUBMIT,
"io_cancel": SNR_IO_CANCEL,
"get_thread_area": SNR_GET_THREAD_AREA,
"lookup_dcookie": SNR_LOOKUP_DCOOKIE,
"epoll_create": SNR_EPOLL_CREATE,
"epoll_ctl_old": SNR_EPOLL_CTL_OLD,
"epoll_wait_old": SNR_EPOLL_WAIT_OLD,
"remap_file_pages": SNR_REMAP_FILE_PAGES,
"getdents64": SNR_GETDENTS64,
"set_tid_address": SNR_SET_TID_ADDRESS,
"restart_syscall": SNR_RESTART_SYSCALL,
"semtimedop": SNR_SEMTIMEDOP,
"fadvise64": SNR_FADVISE64,
"timer_create": SNR_TIMER_CREATE,
"timer_settime": SNR_TIMER_SETTIME,
"timer_gettime": SNR_TIMER_GETTIME,
"timer_getoverrun": SNR_TIMER_GETOVERRUN,
"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,
"exit_group": SNR_EXIT_GROUP,
"epoll_wait": SNR_EPOLL_WAIT,
"epoll_ctl": SNR_EPOLL_CTL,
"tgkill": SNR_TGKILL,
"utimes": SNR_UTIMES,
"vserver": SNR_VSERVER,
"mbind": SNR_MBIND,
"set_mempolicy": SNR_SET_MEMPOLICY,
"get_mempolicy": SNR_GET_MEMPOLICY,
"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,
"kexec_load": SNR_KEXEC_LOAD,
"waitid": SNR_WAITID,
"add_key": SNR_ADD_KEY,
"request_key": SNR_REQUEST_KEY,
"keyctl": SNR_KEYCTL,
"ioprio_set": SNR_IOPRIO_SET,
"ioprio_get": SNR_IOPRIO_GET,
"inotify_init": SNR_INOTIFY_INIT,
"inotify_add_watch": SNR_INOTIFY_ADD_WATCH,
"inotify_rm_watch": SNR_INOTIFY_RM_WATCH,
"migrate_pages": SNR_MIGRATE_PAGES,
"openat": SNR_OPENAT,
"mkdirat": SNR_MKDIRAT,
"mknodat": SNR_MKNODAT,
"fchownat": SNR_FCHOWNAT,
"futimesat": SNR_FUTIMESAT,
"newfstatat": SNR_NEWFSTATAT,
"unlinkat": SNR_UNLINKAT,
"renameat": SNR_RENAMEAT,
"linkat": SNR_LINKAT,
"symlinkat": SNR_SYMLINKAT,
"readlinkat": SNR_READLINKAT,
"fchmodat": SNR_FCHMODAT,
"faccessat": SNR_FACCESSAT,
"pselect6": SNR_PSELECT6,
"ppoll": SNR_PPOLL,
"unshare": SNR_UNSHARE,
"set_robust_list": SNR_SET_ROBUST_LIST,
"get_robust_list": SNR_GET_ROBUST_LIST,
"splice": SNR_SPLICE,
"tee": SNR_TEE,
"sync_file_range": SNR_SYNC_FILE_RANGE,
"vmsplice": SNR_VMSPLICE,
"move_pages": SNR_MOVE_PAGES,
"utimensat": SNR_UTIMENSAT,
"epoll_pwait": SNR_EPOLL_PWAIT,
"signalfd": SNR_SIGNALFD,
"timerfd_create": SNR_TIMERFD_CREATE,
"eventfd": SNR_EVENTFD,
"fallocate": SNR_FALLOCATE,
"timerfd_settime": SNR_TIMERFD_SETTIME,
"timerfd_gettime": SNR_TIMERFD_GETTIME,
"accept4": SNR_ACCEPT4,
"signalfd4": SNR_SIGNALFD4,
"eventfd2": SNR_EVENTFD2,
"epoll_create1": SNR_EPOLL_CREATE1,
"dup3": SNR_DUP3,
"pipe2": SNR_PIPE2,
"inotify_init1": SNR_INOTIFY_INIT1,
"preadv": SNR_PREADV,
"pwritev": SNR_PWRITEV,
"rt_tgsigqueueinfo": SNR_RT_TGSIGQUEUEINFO,
"perf_event_open": SNR_PERF_EVENT_OPEN,
"recvmmsg": SNR_RECVMMSG,
"fanotify_init": SNR_FANOTIFY_INIT,
"fanotify_mark": SNR_FANOTIFY_MARK,
"prlimit64": SNR_PRLIMIT64,
"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,
"sendmmsg": SNR_SENDMMSG,
"setns": SNR_SETNS,
"getcpu": SNR_GETCPU,
"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,
"kexec_file_load": SNR_KEXEC_FILE_LOAD,
"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,
"uretprobe": SNR_URETPROBE,
"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 (
SYS_NAME_TO_HANDLE_AT = 303
SYS_OPEN_BY_HANDLE_AT = 304
SYS_CLOCK_ADJTIME = 305
SYS_SYNCFS = 306
SYS_SENDMMSG = 307
SYS_SETNS = 308
SYS_GETCPU = 309
SYS_PROCESS_VM_READV = 310
SYS_PROCESS_VM_WRITEV = 311
SYS_KCMP = 312
SYS_FINIT_MODULE = 313
SYS_SCHED_SETATTR = 314
SYS_SCHED_GETATTR = 315
SYS_RENAMEAT2 = 316
SYS_SECCOMP = 317
SYS_GETRANDOM = 318
SYS_MEMFD_CREATE = 319
SYS_KEXEC_FILE_LOAD = 320
SYS_BPF = 321
SYS_EXECVEAT = 322
SYS_USERFAULTFD = 323
SYS_MEMBARRIER = 324
SYS_MLOCK2 = 325
SYS_COPY_FILE_RANGE = 326
SYS_PREADV2 = 327
SYS_PWRITEV2 = 328
SYS_PKEY_MPROTECT = 329
SYS_PKEY_ALLOC = 330
SYS_PKEY_FREE = 331
SYS_STATX = 332
SYS_IO_PGETEVENTS = 333
SYS_RSEQ = 334
SYS_URETPROBE = 335
SYS_PIDFD_SEND_SIGNAL = 424
SYS_IO_URING_SETUP = 425
SYS_IO_URING_ENTER = 426
SYS_IO_URING_REGISTER = 427
SYS_OPEN_TREE = 428
SYS_MOVE_MOUNT = 429
SYS_FSOPEN = 430
SYS_FSCONFIG = 431
SYS_FSMOUNT = 432
SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435
SYS_CLOSE_RANGE = 436
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
SYS_FACCESSAT2 = 439
SYS_PROCESS_MADVISE = 440
SYS_EPOLL_PWAIT2 = 441
SYS_MOUNT_SETATTR = 442
SYS_QUOTACTL_FD = 443
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
SYS_STATMOUNT = 457
SYS_LISTMOUNT = 458
SYS_LSM_GET_SELF_ATTR = 459
SYS_LSM_SET_SELF_ATTR = 460
SYS_LSM_LIST_MODULES = 461
SYS_MSEAL = 462
)
const (
SNR_READ ScmpSyscall = SYS_READ
SNR_WRITE ScmpSyscall = SYS_WRITE
SNR_OPEN ScmpSyscall = SYS_OPEN
SNR_CLOSE ScmpSyscall = SYS_CLOSE
SNR_STAT ScmpSyscall = SYS_STAT
SNR_FSTAT ScmpSyscall = SYS_FSTAT
SNR_LSTAT ScmpSyscall = SYS_LSTAT
SNR_POLL ScmpSyscall = SYS_POLL
SNR_LSEEK ScmpSyscall = SYS_LSEEK
SNR_MMAP ScmpSyscall = SYS_MMAP
SNR_MPROTECT ScmpSyscall = SYS_MPROTECT
SNR_MUNMAP ScmpSyscall = SYS_MUNMAP
SNR_BRK ScmpSyscall = SYS_BRK
SNR_RT_SIGACTION ScmpSyscall = SYS_RT_SIGACTION
SNR_RT_SIGPROCMASK ScmpSyscall = SYS_RT_SIGPROCMASK
SNR_RT_SIGRETURN ScmpSyscall = SYS_RT_SIGRETURN
SNR_IOCTL ScmpSyscall = SYS_IOCTL
SNR_PREAD64 ScmpSyscall = SYS_PREAD64
SNR_PWRITE64 ScmpSyscall = SYS_PWRITE64
SNR_READV ScmpSyscall = SYS_READV
SNR_WRITEV ScmpSyscall = SYS_WRITEV
SNR_ACCESS ScmpSyscall = SYS_ACCESS
SNR_PIPE ScmpSyscall = SYS_PIPE
SNR_SELECT ScmpSyscall = SYS_SELECT
SNR_SCHED_YIELD ScmpSyscall = SYS_SCHED_YIELD
SNR_MREMAP ScmpSyscall = SYS_MREMAP
SNR_MSYNC ScmpSyscall = SYS_MSYNC
SNR_MINCORE ScmpSyscall = SYS_MINCORE
SNR_MADVISE ScmpSyscall = SYS_MADVISE
SNR_SHMGET ScmpSyscall = SYS_SHMGET
SNR_SHMAT ScmpSyscall = SYS_SHMAT
SNR_SHMCTL ScmpSyscall = SYS_SHMCTL
SNR_DUP ScmpSyscall = SYS_DUP
SNR_DUP2 ScmpSyscall = SYS_DUP2
SNR_PAUSE ScmpSyscall = SYS_PAUSE
SNR_NANOSLEEP ScmpSyscall = SYS_NANOSLEEP
SNR_GETITIMER ScmpSyscall = SYS_GETITIMER
SNR_ALARM ScmpSyscall = SYS_ALARM
SNR_SETITIMER ScmpSyscall = SYS_SETITIMER
SNR_GETPID ScmpSyscall = SYS_GETPID
SNR_SENDFILE ScmpSyscall = SYS_SENDFILE
SNR_SOCKET ScmpSyscall = SYS_SOCKET
SNR_CONNECT ScmpSyscall = SYS_CONNECT
SNR_ACCEPT ScmpSyscall = SYS_ACCEPT
SNR_SENDTO ScmpSyscall = SYS_SENDTO
SNR_RECVFROM ScmpSyscall = SYS_RECVFROM
SNR_SENDMSG ScmpSyscall = SYS_SENDMSG
SNR_RECVMSG ScmpSyscall = SYS_RECVMSG
SNR_SHUTDOWN ScmpSyscall = SYS_SHUTDOWN
SNR_BIND ScmpSyscall = SYS_BIND
SNR_LISTEN ScmpSyscall = SYS_LISTEN
SNR_GETSOCKNAME ScmpSyscall = SYS_GETSOCKNAME
SNR_GETPEERNAME ScmpSyscall = SYS_GETPEERNAME
SNR_SOCKETPAIR ScmpSyscall = SYS_SOCKETPAIR
SNR_SETSOCKOPT ScmpSyscall = SYS_SETSOCKOPT
SNR_GETSOCKOPT ScmpSyscall = SYS_GETSOCKOPT
SNR_CLONE ScmpSyscall = SYS_CLONE
SNR_FORK ScmpSyscall = SYS_FORK
SNR_VFORK ScmpSyscall = SYS_VFORK
SNR_EXECVE ScmpSyscall = SYS_EXECVE
SNR_EXIT ScmpSyscall = SYS_EXIT
SNR_WAIT4 ScmpSyscall = SYS_WAIT4
SNR_KILL ScmpSyscall = SYS_KILL
SNR_UNAME ScmpSyscall = SYS_UNAME
SNR_SEMGET ScmpSyscall = SYS_SEMGET
SNR_SEMOP ScmpSyscall = SYS_SEMOP
SNR_SEMCTL ScmpSyscall = SYS_SEMCTL
SNR_SHMDT ScmpSyscall = SYS_SHMDT
SNR_MSGGET ScmpSyscall = SYS_MSGGET
SNR_MSGSND ScmpSyscall = SYS_MSGSND
SNR_MSGRCV ScmpSyscall = SYS_MSGRCV
SNR_MSGCTL ScmpSyscall = SYS_MSGCTL
SNR_FCNTL ScmpSyscall = SYS_FCNTL
SNR_FLOCK ScmpSyscall = SYS_FLOCK
SNR_FSYNC ScmpSyscall = SYS_FSYNC
SNR_FDATASYNC ScmpSyscall = SYS_FDATASYNC
SNR_TRUNCATE ScmpSyscall = SYS_TRUNCATE
SNR_FTRUNCATE ScmpSyscall = SYS_FTRUNCATE
SNR_GETDENTS ScmpSyscall = SYS_GETDENTS
SNR_GETCWD ScmpSyscall = SYS_GETCWD
SNR_CHDIR ScmpSyscall = SYS_CHDIR
SNR_FCHDIR ScmpSyscall = SYS_FCHDIR
SNR_RENAME ScmpSyscall = SYS_RENAME
SNR_MKDIR ScmpSyscall = SYS_MKDIR
SNR_RMDIR ScmpSyscall = SYS_RMDIR
SNR_CREAT ScmpSyscall = SYS_CREAT
SNR_LINK ScmpSyscall = SYS_LINK
SNR_UNLINK ScmpSyscall = SYS_UNLINK
SNR_SYMLINK ScmpSyscall = SYS_SYMLINK
SNR_READLINK ScmpSyscall = SYS_READLINK
SNR_CHMOD ScmpSyscall = SYS_CHMOD
SNR_FCHMOD ScmpSyscall = SYS_FCHMOD
SNR_CHOWN ScmpSyscall = SYS_CHOWN
SNR_FCHOWN ScmpSyscall = SYS_FCHOWN
SNR_LCHOWN ScmpSyscall = SYS_LCHOWN
SNR_UMASK ScmpSyscall = SYS_UMASK
SNR_GETTIMEOFDAY ScmpSyscall = SYS_GETTIMEOFDAY
SNR_GETRLIMIT ScmpSyscall = SYS_GETRLIMIT
SNR_GETRUSAGE ScmpSyscall = SYS_GETRUSAGE
SNR_SYSINFO ScmpSyscall = SYS_SYSINFO
SNR_TIMES ScmpSyscall = SYS_TIMES
SNR_PTRACE ScmpSyscall = SYS_PTRACE
SNR_GETUID ScmpSyscall = SYS_GETUID
SNR_SYSLOG ScmpSyscall = SYS_SYSLOG
SNR_GETGID ScmpSyscall = SYS_GETGID
SNR_SETUID ScmpSyscall = SYS_SETUID
SNR_SETGID ScmpSyscall = SYS_SETGID
SNR_GETEUID ScmpSyscall = SYS_GETEUID
SNR_GETEGID ScmpSyscall = SYS_GETEGID
SNR_SETPGID ScmpSyscall = SYS_SETPGID
SNR_GETPPID ScmpSyscall = SYS_GETPPID
SNR_GETPGRP ScmpSyscall = SYS_GETPGRP
SNR_SETSID ScmpSyscall = SYS_SETSID
SNR_SETREUID ScmpSyscall = SYS_SETREUID
SNR_SETREGID ScmpSyscall = SYS_SETREGID
SNR_GETGROUPS ScmpSyscall = SYS_GETGROUPS
SNR_SETGROUPS ScmpSyscall = SYS_SETGROUPS
SNR_SETRESUID ScmpSyscall = SYS_SETRESUID
SNR_GETRESUID ScmpSyscall = SYS_GETRESUID
SNR_SETRESGID ScmpSyscall = SYS_SETRESGID
SNR_GETRESGID ScmpSyscall = SYS_GETRESGID
SNR_GETPGID ScmpSyscall = SYS_GETPGID
SNR_SETFSUID ScmpSyscall = SYS_SETFSUID
SNR_SETFSGID ScmpSyscall = SYS_SETFSGID
SNR_GETSID ScmpSyscall = SYS_GETSID
SNR_CAPGET ScmpSyscall = SYS_CAPGET
SNR_CAPSET ScmpSyscall = SYS_CAPSET
SNR_RT_SIGPENDING ScmpSyscall = SYS_RT_SIGPENDING
SNR_RT_SIGTIMEDWAIT ScmpSyscall = SYS_RT_SIGTIMEDWAIT
SNR_RT_SIGQUEUEINFO ScmpSyscall = SYS_RT_SIGQUEUEINFO
SNR_RT_SIGSUSPEND ScmpSyscall = SYS_RT_SIGSUSPEND
SNR_SIGALTSTACK ScmpSyscall = SYS_SIGALTSTACK
SNR_UTIME ScmpSyscall = SYS_UTIME
SNR_MKNOD ScmpSyscall = SYS_MKNOD
SNR_USELIB ScmpSyscall = SYS_USELIB
SNR_PERSONALITY ScmpSyscall = SYS_PERSONALITY
SNR_USTAT ScmpSyscall = SYS_USTAT
SNR_STATFS ScmpSyscall = SYS_STATFS
SNR_FSTATFS ScmpSyscall = SYS_FSTATFS
SNR_SYSFS ScmpSyscall = SYS_SYSFS
SNR_GETPRIORITY ScmpSyscall = SYS_GETPRIORITY
SNR_SETPRIORITY ScmpSyscall = SYS_SETPRIORITY
SNR_SCHED_SETPARAM ScmpSyscall = SYS_SCHED_SETPARAM
SNR_SCHED_GETPARAM ScmpSyscall = SYS_SCHED_GETPARAM
SNR_SCHED_SETSCHEDULER ScmpSyscall = SYS_SCHED_SETSCHEDULER
SNR_SCHED_GETSCHEDULER ScmpSyscall = SYS_SCHED_GETSCHEDULER
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_MLOCK ScmpSyscall = SYS_MLOCK
SNR_MUNLOCK ScmpSyscall = SYS_MUNLOCK
SNR_MLOCKALL ScmpSyscall = SYS_MLOCKALL
SNR_MUNLOCKALL ScmpSyscall = SYS_MUNLOCKALL
SNR_VHANGUP ScmpSyscall = SYS_VHANGUP
SNR_MODIFY_LDT ScmpSyscall = SYS_MODIFY_LDT
SNR_PIVOT_ROOT ScmpSyscall = SYS_PIVOT_ROOT
SNR__SYSCTL ScmpSyscall = SYS__SYSCTL
SNR_PRCTL ScmpSyscall = SYS_PRCTL
SNR_ARCH_PRCTL ScmpSyscall = SYS_ARCH_PRCTL
SNR_ADJTIMEX ScmpSyscall = SYS_ADJTIMEX
SNR_SETRLIMIT ScmpSyscall = SYS_SETRLIMIT
SNR_CHROOT ScmpSyscall = SYS_CHROOT
SNR_SYNC ScmpSyscall = SYS_SYNC
SNR_ACCT ScmpSyscall = SYS_ACCT
SNR_SETTIMEOFDAY ScmpSyscall = SYS_SETTIMEOFDAY
SNR_MOUNT ScmpSyscall = SYS_MOUNT
SNR_UMOUNT2 ScmpSyscall = SYS_UMOUNT2
SNR_SWAPON ScmpSyscall = SYS_SWAPON
SNR_SWAPOFF ScmpSyscall = SYS_SWAPOFF
SNR_REBOOT ScmpSyscall = SYS_REBOOT
SNR_SETHOSTNAME ScmpSyscall = SYS_SETHOSTNAME
SNR_SETDOMAINNAME ScmpSyscall = SYS_SETDOMAINNAME
SNR_IOPL ScmpSyscall = SYS_IOPL
SNR_IOPERM ScmpSyscall = SYS_IOPERM
SNR_CREATE_MODULE ScmpSyscall = SYS_CREATE_MODULE
SNR_INIT_MODULE ScmpSyscall = SYS_INIT_MODULE
SNR_DELETE_MODULE ScmpSyscall = SYS_DELETE_MODULE
SNR_GET_KERNEL_SYMS ScmpSyscall = SYS_GET_KERNEL_SYMS
SNR_QUERY_MODULE ScmpSyscall = SYS_QUERY_MODULE
SNR_QUOTACTL ScmpSyscall = SYS_QUOTACTL
SNR_NFSSERVCTL ScmpSyscall = SYS_NFSSERVCTL
SNR_GETPMSG ScmpSyscall = SYS_GETPMSG
SNR_PUTPMSG ScmpSyscall = SYS_PUTPMSG
SNR_AFS_SYSCALL ScmpSyscall = SYS_AFS_SYSCALL
SNR_TUXCALL ScmpSyscall = SYS_TUXCALL
SNR_SECURITY ScmpSyscall = SYS_SECURITY
SNR_GETTID ScmpSyscall = SYS_GETTID
SNR_READAHEAD ScmpSyscall = SYS_READAHEAD
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_TKILL ScmpSyscall = SYS_TKILL
SNR_TIME ScmpSyscall = SYS_TIME
SNR_FUTEX ScmpSyscall = SYS_FUTEX
SNR_SCHED_SETAFFINITY ScmpSyscall = SYS_SCHED_SETAFFINITY
SNR_SCHED_GETAFFINITY ScmpSyscall = SYS_SCHED_GETAFFINITY
SNR_SET_THREAD_AREA ScmpSyscall = SYS_SET_THREAD_AREA
SNR_IO_SETUP ScmpSyscall = SYS_IO_SETUP
SNR_IO_DESTROY ScmpSyscall = SYS_IO_DESTROY
SNR_IO_GETEVENTS ScmpSyscall = SYS_IO_GETEVENTS
SNR_IO_SUBMIT ScmpSyscall = SYS_IO_SUBMIT
SNR_IO_CANCEL ScmpSyscall = SYS_IO_CANCEL
SNR_GET_THREAD_AREA ScmpSyscall = SYS_GET_THREAD_AREA
SNR_LOOKUP_DCOOKIE ScmpSyscall = SYS_LOOKUP_DCOOKIE
SNR_EPOLL_CREATE ScmpSyscall = SYS_EPOLL_CREATE
SNR_EPOLL_CTL_OLD ScmpSyscall = SYS_EPOLL_CTL_OLD
SNR_EPOLL_WAIT_OLD ScmpSyscall = SYS_EPOLL_WAIT_OLD
SNR_REMAP_FILE_PAGES ScmpSyscall = SYS_REMAP_FILE_PAGES
SNR_GETDENTS64 ScmpSyscall = SYS_GETDENTS64
SNR_SET_TID_ADDRESS ScmpSyscall = SYS_SET_TID_ADDRESS
SNR_RESTART_SYSCALL ScmpSyscall = SYS_RESTART_SYSCALL
SNR_SEMTIMEDOP ScmpSyscall = SYS_SEMTIMEDOP
SNR_FADVISE64 ScmpSyscall = SYS_FADVISE64
SNR_TIMER_CREATE ScmpSyscall = SYS_TIMER_CREATE
SNR_TIMER_SETTIME ScmpSyscall = SYS_TIMER_SETTIME
SNR_TIMER_GETTIME ScmpSyscall = SYS_TIMER_GETTIME
SNR_TIMER_GETOVERRUN ScmpSyscall = SYS_TIMER_GETOVERRUN
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_EXIT_GROUP ScmpSyscall = SYS_EXIT_GROUP
SNR_EPOLL_WAIT ScmpSyscall = SYS_EPOLL_WAIT
SNR_EPOLL_CTL ScmpSyscall = SYS_EPOLL_CTL
SNR_TGKILL ScmpSyscall = SYS_TGKILL
SNR_UTIMES ScmpSyscall = SYS_UTIMES
SNR_VSERVER ScmpSyscall = SYS_VSERVER
SNR_MBIND ScmpSyscall = SYS_MBIND
SNR_SET_MEMPOLICY ScmpSyscall = SYS_SET_MEMPOLICY
SNR_GET_MEMPOLICY ScmpSyscall = SYS_GET_MEMPOLICY
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_KEXEC_LOAD ScmpSyscall = SYS_KEXEC_LOAD
SNR_WAITID ScmpSyscall = SYS_WAITID
SNR_ADD_KEY ScmpSyscall = SYS_ADD_KEY
SNR_REQUEST_KEY ScmpSyscall = SYS_REQUEST_KEY
SNR_KEYCTL ScmpSyscall = SYS_KEYCTL
SNR_IOPRIO_SET ScmpSyscall = SYS_IOPRIO_SET
SNR_IOPRIO_GET ScmpSyscall = SYS_IOPRIO_GET
SNR_INOTIFY_INIT ScmpSyscall = SYS_INOTIFY_INIT
SNR_INOTIFY_ADD_WATCH ScmpSyscall = SYS_INOTIFY_ADD_WATCH
SNR_INOTIFY_RM_WATCH ScmpSyscall = SYS_INOTIFY_RM_WATCH
SNR_MIGRATE_PAGES ScmpSyscall = SYS_MIGRATE_PAGES
SNR_OPENAT ScmpSyscall = SYS_OPENAT
SNR_MKDIRAT ScmpSyscall = SYS_MKDIRAT
SNR_MKNODAT ScmpSyscall = SYS_MKNODAT
SNR_FCHOWNAT ScmpSyscall = SYS_FCHOWNAT
SNR_FUTIMESAT ScmpSyscall = SYS_FUTIMESAT
SNR_NEWFSTATAT ScmpSyscall = SYS_NEWFSTATAT
SNR_UNLINKAT ScmpSyscall = SYS_UNLINKAT
SNR_RENAMEAT ScmpSyscall = SYS_RENAMEAT
SNR_LINKAT ScmpSyscall = SYS_LINKAT
SNR_SYMLINKAT ScmpSyscall = SYS_SYMLINKAT
SNR_READLINKAT ScmpSyscall = SYS_READLINKAT
SNR_FCHMODAT ScmpSyscall = SYS_FCHMODAT
SNR_FACCESSAT ScmpSyscall = SYS_FACCESSAT
SNR_PSELECT6 ScmpSyscall = SYS_PSELECT6
SNR_PPOLL ScmpSyscall = SYS_PPOLL
SNR_UNSHARE ScmpSyscall = SYS_UNSHARE
SNR_SET_ROBUST_LIST ScmpSyscall = SYS_SET_ROBUST_LIST
SNR_GET_ROBUST_LIST ScmpSyscall = SYS_GET_ROBUST_LIST
SNR_SPLICE ScmpSyscall = SYS_SPLICE
SNR_TEE ScmpSyscall = SYS_TEE
SNR_SYNC_FILE_RANGE ScmpSyscall = SYS_SYNC_FILE_RANGE
SNR_VMSPLICE ScmpSyscall = SYS_VMSPLICE
SNR_MOVE_PAGES ScmpSyscall = SYS_MOVE_PAGES
SNR_UTIMENSAT ScmpSyscall = SYS_UTIMENSAT
SNR_EPOLL_PWAIT ScmpSyscall = SYS_EPOLL_PWAIT
SNR_SIGNALFD ScmpSyscall = SYS_SIGNALFD
SNR_TIMERFD_CREATE ScmpSyscall = SYS_TIMERFD_CREATE
SNR_EVENTFD ScmpSyscall = SYS_EVENTFD
SNR_FALLOCATE ScmpSyscall = SYS_FALLOCATE
SNR_TIMERFD_SETTIME ScmpSyscall = SYS_TIMERFD_SETTIME
SNR_TIMERFD_GETTIME ScmpSyscall = SYS_TIMERFD_GETTIME
SNR_ACCEPT4 ScmpSyscall = SYS_ACCEPT4
SNR_SIGNALFD4 ScmpSyscall = SYS_SIGNALFD4
SNR_EVENTFD2 ScmpSyscall = SYS_EVENTFD2
SNR_EPOLL_CREATE1 ScmpSyscall = SYS_EPOLL_CREATE1
SNR_DUP3 ScmpSyscall = SYS_DUP3
SNR_PIPE2 ScmpSyscall = SYS_PIPE2
SNR_INOTIFY_INIT1 ScmpSyscall = SYS_INOTIFY_INIT1
SNR_PREADV ScmpSyscall = SYS_PREADV
SNR_PWRITEV ScmpSyscall = SYS_PWRITEV
SNR_RT_TGSIGQUEUEINFO ScmpSyscall = SYS_RT_TGSIGQUEUEINFO
SNR_PERF_EVENT_OPEN ScmpSyscall = SYS_PERF_EVENT_OPEN
SNR_RECVMMSG ScmpSyscall = SYS_RECVMMSG
SNR_FANOTIFY_INIT ScmpSyscall = SYS_FANOTIFY_INIT
SNR_FANOTIFY_MARK ScmpSyscall = SYS_FANOTIFY_MARK
SNR_PRLIMIT64 ScmpSyscall = SYS_PRLIMIT64
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_SENDMMSG ScmpSyscall = SYS_SENDMMSG
SNR_SETNS ScmpSyscall = SYS_SETNS
SNR_GETCPU ScmpSyscall = SYS_GETCPU
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_KEXEC_FILE_LOAD ScmpSyscall = SYS_KEXEC_FILE_LOAD
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_URETPROBE ScmpSyscall = SYS_URETPROBE
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

@@ -0,0 +1,703 @@
// mksysnum_linux.pl /usr/include/asm/unistd_64.h
// Code generated by the command above; DO NOT EDIT.
package std
import . "syscall"
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 (
SYS_USERFAULTFD = 282
SYS_MEMBARRIER = 283
SYS_MLOCK2 = 284
SYS_COPY_FILE_RANGE = 285
SYS_PREADV2 = 286
SYS_PWRITEV2 = 287
SYS_PKEY_MPROTECT = 288
SYS_PKEY_ALLOC = 289
SYS_PKEY_FREE = 290
SYS_STATX = 291
SYS_IO_PGETEVENTS = 292
SYS_RSEQ = 293
SYS_KEXEC_FILE_LOAD = 294
SYS_PIDFD_SEND_SIGNAL = 424
SYS_IO_URING_SETUP = 425
SYS_IO_URING_ENTER = 426
SYS_IO_URING_REGISTER = 427
SYS_OPEN_TREE = 428
SYS_MOVE_MOUNT = 429
SYS_FSOPEN = 430
SYS_FSCONFIG = 431
SYS_FSMOUNT = 432
SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435
SYS_CLOSE_RANGE = 436
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
SYS_FACCESSAT2 = 439
SYS_PROCESS_MADVISE = 440
SYS_EPOLL_PWAIT2 = 441
SYS_MOUNT_SETATTR = 442
SYS_QUOTACTL_FD = 443
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
SYS_STATMOUNT = 457
SYS_LISTMOUNT = 458
SYS_LSM_GET_SELF_ATTR = 459
SYS_LSM_SET_SELF_ATTR = 460
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

@@ -0,0 +1,719 @@
// mksysnum_linux.pl /usr/include/riscv64-linux-gnu/asm/unistd.h
// Code generated by the command above; DO NOT EDIT.
package std
import . "syscall"
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,
"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,
"setxattrat": SNR_SETXATTRAT,
"getxattrat": SNR_GETXATTRAT,
"listxattrat": SNR_LISTXATTRAT,
"removexattrat": SNR_REMOVEXATTRAT,
}
const (
SYS_USERFAULTFD = 282
SYS_MEMBARRIER = 283
SYS_MLOCK2 = 284
SYS_COPY_FILE_RANGE = 285
SYS_PREADV2 = 286
SYS_PWRITEV2 = 287
SYS_PKEY_MPROTECT = 288
SYS_PKEY_ALLOC = 289
SYS_PKEY_FREE = 290
SYS_STATX = 291
SYS_IO_PGETEVENTS = 292
SYS_RSEQ = 293
SYS_KEXEC_FILE_LOAD = 294
SYS_PIDFD_SEND_SIGNAL = 424
SYS_IO_URING_SETUP = 425
SYS_IO_URING_ENTER = 426
SYS_IO_URING_REGISTER = 427
SYS_OPEN_TREE = 428
SYS_MOVE_MOUNT = 429
SYS_FSOPEN = 430
SYS_FSCONFIG = 431
SYS_FSMOUNT = 432
SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435
SYS_CLOSE_RANGE = 436
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
SYS_FACCESSAT2 = 439
SYS_PROCESS_MADVISE = 440
SYS_EPOLL_PWAIT2 = 441
SYS_MOUNT_SETATTR = 442
SYS_QUOTACTL_FD = 443
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
SYS_SET_MEMPOLICY_HOME_NODE = 450
SYS_CACHESTAT = 451
SYS_FCHMODAT2 = 452
SYS_MAP_SHADOW_STACK = 453
SYS_FUTEX_WAKE = 454
SYS_FUTEX_WAIT = 455
SYS_FUTEX_REQUEUE = 456
SYS_STATMOUNT = 457
SYS_LISTMOUNT = 458
SYS_LSM_GET_SELF_ATTR = 459
SYS_LSM_SET_SELF_ATTR = 460
SYS_LSM_LIST_MODULES = 461
SYS_MSEAL = 462
SYS_SETXATTRAT = 463
SYS_GETXATTRAT = 464
SYS_LISTXATTRAT = 465
SYS_REMOVEXATTRAT = 466
SYS_OPEN_TREE_ATTR = 467
SYS_FILE_GETATTR = 468
SYS_FILE_SETATTR = 469
)
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_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
SNR_SETXATTRAT ScmpSyscall = SYS_SETXATTRAT
SNR_GETXATTRAT ScmpSyscall = SYS_GETXATTRAT
SNR_LISTXATTRAT ScmpSyscall = SYS_LISTXATTRAT
SNR_REMOVEXATTRAT ScmpSyscall = SYS_REMOVEXATTRAT
SNR_OPEN_TREE_ATTR ScmpSyscall = SYS_OPEN_TREE_ATTR
SNR_FILE_GETATTR ScmpSyscall = SYS_FILE_GETATTR
SNR_FILE_SETATTR ScmpSyscall = SYS_FILE_SETATTR
)

View File

@@ -0,0 +1,21 @@
package std_test
import (
"testing"
"hakurei.app/container/std"
)
func TestSyscallResolveName(t *testing.T) {
t.Parallel()
for name, want := range std.Syscalls() {
t.Run(name, func(t *testing.T) {
t.Parallel()
if got, ok := std.SyscallResolveName(name); !ok || got != want {
t.Errorf("SyscallResolveName(%q) = %d, want %d", name, got, want)
}
})
}
}

View File

@@ -4,7 +4,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestCallError(t *testing.T) { func TestCallError(t *testing.T) {

View File

@@ -9,14 +9,11 @@ var (
ErrCheck = errors.New("one or more arguments did not match") ErrCheck = errors.New("one or more arguments did not match")
) )
// UniqueError is an error that only equivalates to another [UniqueError] with // UniqueError is an error that only equivalates to other [UniqueError] with the same magic value.
// the same magic value.
type UniqueError uintptr type UniqueError uintptr
func (e UniqueError) Error() string { func (e UniqueError) Error() string {
return "unique error " + return "unique error " + strconv.FormatUint(uint64(e), 10) + " injected by the test suite"
strconv.FormatUint(uint64(e), 10) +
" injected by the test suite"
} }
func (e UniqueError) Is(target error) bool { func (e UniqueError) Is(target error) bool {

View File

@@ -5,7 +5,7 @@ import (
"syscall" "syscall"
"testing" "testing"
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
func TestUniqueError(t *testing.T) { func TestUniqueError(t *testing.T) {

View File

@@ -4,12 +4,12 @@ import (
"testing" "testing"
_ "unsafe" // for go:linkname _ "unsafe" // for go:linkname
"hakurei.app/internal/stub" "hakurei.app/container/stub"
) )
// Made available here to check panic recovery behaviour. // Made available here to check panic recovery behaviour.
// //
//go:linkname handleExitNew hakurei.app/internal/stub.handleExitNew //go:linkname handleExitNew hakurei.app/container/stub.handleExitNew
func handleExitNew(t testing.TB) func handleExitNew(t testing.TB)
// overrideTFailNow overrides the Fail and FailNow method. // overrideTFailNow overrides the Fail and FailNow method.

View File

@@ -1,5 +1,5 @@
// Package stub provides function call level stubbing and validation for library // Package stub provides function call level stubbing and validation
// functions that are impossible to check otherwise. // for library functions that are impossible to check otherwise.
package stub package stub
import ( import (

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