Some checks failed
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Failing after 52s
Test / Sandbox (race detector) (push) Failing after 1m7s
Test / Hpkg (push) Successful in 1m21s
Test / Hakurei (race detector) (push) Failing after 1m27s
Test / Hakurei (push) Failing after 2m19s
Test / Flake checks (push) Has been skipped
Most tests already had no global state, however parallel was never enabled. This change enables it for all applicable tests. Signed-off-by: Ophestra <cat@gensokyo.uk>
428 lines
25 KiB
Go
428 lines
25 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"maps"
|
|
"os"
|
|
"reflect"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"hakurei.app/container"
|
|
"hakurei.app/container/bits"
|
|
"hakurei.app/container/check"
|
|
"hakurei.app/container/fhs"
|
|
"hakurei.app/container/seccomp"
|
|
"hakurei.app/container/stub"
|
|
"hakurei.app/hst"
|
|
"hakurei.app/system/dbus"
|
|
)
|
|
|
|
func TestSpParamsOp(t *testing.T) {
|
|
t.Parallel()
|
|
config := hst.Template()
|
|
|
|
checkOpBehaviour(t, []opBehaviourTestCase{
|
|
{"invalid program path", func(isShim, _ bool) outcomeOp {
|
|
if !isShim {
|
|
return new(spParamsOp)
|
|
}
|
|
return &spParamsOp{Term: "xterm", TermSet: true}
|
|
}, func() *hst.Config {
|
|
c := hst.Template()
|
|
c.Container.Path = nil
|
|
return c
|
|
}, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{"TERM"}, "xterm", nil),
|
|
}, newI().
|
|
Ensure(m(container.Nonexistent+"/tmp/hakurei.0"), 0711), nil, nil, nil, []stub.Call{
|
|
// this op configures the container state and does not make calls during toContainer
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "finalise",
|
|
Err: os.ErrInvalid,
|
|
Msg: "invalid program path",
|
|
}},
|
|
|
|
{"success defaultargs secure", func(isShim, _ bool) outcomeOp {
|
|
if !isShim {
|
|
return new(spParamsOp)
|
|
}
|
|
return &spParamsOp{Term: "xterm", TermSet: true}
|
|
}, func() *hst.Config {
|
|
c := hst.Template()
|
|
c.Container.Args = nil
|
|
c.Container.Multiarch = false
|
|
c.Container.SeccompCompat = false
|
|
c.Container.Devel = false
|
|
c.Container.Userns = false
|
|
c.Container.Tty = false
|
|
c.Container.Device = false
|
|
return c
|
|
}, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{"TERM"}, "xterm", nil),
|
|
}, newI().
|
|
Ensure(m(container.Nonexistent+"/tmp/hakurei.0"), 0711), nil, nil, nil, []stub.Call{
|
|
// this op configures the container state and does not make calls during toContainer
|
|
}, &container.Params{
|
|
Hostname: config.Container.Hostname,
|
|
HostNet: config.Container.HostNet,
|
|
HostAbstract: config.Container.HostAbstract,
|
|
Path: config.Container.Path,
|
|
Args: []string{config.Container.Path.String()},
|
|
SeccompPresets: bits.PresetExt | bits.PresetDenyDevel | bits.PresetDenyNS | bits.PresetDenyTTY,
|
|
Uid: 1000,
|
|
Gid: 100,
|
|
Ops: new(container.Ops).
|
|
Root(m("/var/lib/hakurei/base/org.debian"), bits.BindWritable).
|
|
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
|
DevWritable(fhs.AbsDev, true).
|
|
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
|
|
}, func(t *testing.T, state *outcomeStateParams) {
|
|
wantEnv := map[string]string{
|
|
"TERM": "xterm",
|
|
}
|
|
maps.Copy(wantEnv, config.Container.Env)
|
|
if !maps.Equal(state.env, wantEnv) {
|
|
t.Errorf("toContainer: env = %#v, want %#v", state.env, wantEnv)
|
|
}
|
|
|
|
const wantAutoEtcPrefix = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
if state.as.AutoEtcPrefix != wantAutoEtcPrefix {
|
|
t.Errorf("toContainer: as.AutoEtcPrefix = %q, want %q", state.as.AutoEtcPrefix, wantAutoEtcPrefix)
|
|
}
|
|
|
|
wantFilesystems := config.Container.Filesystem[1:]
|
|
if !reflect.DeepEqual(state.filesystem, wantFilesystems) {
|
|
t.Errorf("toContainer: filesystem = %#v, want %#v", state.filesystem, wantFilesystems)
|
|
}
|
|
}, nil},
|
|
|
|
{"success", func(isShim, _ bool) outcomeOp {
|
|
if !isShim {
|
|
return new(spParamsOp)
|
|
}
|
|
return &spParamsOp{Term: "xterm", TermSet: true}
|
|
}, hst.Template, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{"TERM"}, "xterm", nil),
|
|
}, newI().
|
|
Ensure(m(container.Nonexistent+"/tmp/hakurei.0"), 0711), nil, nil, nil, []stub.Call{
|
|
// this op configures the container state and does not make calls during toContainer
|
|
}, &container.Params{
|
|
Hostname: config.Container.Hostname,
|
|
RetainSession: config.Container.Tty,
|
|
HostNet: config.Container.HostNet,
|
|
HostAbstract: config.Container.HostAbstract,
|
|
Path: config.Container.Path,
|
|
Args: config.Container.Args,
|
|
SeccompFlags: seccomp.AllowMultiarch,
|
|
Uid: 1000,
|
|
Gid: 100,
|
|
Ops: new(container.Ops).
|
|
Root(m("/var/lib/hakurei/base/org.debian"), bits.BindWritable).
|
|
Proc(fhs.AbsProc).Tmpfs(hst.AbsPrivateTmp, 1<<12, 0755).
|
|
Bind(fhs.AbsDev, fhs.AbsDev, bits.BindWritable|bits.BindDevice).
|
|
Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777),
|
|
}, func(t *testing.T, state *outcomeStateParams) {
|
|
wantEnv := map[string]string{
|
|
"TERM": "xterm",
|
|
}
|
|
maps.Copy(wantEnv, config.Container.Env)
|
|
if !maps.Equal(state.env, wantEnv) {
|
|
t.Errorf("toContainer: env = %#v, want %#v", state.env, wantEnv)
|
|
}
|
|
|
|
if state.as.AutoEtcPrefix != wantAutoEtcPrefix {
|
|
t.Errorf("toContainer: as.AutoEtcPrefix = %q, want %q", state.as.AutoEtcPrefix, wantAutoEtcPrefix)
|
|
}
|
|
|
|
wantFilesystems := config.Container.Filesystem[1:]
|
|
if !reflect.DeepEqual(state.filesystem, wantFilesystems) {
|
|
t.Errorf("toContainer: filesystem = %#v, want %#v", state.filesystem, wantFilesystems)
|
|
}
|
|
}, nil},
|
|
})
|
|
}
|
|
|
|
func TestSpFilesystemOp(t *testing.T) {
|
|
const nePrefix = container.Nonexistent + "/eval"
|
|
var stubDebianRoot = stubDir("bin", "dev", "etc", "home", "lib64", "lost+found",
|
|
"mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var")
|
|
config := hst.Template()
|
|
|
|
newConfigSmall := func() *hst.Config {
|
|
c := hst.Template()
|
|
c.Container.Filesystem = []hst.FilesystemConfigJSON{
|
|
{FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: fhs.AbsEtc, Special: true}},
|
|
{FilesystemConfig: &hst.FSOverlay{Target: m("/nix/store"), Lower: []*check.Absolute{
|
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/.ro-store"),
|
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/org.chromium.Chromium"),
|
|
}}},
|
|
{FilesystemConfig: &hst.FSEphemeral{Target: hst.AbsPrivateTmp}},
|
|
}
|
|
c.Container.Device = false
|
|
return c
|
|
}
|
|
configSmall := newConfigSmall()
|
|
|
|
checkOpBehaviour(t, []opBehaviourTestCase{
|
|
{"readdir", func(bool, bool) outcomeOp {
|
|
return new(spFilesystemOp)
|
|
}, hst.Template, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/dbus"}, nePrefix+"/run/dbus", nil),
|
|
call("readdir", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian"}, []os.DirEntry{}, stub.UniqueError(2)),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "access autoroot source",
|
|
Err: stub.UniqueError(2),
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"invalid dbus address", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, func() *hst.Config {
|
|
c := newConfigSmall()
|
|
c.Container.Filesystem = append(c.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: invalidFSHost(false)})
|
|
return c
|
|
}, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid", nil),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "parse dbus address",
|
|
Err: &dbus.BadAddressError{
|
|
Type: dbus.ErrNoColon,
|
|
EntryVal: []byte("invalid"),
|
|
PairPos: -1,
|
|
},
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"invalid fs early", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, func() *hst.Config {
|
|
c := newConfigSmall()
|
|
c.Container.Filesystem = append(c.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: invalidFSHost(false)})
|
|
return c
|
|
}, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, nePrefix+"/etc/dbus", nil), // to match hidePaths
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "finalise",
|
|
Err: os.ErrInvalid,
|
|
Msg: "invalid filesystem at index 3",
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"evalSymlinks early", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, newConfigSmall, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, "", stub.UniqueError(0)),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "evaluate path hiding target",
|
|
Err: stub.UniqueError(0),
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"host nil abs", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, func() *hst.Config {
|
|
c := newConfigSmall()
|
|
c.Container.Filesystem = append(c.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: invalidFSHost(true)})
|
|
return c
|
|
}, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, nePrefix+"/etc/dbus", nil), // to match hidePaths
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, nePrefix+"/etc", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/.ro-store"}, nePrefix+"/var/lib/hakurei/base/org.nixos/.ro-store", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium"}, "var/lib/hakurei/base/org.nixos/org.chromium.Chromium", nil),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "finalise",
|
|
Err: os.ErrInvalid,
|
|
Msg: "impossible path hiding state reached",
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"evalSymlinks late", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, newConfigSmall, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, nePrefix+"/etc/dbus", nil), // to match hidePaths
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, nePrefix+"/etc", stub.UniqueError(1)),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "evaluate path hiding source",
|
|
Err: stub.UniqueError(1),
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"invalid contains", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, newConfigSmall, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, nePrefix+"/etc/dbus", nil), // to match hidePaths
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, nePrefix+"/etc", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/.ro-store"}, nePrefix+"/var/lib/hakurei/base/org.nixos/.ro-store", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium"}, "var/lib/hakurei/base/org.nixos/org.chromium.Chromium", nil),
|
|
call("verbosef", stub.ExpectArgs{"hiding path %q from %q", []any{"/proc/nonexistent/eval/etc/dbus", "/etc/"}}, nil, nil),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "determine path hiding outcome",
|
|
Err: errors.New("Rel: can't make /proc/nonexistent/eval/xdg_runtime_dir relative to var/lib/hakurei/base/org.nixos/org.chromium.Chromium"),
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"invalid hide", func(bool, bool) outcomeOp { return new(spFilesystemOp) }, newConfigSmall, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, "xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, "tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "nscd", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, "nonexistent/dbus", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, "nonexistent", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/.ro-store"}, ".ro-store", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium"}, "org.chromium.Chromium", nil),
|
|
call("verbosef", stub.ExpectArgs{"hiding path %q from %q", []any{"nonexistent/dbus", "/etc/"}}, nil, nil),
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "finalise",
|
|
Err: os.ErrInvalid,
|
|
Msg: `invalid path hiding candidate "nonexistent/dbus"`,
|
|
}, nil, nil, nil, nil, nil},
|
|
|
|
{"invalid fs", func(isShim, clearUnexported bool) outcomeOp {
|
|
if !isShim {
|
|
return new(spFilesystemOp)
|
|
}
|
|
return &spFilesystemOp{HidePaths: []*check.Absolute{m("/proc/nonexistent/eval/etc/dbus")}}
|
|
}, newConfigSmall, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, nePrefix+"/etc/dbus", nil), // to match hidePaths
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, nePrefix+"/etc", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/.ro-store"}, nePrefix+"/var/lib/hakurei/base/org.nixos/.ro-store", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium"}, nePrefix+"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium", nil),
|
|
call("verbosef", stub.ExpectArgs{"hiding path %q from %q", []any{"/proc/nonexistent/eval/etc/dbus", "/etc/"}}, nil, nil),
|
|
}, newI(), nil, nil, func(state *outcomeStateParams) {
|
|
state.filesystem = configSmall.Container.Filesystem
|
|
state.params.Ops = new(container.Ops)
|
|
state.as = hst.ApplyState{AutoEtcPrefix: wantAutoEtcPrefix, Ops: opsAdapter{state.params.Ops}}
|
|
state.filesystem = append(state.filesystem, hst.FilesystemConfigJSON{})
|
|
}, []stub.Call{
|
|
// this op configures the container state and does not make calls during toContainer
|
|
}, nil, nil, &hst.AppError{
|
|
Step: "finalise",
|
|
Err: os.ErrInvalid,
|
|
Msg: "invalid filesystem at index 3",
|
|
}},
|
|
|
|
{"success noroot nodev envdbus strangedbus dbusnotabs hide", func(isShim, clearUnexported bool) outcomeOp {
|
|
if !isShim {
|
|
return new(spFilesystemOp)
|
|
}
|
|
return &spFilesystemOp{HidePaths: []*check.Absolute{m("/proc/nonexistent/eval/etc/dbus")}}
|
|
}, newConfigSmall, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, "invalid:meow=0;unix:path=/system_bus_socket;unix:path=system_bus_socket", nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is in an unusual location", []any{"/system_bus_socket"}}, nil, nil),
|
|
call("verbosef", stub.ExpectArgs{"dbus socket %q is not absolute", []any{"system_bus_socket"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/"}, nePrefix+"/etc/dbus", nil), // to match hidePaths
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, nePrefix+"/etc", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/.ro-store"}, nePrefix+"/var/lib/hakurei/base/org.nixos/.ro-store", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium"}, nePrefix+"/var/lib/hakurei/base/org.nixos/org.chromium.Chromium", nil),
|
|
call("verbosef", stub.ExpectArgs{"hiding path %q from %q", []any{"/proc/nonexistent/eval/etc/dbus", "/etc/"}}, nil, nil),
|
|
}, newI(), nil, nil, func(state *outcomeStateParams) {
|
|
state.filesystem = configSmall.Container.Filesystem
|
|
state.params.Ops = new(container.Ops)
|
|
state.as = hst.ApplyState{AutoEtcPrefix: wantAutoEtcPrefix, Ops: opsAdapter{state.params.Ops}}
|
|
}, []stub.Call{
|
|
// this op configures the container state and does not make calls during toContainer
|
|
}, &container.Params{
|
|
Ops: new(container.Ops).
|
|
Etc(fhs.AbsEtc, wantAutoEtcPrefix).
|
|
OverlayReadonly(
|
|
check.MustAbs("/nix/store"),
|
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/.ro-store"),
|
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/org.chromium.Chromium")).
|
|
Readonly(hst.AbsPrivateTmp, 0755).
|
|
Tmpfs(m("/proc/nonexistent/eval/etc/dbus"), 1<<13, 0755).
|
|
Remount(fhs.AbsDev, syscall.MS_RDONLY),
|
|
}, nil, nil},
|
|
|
|
{"success", func(bool, bool) outcomeOp {
|
|
return new(spFilesystemOp)
|
|
}, hst.Template, nil, []stub.Call{
|
|
call("lookupEnv", stub.ExpectArgs{dbus.SystemBusAddress}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/xdg_runtime_dir"}, nePrefix+"/xdg_runtime_dir", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{container.Nonexistent + "/tmp/hakurei.0"}, nePrefix+"/tmp/hakurei.0", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/nscd"}, "", &os.PathError{Op: "lstat", Path: "/var/run/nscd", Err: os.ErrNotExist}),
|
|
call("verbosef", stub.ExpectArgs{"path %q does not yet exist", []any{"/var/run/nscd"}}, nil, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/run/dbus"}, nePrefix+"/run/dbus", nil),
|
|
call("readdir", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian"}, stubDebianRoot, nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/etc/"}, nePrefix+"/etc", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/upper"}, nePrefix+"/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/upper", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/work"}, nePrefix+"/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/work", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.nixos/ro-store"}, nePrefix+"/var/lib/hakurei/base/org.nixos/ro-store", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/u0/org.chromium.Chromium"}, nePrefix+"/var/lib/hakurei/u0/org.chromium.Chromium", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/dev/dri"}, nePrefix+"/dev/dri", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/bin"}, nePrefix+"/var/lib/hakurei/base/org.debian/bin", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/home"}, nePrefix+"/var/lib/hakurei/base/org.debian/home", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/lib64"}, nePrefix+"/var/lib/hakurei/base/org.debian/lib64", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/lost+found"}, nePrefix+"/var/lib/hakurei/base/org.debian/lost+found", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/nix"}, nePrefix+"/var/lib/hakurei/base/org.debian/nix", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/root"}, nePrefix+"/var/lib/hakurei/base/org.debian/root", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/run"}, nePrefix+"/var/lib/hakurei/base/org.debian/run", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/srv"}, nePrefix+"/var/lib/hakurei/base/org.debian/srv", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/sys"}, nePrefix+"/var/lib/hakurei/base/org.debian/sys", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/usr"}, nePrefix+"/var/lib/hakurei/base/org.debian/usr", nil),
|
|
call("evalSymlinks", stub.ExpectArgs{"/var/lib/hakurei/base/org.debian/var"}, nePrefix+"/var/lib/hakurei/base/org.debian/var", nil),
|
|
}, newI(), nil, nil, func(state *outcomeStateParams) {
|
|
state.filesystem = config.Container.Filesystem[1:]
|
|
state.params.Ops = new(container.Ops)
|
|
state.as = hst.ApplyState{AutoEtcPrefix: wantAutoEtcPrefix, Ops: opsAdapter{state.params.Ops}}
|
|
}, []stub.Call{
|
|
// this op configures the container state and does not make calls during toContainer
|
|
}, &container.Params{
|
|
Ops: new(container.Ops).
|
|
Etc(fhs.AbsEtc, wantAutoEtcPrefix).
|
|
Tmpfs(fhs.AbsTmp, 0, 0755).
|
|
Overlay(
|
|
check.MustAbs("/nix/store"),
|
|
fhs.AbsVarLib.Append("hakurei/nix/u0/org.chromium.Chromium/rw-store/upper"),
|
|
fhs.AbsVarLib.Append("hakurei/nix/u0/org.chromium.Chromium/rw-store/work"),
|
|
fhs.AbsVarLib.Append("hakurei/base/org.nixos/ro-store")).
|
|
Link(fhs.AbsRun.Append("current-system"), "/run/current-system", true).
|
|
Link(fhs.AbsRun.Append("opengl-driver"), "/run/opengl-driver", true).
|
|
Bind(
|
|
fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
|
|
check.MustAbs("/data/data/org.chromium.Chromium"),
|
|
bits.BindWritable|bits.BindEnsure).
|
|
Bind(fhs.AbsDev.Append("dri"), fhs.AbsDev.Append("dri"), bits.BindDevice|bits.BindWritable|bits.BindOptional),
|
|
}, nil, nil},
|
|
})
|
|
}
|
|
|
|
// invalidFSHost implements the Host method of [hst.FilesystemConfig] with an invalid response.
|
|
type invalidFSHost bool
|
|
|
|
func (f invalidFSHost) Valid() bool { return bool(f) }
|
|
func (invalidFSHost) Path() *check.Absolute { panic("unreachable") }
|
|
func (invalidFSHost) Host() []*check.Absolute { return []*check.Absolute{nil} }
|
|
func (invalidFSHost) Apply(*hst.ApplyState) { panic("unreachable") }
|
|
func (invalidFSHost) String() string { panic("unreachable") }
|