aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/app/shim_linux.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-28 01:07:51 +0900
committerOphestra <cat@gensokyo.uk>2025-08-28 01:07:51 +0900
commitb14690aa77b3d5f86c4d1b1965675d6d82789e32 (patch)
tree5765f705fd69dae7a65a0666451ac71a729a6aa8 /internal/app/shim_linux.go
parentd0b6852cd7db2bb1214c3267719d3ac108c0a53e (diff)
internal/app: remove seal interface
This further cleans up the package for the restructure. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/app/shim_linux.go')
-rw-r--r--internal/app/shim_linux.go183
1 files changed, 0 insertions, 183 deletions
diff --git a/internal/app/shim_linux.go b/internal/app/shim_linux.go
deleted file mode 100644
index 33ede520..00000000
--- a/internal/app/shim_linux.go
+++ /dev/null
@@ -1,183 +0,0 @@
-package app
-
-import (
- "context"
- "errors"
- "io"
- "log"
- "os"
- "os/exec"
- "os/signal"
- "runtime"
- "sync/atomic"
- "syscall"
- "time"
-
- "hakurei.app/container"
- "hakurei.app/container/seccomp"
- "hakurei.app/internal"
- "hakurei.app/internal/hlog"
-)
-
-//#include "shim-signal.h"
-import "C"
-
-const shimEnv = "HAKUREI_SHIM"
-
-type shimParams struct {
- // monitor pid, checked against ppid in signal handler
- Monitor int
-
- // duration to wait for after interrupting a container's initial process before the container is killed;
- // zero value defaults to [DefaultShimWaitDelay], values exceeding [MaxShimWaitDelay] becomes [MaxShimWaitDelay]
- WaitDelay time.Duration
-
- // finalised container params
- Container *container.Params
-
- // verbosity pass through
- Verbose bool
-}
-
-const (
- // ShimExitRequest is returned when the monitor process requests shim exit.
- ShimExitRequest = 254
- // ShimExitOrphan is returned when the shim is orphaned before monitor delivers a signal.
- ShimExitOrphan = 3
-
- DefaultShimWaitDelay = 5 * time.Second
- MaxShimWaitDelay = 30 * time.Second
-)
-
-// ShimMain is the main function of the shim process and runs as the unconstrained target user.
-func ShimMain() {
- hlog.Prepare("shim")
-
- if err := container.SetDumpable(container.SUID_DUMP_DISABLE); err != nil {
- log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
- }
-
- var (
- params shimParams
- closeSetup func() error
- )
- if f, err := container.Receive(shimEnv, &params, nil); err != nil {
- if errors.Is(err, syscall.EBADF) {
- log.Fatal("invalid config descriptor")
- }
- if errors.Is(err, container.ErrNotSet) {
- log.Fatal("HAKUREI_SHIM not set")
- }
-
- log.Fatalf("cannot receive shim setup params: %v", err)
- } else {
- internal.InstallOutput(params.Verbose)
- closeSetup = f
- }
-
- var signalPipe io.ReadCloser
- // the Go runtime does not expose siginfo_t so SIGCONT is handled in C to check si_pid
- if r, w, err := os.Pipe(); err != nil {
- log.Fatalf("cannot pipe: %v", err)
- } else if _, err = C.hakurei_shim_setup_cont_signal(C.pid_t(params.Monitor), C.int(w.Fd())); err != nil {
- log.Fatalf("cannot install SIGCONT handler: %v", err)
- } else {
- defer runtime.KeepAlive(w)
- signalPipe = r
- }
-
- // pdeath_signal delivery is checked as if the dying process called kill(2), see kernel/exit.c
- if _, _, errno := syscall.Syscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGCONT), 0); errno != 0 {
- log.Fatalf("cannot set parent-death signal: %v", errno)
- }
-
- // signal handler outcome
- var cancelContainer atomic.Pointer[context.CancelFunc]
- go func() {
- buf := make([]byte, 1)
- for {
- if _, err := signalPipe.Read(buf); err != nil {
- log.Fatalf("cannot read from signal pipe: %v", err)
- }
-
- switch buf[0] {
- case 0: // got SIGCONT from monitor: shim exit requested
- if fp := cancelContainer.Load(); params.Container.ForwardCancel && fp != nil && *fp != nil {
- (*fp)()
- // shim now bound by ShimWaitDelay, implemented below
- continue
- }
-
- // setup has not completed, terminate immediately
- hlog.Resume()
- os.Exit(ShimExitRequest)
- return
-
- case 1: // got SIGCONT after adoption: monitor died before delivering signal
- hlog.BeforeExit()
- os.Exit(ShimExitOrphan)
- return
-
- case 2: // unreachable
- log.Println("sa_sigaction got invalid siginfo")
-
- case 3: // got SIGCONT from unexpected process: hopefully the terminal driver
- log.Println("got SIGCONT from unexpected process")
-
- default: // unreachable
- log.Fatalf("got invalid message %d from signal handler", buf[0])
- }
- }
- }()
-
- if params.Container == nil || params.Container.Ops == nil {
- log.Fatal("invalid container params")
- }
-
- // close setup socket
- if err := closeSetup(); err != nil {
- log.Printf("cannot close setup pipe: %v", err)
- // not fatal
- }
-
- ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
- cancelContainer.Store(&stop)
- z := container.New(ctx)
- z.Params = *params.Container
- z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
-
- z.WaitDelay = params.WaitDelay
- if z.WaitDelay == 0 {
- z.WaitDelay = DefaultShimWaitDelay
- }
- if z.WaitDelay > MaxShimWaitDelay {
- z.WaitDelay = MaxShimWaitDelay
- }
-
- if err := z.Start(); err != nil {
- hlog.PrintBaseError(err, "cannot start container:")
- os.Exit(1)
- }
- if err := z.Serve(); err != nil {
- hlog.PrintBaseError(err, "cannot configure container:")
- }
-
- if err := seccomp.Load(
- seccomp.Preset(seccomp.PresetStrict, seccomp.AllowMultiarch),
- seccomp.AllowMultiarch,
- ); err != nil {
- log.Fatalf("cannot load syscall filter: %v", err)
- }
-
- if err := z.Wait(); err != nil {
- var exitError *exec.ExitError
- if !errors.As(err, &exitError) {
- if errors.Is(err, context.Canceled) {
- os.Exit(2)
- }
- log.Printf("wait: %v", err)
- os.Exit(127)
- }
- os.Exit(exitError.ExitCode())
- }
-}