diff options
Diffstat (limited to 'internal/outcome/shim_test.go')
| -rw-r--r-- | internal/outcome/shim_test.go | 344 |
1 files changed, 340 insertions, 4 deletions
diff --git a/internal/outcome/shim_test.go b/internal/outcome/shim_test.go index 046c22b6..9626b6cb 100644 --- a/internal/outcome/shim_test.go +++ b/internal/outcome/shim_test.go @@ -106,8 +106,8 @@ func TestShimEntrypoint(t *testing.T) { Remount(fhs.AbsRoot, syscall.MS_RDONLY), } - templateState := outcomeState{ - Shim: &shimParams{PrivPID: 0xbad, WaitDelay: 0xf, Verbose: true, Ops: []outcomeOp{ + newShimParams := func() *shimParams { + return &shimParams{PrivPID: 0xbad, WaitDelay: 0xf, Verbose: true, Ops: []outcomeOp{ &spParamsOp{"xterm-256color", true}, &spRuntimeOp{sessionTypeWayland}, spTmpdirOp{}, @@ -116,8 +116,11 @@ func TestShimEntrypoint(t *testing.T) { &spPulseOp{(*[pulseCookieSizeMax]byte)(bytes.Repeat([]byte{0}, pulseCookieSizeMax)), pulseCookieSizeMax}, &spDBusOp{true}, &spFilesystemOp{}, - }}, + }} + } + templateState := outcomeState{ + Shim: newShimParams(), ID: &checkExpectInstanceId, Identity: hst.IdentityMax, UserID: 10, @@ -128,6 +131,333 @@ func TestShimEntrypoint(t *testing.T) { } checkSimple(t, "shimEntrypoint", []simpleTestCase{ + {"dumpable", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, new(log.Logger), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, stub.UniqueError(11)), + call("fatalf", stub.ExpectArgs{"cannot set SUID_DUMP_DISABLE: %v", []any{stub.UniqueError(11)}}, nil, nil), + }}, nil}, + + {"receive fd", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{}, nil}, nil, syscall.EBADF), + call("fatal", stub.ExpectArgs{[]any{"invalid config descriptor"}}, nil, nil), + }}, nil}, + + {"receive env", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{}, nil}, nil, container.ErrReceiveEnv), + call("fatal", stub.ExpectArgs{[]any{"HAKUREI_SHIM not set"}}, nil, nil), + }}, nil}, + + {"receive strange", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{}, nil}, nil, stub.UniqueError(10)), + call("fatalf", stub.ExpectArgs{"cannot receive shim setup params: %v", []any{stub.UniqueError(10)}}, nil, nil), + }}, nil}, + + {"invalid state", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", func() outcomeState { + state := templateState + state.Shim = newShimParams() + state.Shim.PrivPID = 0 + return state + }(), nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("fatal", stub.ExpectArgs{[]any{"impossible outcome state reached\n"}}, nil, nil), + }}, nil}, + + {"sigaction pipe", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, &os.SyscallError{Syscall: "pipe2", Err: stub.UniqueError(9)}), + call("fatal", stub.ExpectArgs{[]any{"pipe2: unique error 9 injected by the test suite"}}, nil, nil), + }}, nil}, + + {"sigaction cgo", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, syscall.ENOTRECOVERABLE), + call("fatalf", stub.ExpectArgs{"cannot install SIGCONT handler: %v", []any{syscall.ENOTRECOVERABLE}}, nil, nil), + }}, nil}, + + {"sigaction strange", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, stub.UniqueError(8)), + call("fatalf", stub.ExpectArgs{"cannot set up exit request: %v", []any{stub.UniqueError(8)}}, nil, nil), + }}, nil}, + + {"prctl", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, stub.UniqueError(7)), + call("fatalf", stub.ExpectArgs{"cannot set parent-death signal: %v", []any{stub.UniqueError(7)}}, nil, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }}, nil}, + + {"toContainer", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", func() outcomeState { + state := templateState + state.Shim = newShimParams() + state.Shim.Ops = []outcomeOp{errorOp(6)} + return state + }(), nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("fatal", stub.ExpectArgs{[]any{"cannot create container state: unique error 6 injected by the test suite\n"}}, nil, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }}, nil}, + + {"bad ops", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", func() outcomeState { + state := templateState + state.Shim = newShimParams() + state.Shim.Ops = nil + return state + }(), nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("fatal", stub.ExpectArgs{[]any{"invalid container state"}}, nil, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }}, nil}, + + {"start", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(5)), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("verbose", stub.ExpectArgs{[]any{"cannot start container: unique error 5 injected by the test suite\n"}}, nil, nil), + call("exit", stub.ExpectArgs{hst.ExitFailure}, stub.PanicExit, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine + }}}}, nil}, + + {"start logger signalread", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(5)), + call("getLogger", stub.ExpectArgs{}, log.Default(), nil), + call("exit", stub.ExpectArgs{hst.ExitFailure}, stub.PanicExit, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, []byte{}, stub.UniqueError(4)), + call("fatalf", stub.ExpectArgs{"cannot read from signal pipe: %v", []any{stub.UniqueError(4)}}, nil, nil), + }}}}, nil}, + + {"serve", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), + call("containerServe", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(3)), + call("fatal", stub.ExpectArgs{[]any{"cannot configure container: unique error 3 injected by the test suite\n"}}, nil, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine + }}}}, nil}, + + {"seccomp", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), + call("containerServe", stub.ExpectArgs{templateParams}, nil, nil), + call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, stub.UniqueError(2)), + call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(2)}}, nil, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine + }}}}, nil}, + + {"exited closesetup earlyrequested", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, stub.UniqueError(1)), + call("verbosef", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(1)}}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, 0, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), + call("containerServe", stub.ExpectArgs{templateParams}, nil, nil), + call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil), + call("containerWait", stub.ExpectArgs{templateParams}, nil, makeExitError(1<<8)), + call("exit", stub.ExpectArgs{1}, stub.PanicExit, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, []byte{shimMsgExitRequested}, nil), + call("exit", stub.ExpectArgs{hst.ExitRequest}, stub.PanicExit, unblockNotifyContext), + }}}}, nil}, + + {"exited requested", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, 0, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), + call("containerServe", stub.ExpectArgs{templateParams}, nil, nil), + call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil), + call("containerWait", stub.ExpectArgs{templateParams}, nil, makeExitError(1<<8)), + call("exit", stub.ExpectArgs{1}, stub.PanicExit, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, []byte{shimMsgExitRequested}, unblockNotifyContext), + call("notifyContextStop", stub.ExpectArgs{}, nil, nil), + call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine + }}}}, nil}, + + {"canceled orphaned", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), + call("containerServe", stub.ExpectArgs{templateParams}, nil, nil), + call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil), + call("containerWait", stub.ExpectArgs{templateParams}, nil, context.Canceled), + call("exit", stub.ExpectArgs{hst.ExitCancel}, stub.PanicExit, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, []byte{shimMsgOrphaned}, nil), + call("exit", stub.ExpectArgs{hst.ExitOrphan}, stub.PanicExit, nil), + }}}}, nil}, + + {"strangewait invalidmsg", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ + call("getMsg", stub.ExpectArgs{}, nil, nil), + call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), + call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil), + call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil), + call("swapVerbose", stub.ExpectArgs{true}, false, nil), + call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil), + call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil), + call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), + call("New", stub.ExpectArgs{}, nil, nil), + call("closeReceive", stub.ExpectArgs{}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), + call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), + call("containerServe", stub.ExpectArgs{templateParams}, nil, nil), + call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil), + call("containerWait", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(0)), + call("verbosef", stub.ExpectArgs{"cannot wait: %v", []any{stub.UniqueError(0)}}, nil, nil), + call("exit", stub.ExpectArgs{127}, stub.PanicExit, nil), + + // deferred + call("wKeepAlive", stub.ExpectArgs{}, nil, nil), + }, Tracks: []stub.Expect{{Calls: []stub.Call{ + call("rcRead", stub.ExpectArgs{}, []byte{0xff}, nil), + call("fatalf", stub.ExpectArgs{"got invalid message %d from signal handler", []any{byte(0xff)}}, nil, nil), + }}}}, nil}, + {"success", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{ call("getMsg", stub.ExpectArgs{}, nil, nil), call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil), @@ -139,7 +469,7 @@ func TestShimEntrypoint(t *testing.T) { call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil), call("New", stub.ExpectArgs{}, nil, nil), call("closeReceive", stub.ExpectArgs{}, nil, nil), - call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, nil, nil), + call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil), call("containerStart", stub.ExpectArgs{templateParams}, nil, nil), call("containerServe", stub.ExpectArgs{templateParams}, nil, nil), call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil), @@ -156,3 +486,9 @@ func TestShimEntrypoint(t *testing.T) { }}}}, nil}, }) } + +// errorOp implements a noop outcomeOp that unconditionally returns [stub.UniqueError]. +type errorOp stub.UniqueError + +func (e errorOp) toSystem(*outcomeStateSys) error { return stub.UniqueError(e) } +func (e errorOp) toContainer(*outcomeStateParams) error { return stub.UniqueError(e) } |
