diff --git a/container/autoetc.go b/container/autoetc.go index d73d275..3be4ec3 100644 --- a/container/autoetc.go +++ b/container/autoetc.go @@ -31,10 +31,10 @@ func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error { rel := e.hostRel() + "/" if err := k.mkdirAll(target, 0755); err != nil { - return wrapErrSelf(err) + return err } if d, err := k.readdir(toSysroot(e.hostPath().String())); err != nil { - return wrapErrSelf(err) + return err } else { for _, ent := range d { n := ent.Name() @@ -43,12 +43,12 @@ func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error { case "mtab": if err = k.symlink(FHSProc+"mounts", target+n); err != nil { - return wrapErrSelf(err) + return err } default: if err = k.symlink(rel+n, target+n); err != nil { - return wrapErrSelf(err) + return err } } } diff --git a/container/autoetc_test.go b/container/autoetc_test.go index 32513bf..a892b59 100644 --- a/container/autoetc_test.go +++ b/container/autoetc_test.go @@ -19,14 +19,14 @@ func TestAutoEtcOp(t *testing.T) { Prefix: "81ceabb30d37bbdb3868004629cb84e9", }, nil, nil, []kexpect{ {"mkdirAll", expectArgs{"/sysroot/etc/", os.FileMode(0755)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"readdir", new(Params), &AutoEtcOp{ Prefix: "81ceabb30d37bbdb3868004629cb84e9", }, nil, nil, []kexpect{ {"mkdirAll", expectArgs{"/sysroot/etc/", os.FileMode(0755)}, nil, nil}, {"readdir", expectArgs{"/sysroot/etc/.host/81ceabb30d37bbdb3868004629cb84e9"}, stubDir(), errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink", new(Params), &AutoEtcOp{ Prefix: "81ceabb30d37bbdb3868004629cb84e9", @@ -42,7 +42,7 @@ func TestAutoEtcOp(t *testing.T) { "ssh", "ssl", "static", "subgid", "subuid", "sudoers", "sway", "sysctl.d", "systemd", "terminfo", "tmpfiles.d", "udev", "vconsole.conf", "X11", "xdg", "zoneinfo"), nil}, {"symlink", expectArgs{".host/81ceabb30d37bbdb3868004629cb84e9/alsa", "/sysroot/etc/alsa"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink mtab", new(Params), &AutoEtcOp{ Prefix: "81ceabb30d37bbdb3868004629cb84e9", @@ -84,7 +84,7 @@ func TestAutoEtcOp(t *testing.T) { {"symlink", expectArgs{".host/81ceabb30d37bbdb3868004629cb84e9/modprobe.d", "/sysroot/etc/modprobe.d"}, nil, nil}, {"symlink", expectArgs{".host/81ceabb30d37bbdb3868004629cb84e9/modules-load.d", "/sysroot/etc/modules-load.d"}, nil, nil}, {"symlink", expectArgs{"/proc/mounts", "/sysroot/etc/mtab"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"success nested", new(Params), &AutoEtcOp{ Prefix: "81ceabb30d37bbdb3868004629cb84e9", diff --git a/container/autoroot.go b/container/autoroot.go index 32b5062..9d45609 100644 --- a/container/autoroot.go +++ b/container/autoroot.go @@ -29,7 +29,7 @@ func (r *AutoRootOp) Valid() bool { return r != nil && r.Host != nil } func (r *AutoRootOp) early(state *setupState, k syscallDispatcher) error { if d, err := k.readdir(r.Host.String()); err != nil { - return wrapErrSelf(err) + return err } else { r.resolved = make([]Op, 0, len(d)) for _, ent := range d { diff --git a/container/autoroot_test.go b/container/autoroot_test.go index 13319de..3678725 100644 --- a/container/autoroot_test.go +++ b/container/autoroot_test.go @@ -20,7 +20,7 @@ func TestAutoRootOp(t *testing.T) { Flags: BindWritable, }, []kexpect{ {"readdir", expectArgs{"/"}, stubDir(), errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"early", &Params{ParentPerm: 0750}, &AutoRootOp{ Host: MustAbs("/"), @@ -29,7 +29,7 @@ func TestAutoRootOp(t *testing.T) { {"readdir", expectArgs{"/"}, stubDir("bin", "dev", "etc", "home", "lib64", "lost+found", "mnt", "nix", "proc", "root", "run", "srv", "sys", "tmp", "usr", "var"), nil}, {"evalSymlinks", expectArgs{"/bin"}, "", errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"apply", &Params{ParentPerm: 0750}, &AutoRootOp{ Host: MustAbs("/"), @@ -51,7 +51,7 @@ func TestAutoRootOp(t *testing.T) { }, nil, []kexpect{ {"verbosef", expectArgs{"%s %s", []any{"mounting", &BindMountOp{MustAbs("/usr/bin"), MustAbs("/bin"), MustAbs("/bin"), BindWritable}}}, nil, nil}, {"stat", expectArgs{"/host/usr/bin"}, isDirFi(false), errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"success pd", &Params{ParentPerm: 0750}, &AutoRootOp{ Host: MustAbs("/"), diff --git a/container/init_test.go b/container/init_test.go index 94e165d..bc29770 100644 --- a/container/init_test.go +++ b/container/init_test.go @@ -410,13 +410,51 @@ func TestInitEntrypoint(t *testing.T) { {"mount", expectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil}, /* begin early */ {"evalSymlinks", expectArgs{"/"}, "/", errUnique}, - {"printBaseErr", expectArgs{wrapErrSelf(errUnique), "cannot prepare op at index 0:"}, nil, nil}, + {"printBaseErr", expectArgs{errUnique, "cannot prepare op at index 0:"}, nil, nil}, {"beforeExit", expectArgs{}, nil, nil}, {"exit", expectArgs{1}, nil, nil}, /* end early */ }, }, nil}, + {"early", func(k syscallDispatcher) error { initEntrypoint(k, assertPrefix, assertVerboseTrue); return nil }, [][]kexpect{ + { + {"lockOSThread", expectArgs{}, nil, nil}, + {"getpid", expectArgs{}, 1, nil}, + {"setPtracer", expectArgs{uintptr(0)}, nil, nil}, + {"receive", expectArgs{"HAKUREI_SETUP", new(initParams), new(uintptr), &initParams{Params{ + Dir: MustAbs("/.hakurei"), + Env: []string{"DISPLAY=:0"}, + Path: MustAbs("/bin/zsh"), + Args: []string{"zsh", "-c", "exec vim"}, + ForwardCancel: true, + AdoptWaitDelay: 5 * time.Second, + Uid: 1 << 32, + Gid: 1 << 31, + Hostname: "hakurei-check", + Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), + SeccompRules: make([]seccomp.NativeRule, 0), + SeccompPresets: seccomp.PresetStrict, + RetainSession: true, + Privileged: true, + }, 1000, 100, 3, true}, uintptr(9)}, errUnique, nil}, + {"verbose", expectArgs{[]any{"received setup parameters"}}, nil, nil}, + {"setDumpable", expectArgs{uintptr(1)}, nil, nil}, + {"writeFile", expectArgs{"/proc/self/uid_map", []byte("4294967296 1000 1\n"), os.FileMode(0)}, nil, nil}, + {"writeFile", expectArgs{"/proc/self/setgroups", []byte("deny\n"), os.FileMode(0)}, nil, nil}, + {"writeFile", expectArgs{"/proc/self/gid_map", []byte("2147483648 100 1\n"), os.FileMode(0)}, nil, nil}, + {"setDumpable", expectArgs{uintptr(0)}, nil, nil}, + {"umask", expectArgs{0}, 022, nil}, + {"sethostname", expectArgs{[]byte("hakurei-check")}, nil, nil}, + {"lastcap", expectArgs{}, uintptr(40), nil}, + {"mount", expectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil}, + /* begin early */ + {"evalSymlinks", expectArgs{"/"}, "/", &os.PathError{Op: "readlink", Path: "/", Err: errUnique}}, + {"fatal", expectArgs{[]any{"cannot readlink /: unique error injected by the test suite"}}, nil, nil}, + /* end early */ + }, + }, nil}, + {"mount ih", func(k syscallDispatcher) error { initEntrypoint(k, assertPrefix, assertVerboseTrue); return nil }, [][]kexpect{ { {"lockOSThread", expectArgs{}, nil, nil}, @@ -711,6 +749,62 @@ func TestInitEntrypoint(t *testing.T) { }, }, nil}, + {"apply unhandled error", func(k syscallDispatcher) error { initEntrypoint(k, assertPrefix, assertVerboseTrue); return nil }, [][]kexpect{ + { + {"lockOSThread", expectArgs{}, nil, nil}, + {"getpid", expectArgs{}, 1, nil}, + {"setPtracer", expectArgs{uintptr(0)}, nil, nil}, + {"receive", expectArgs{"HAKUREI_SETUP", new(initParams), new(uintptr), &initParams{Params{ + Dir: MustAbs("/.hakurei"), + Env: []string{"DISPLAY=:0"}, + Path: MustAbs("/bin/zsh"), + Args: []string{"zsh", "-c", "exec vim"}, + ForwardCancel: true, + AdoptWaitDelay: 5 * time.Second, + Uid: 1 << 32, + Gid: 1 << 31, + Hostname: "hakurei-check", + Ops: new(Ops).Bind(MustAbs("/"), MustAbs("/"), BindDevice).Proc(MustAbs("/proc/")), + SeccompRules: make([]seccomp.NativeRule, 0), + SeccompPresets: seccomp.PresetStrict, + RetainSession: true, + Privileged: true, + }, 1000, 100, 3, true}, uintptr(9)}, errUnique, nil}, + {"verbose", expectArgs{[]any{"received setup parameters"}}, nil, nil}, + {"setDumpable", expectArgs{uintptr(1)}, nil, nil}, + {"writeFile", expectArgs{"/proc/self/uid_map", []byte("4294967296 1000 1\n"), os.FileMode(0)}, nil, nil}, + {"writeFile", expectArgs{"/proc/self/setgroups", []byte("deny\n"), os.FileMode(0)}, nil, nil}, + {"writeFile", expectArgs{"/proc/self/gid_map", []byte("2147483648 100 1\n"), os.FileMode(0)}, nil, nil}, + {"setDumpable", expectArgs{uintptr(0)}, nil, nil}, + {"umask", expectArgs{0}, 022, nil}, + {"sethostname", expectArgs{[]byte("hakurei-check")}, nil, nil}, + {"lastcap", expectArgs{}, uintptr(40), nil}, + {"mount", expectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil}, + /* begin early */ + {"evalSymlinks", expectArgs{"/"}, "/", nil}, + /* end early */ + {"mount", expectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil}, + {"chdir", expectArgs{"/proc/self/fd"}, nil, nil}, + {"mkdir", expectArgs{"sysroot", os.FileMode(0755)}, nil, nil}, + {"mount", expectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil}, + {"mkdir", expectArgs{"host", os.FileMode(0755)}, nil, nil}, + {"pivotRoot", expectArgs{"/proc/self/fd", "host"}, nil, nil}, + {"chdir", expectArgs{"/"}, nil, nil}, + /* begin apply */ + {"verbosef", expectArgs{"%s %s", []any{"mounting", &BindMountOp{sourceFinal: MustAbs("/"), Source: MustAbs("/"), Target: MustAbs("/"), Flags: BindDevice}}}, nil, nil}, + {"stat", expectArgs{"/host"}, isDirFi(true), nil}, + {"mkdirAll", expectArgs{"/sysroot", os.FileMode(0700)}, nil, nil}, + {"bindMount", expectArgs{"/host", "/sysroot", uintptr(0x4001), false}, nil, nil}, + {"verbosef", expectArgs{"%s %s", []any{"mounting", &MountProcOp{Target: MustAbs("/proc/")}}}, nil, nil}, + {"mkdirAll", expectArgs{"/sysroot/proc", os.FileMode(0755)}, nil, nil}, + {"mount", expectArgs{"proc", "/sysroot/proc", "proc", uintptr(0xe), ""}, nil, errUnique}, + {"printBaseErr", expectArgs{errUnique, "cannot apply op at index 1:"}, nil, nil}, + {"beforeExit", expectArgs{}, nil, nil}, + {"exit", expectArgs{1}, nil, nil}, + /* end apply */ + }, + }, nil}, + {"apply", func(k syscallDispatcher) error { initEntrypoint(k, assertPrefix, assertVerboseTrue); return nil }, [][]kexpect{ { {"lockOSThread", expectArgs{}, nil, nil}, diff --git a/container/initbind.go b/container/initbind.go index 932095b..41097fa 100644 --- a/container/initbind.go +++ b/container/initbind.go @@ -43,7 +43,7 @@ func (b *BindMountOp) Valid() bool { func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error { if b.Flags&BindEnsure != 0 { if err := k.mkdirAll(b.Source.String(), 0700); err != nil { - return wrapErrSelf(err) + return err } } @@ -52,7 +52,7 @@ func (b *BindMountOp) early(_ *setupState, k syscallDispatcher) error { // leave sourceFinal as nil return nil } - return wrapErrSelf(err) + return err } else { b.sourceFinal, err = NewAbs(pathname) return err @@ -74,10 +74,10 @@ func (b *BindMountOp) apply(_ *setupState, k syscallDispatcher) error { // this perm value emulates bwrap behaviour as it clears bits from 0755 based on // op->perms which is never set for any bind setup op so always results in 0700 if fi, err := k.stat(source); err != nil { - return wrapErrSelf(err) + return err } else if fi.IsDir() { if err = k.mkdirAll(target, 0700); err != nil { - return wrapErrSelf(err) + return err } } else if err = k.ensureFile(target, 0444, 0700); err != nil { return err diff --git a/container/initbind_test.go b/container/initbind_test.go index 38e664d..3c91c61 100644 --- a/container/initbind_test.go +++ b/container/initbind_test.go @@ -14,7 +14,7 @@ func TestBindMountOp(t *testing.T) { Target: MustAbs("/bin/"), }, []kexpect{ {"evalSymlinks", expectArgs{"/bin/"}, "", syscall.ENOENT}, - }, wrapErrSelf(syscall.ENOENT), nil, nil}, + }, syscall.ENOENT, nil, nil}, {"skip optional", new(Params), &BindMountOp{ Source: MustAbs("/bin/"), @@ -53,7 +53,7 @@ func TestBindMountOp(t *testing.T) { Flags: BindEnsure, }, []kexpect{ {"mkdirAll", expectArgs{"/bin/", os.FileMode(0700)}, nil, errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"success ensure", new(Params), &BindMountOp{ Source: MustAbs("/bin/"), @@ -97,7 +97,7 @@ func TestBindMountOp(t *testing.T) { Target: MustAbs("/bin/"), }, []kexpect{ {"evalSymlinks", expectArgs{"/bin/"}, "/usr/bin", errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"stat", new(Params), &BindMountOp{ Source: MustAbs("/bin/"), @@ -106,7 +106,7 @@ func TestBindMountOp(t *testing.T) { {"evalSymlinks", expectArgs{"/bin/"}, "/usr/bin", nil}, }, nil, []kexpect{ {"stat", expectArgs{"/host/usr/bin"}, isDirFi(true), errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mkdirAll", new(Params), &BindMountOp{ Source: MustAbs("/bin/"), @@ -116,7 +116,7 @@ func TestBindMountOp(t *testing.T) { }, nil, []kexpect{ {"stat", expectArgs{"/host/usr/bin"}, isDirFi(true), nil}, {"mkdirAll", expectArgs{"/sysroot/bin", os.FileMode(0700)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"bindMount", new(Params), &BindMountOp{ Source: MustAbs("/bin/"), diff --git a/container/initdev.go b/container/initdev.go index 9bb9561..58e8971 100644 --- a/container/initdev.go +++ b/container/initdev.go @@ -59,7 +59,7 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error { FHSProc+"self/fd/"+string(rune(i+'0')), path.Join(target, name), ); err != nil { - return wrapErrSelf(err) + return err } } for _, pair := range [][2]string{ @@ -68,7 +68,7 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error { {"pts/ptmx", "ptmx"}, } { if err := k.symlink(pair[0], path.Join(target, pair[1])); err != nil { - return wrapErrSelf(err) + return err } } @@ -76,7 +76,7 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error { devPtsPath := path.Join(target, "pts") for _, name := range []string{devShmPath, devPtsPath} { if err := k.mkdir(name, state.ParentPerm); err != nil { - return wrapErrSelf(err) + return err } } @@ -92,7 +92,7 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error { return err } if name, err := k.readlink(hostProc.stdout()); err != nil { - return wrapErrSelf(err) + return err } else if err = k.bindMount( toHost(name), consolePath, @@ -107,7 +107,7 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error { if d.Mqueue { mqueueTarget := path.Join(target, "mqueue") if err := k.mkdir(mqueueTarget, state.ParentPerm); err != nil { - return wrapErrSelf(err) + return err } if err := k.mount(SourceMqueue, mqueueTarget, FstypeMqueue, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString); err != nil { return err diff --git a/container/initdev_test.go b/container/initdev_test.go index b7aef45..3293161 100644 --- a/container/initdev_test.go +++ b/container/initdev_test.go @@ -194,7 +194,7 @@ func TestMountDevOp(t *testing.T) { {"ensureFile", expectArgs{"/sysroot/dev/tty", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, {"bindMount", expectArgs{"/host/dev/tty", "/sysroot/dev/tty", uintptr(0), true}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd/0", "/sysroot/dev/stdin"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink stdout", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -215,7 +215,7 @@ func TestMountDevOp(t *testing.T) { {"bindMount", expectArgs{"/host/dev/tty", "/sysroot/dev/tty", uintptr(0), true}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd/0", "/sysroot/dev/stdin"}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd/1", "/sysroot/dev/stdout"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink stderr", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -237,7 +237,7 @@ func TestMountDevOp(t *testing.T) { {"symlink", expectArgs{"/proc/self/fd/0", "/sysroot/dev/stdin"}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd/1", "/sysroot/dev/stdout"}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd/2", "/sysroot/dev/stderr"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink fd", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -260,7 +260,7 @@ func TestMountDevOp(t *testing.T) { {"symlink", expectArgs{"/proc/self/fd/1", "/sysroot/dev/stdout"}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd/2", "/sysroot/dev/stderr"}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd", "/sysroot/dev/fd"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink kcore", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -284,7 +284,7 @@ func TestMountDevOp(t *testing.T) { {"symlink", expectArgs{"/proc/self/fd/2", "/sysroot/dev/stderr"}, nil, nil}, {"symlink", expectArgs{"/proc/self/fd", "/sysroot/dev/fd"}, nil, nil}, {"symlink", expectArgs{"/proc/kcore", "/sysroot/dev/core"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"symlink ptmx", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -309,7 +309,7 @@ func TestMountDevOp(t *testing.T) { {"symlink", expectArgs{"/proc/self/fd", "/sysroot/dev/fd"}, nil, nil}, {"symlink", expectArgs{"/proc/kcore", "/sysroot/dev/core"}, nil, nil}, {"symlink", expectArgs{"pts/ptmx", "/sysroot/dev/ptmx"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mkdir shm", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -335,7 +335,7 @@ func TestMountDevOp(t *testing.T) { {"symlink", expectArgs{"/proc/kcore", "/sysroot/dev/core"}, nil, nil}, {"symlink", expectArgs{"pts/ptmx", "/sysroot/dev/ptmx"}, nil, nil}, {"mkdir", expectArgs{"/sysroot/dev/shm", os.FileMode(0750)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mkdir devpts", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -362,7 +362,7 @@ func TestMountDevOp(t *testing.T) { {"symlink", expectArgs{"pts/ptmx", "/sysroot/dev/ptmx"}, nil, nil}, {"mkdir", expectArgs{"/sysroot/dev/shm", os.FileMode(0750)}, nil, nil}, {"mkdir", expectArgs{"/sysroot/dev/pts", os.FileMode(0750)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mount devpts", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -451,7 +451,7 @@ func TestMountDevOp(t *testing.T) { {"isatty", expectArgs{1}, true, nil}, {"ensureFile", expectArgs{"/sysroot/dev/console", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, {"readlink", expectArgs{"/host/proc/self/fd/1"}, "", errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"bindMount stdout", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -516,7 +516,7 @@ func TestMountDevOp(t *testing.T) { {"readlink", expectArgs{"/host/proc/self/fd/1"}, "/dev/pts/2", nil}, {"bindMount", expectArgs{"/host/dev/pts/2", "/sysroot/dev/console", uintptr(0), false}, nil, nil}, {"mkdir", expectArgs{"/sysroot/dev/mqueue", os.FileMode(0750)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mount mqueue", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), @@ -615,6 +615,38 @@ func TestMountDevOp(t *testing.T) { {"mount", expectArgs{"mqueue", "/sysroot/dev/mqueue", "mqueue", uintptr(0xe), ""}, nil, nil}, }, nil}, + {"remount", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ + Target: MustAbs("/dev/"), + }, nil, nil, []kexpect{ + {"mountTmpfs", expectArgs{"devtmpfs", "/sysroot/dev", uintptr(0x6), 0, os.FileMode(0750)}, nil, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/null", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"bindMount", expectArgs{"/host/dev/null", "/sysroot/dev/null", uintptr(0), true}, nil, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/zero", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"bindMount", expectArgs{"/host/dev/zero", "/sysroot/dev/zero", uintptr(0), true}, nil, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/full", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"bindMount", expectArgs{"/host/dev/full", "/sysroot/dev/full", uintptr(0), true}, nil, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/random", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"bindMount", expectArgs{"/host/dev/random", "/sysroot/dev/random", uintptr(0), true}, nil, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/urandom", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"bindMount", expectArgs{"/host/dev/urandom", "/sysroot/dev/urandom", uintptr(0), true}, nil, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/tty", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"bindMount", expectArgs{"/host/dev/tty", "/sysroot/dev/tty", uintptr(0), true}, nil, nil}, + {"symlink", expectArgs{"/proc/self/fd/0", "/sysroot/dev/stdin"}, nil, nil}, + {"symlink", expectArgs{"/proc/self/fd/1", "/sysroot/dev/stdout"}, nil, nil}, + {"symlink", expectArgs{"/proc/self/fd/2", "/sysroot/dev/stderr"}, nil, nil}, + {"symlink", expectArgs{"/proc/self/fd", "/sysroot/dev/fd"}, nil, nil}, + {"symlink", expectArgs{"/proc/kcore", "/sysroot/dev/core"}, nil, nil}, + {"symlink", expectArgs{"pts/ptmx", "/sysroot/dev/ptmx"}, nil, nil}, + {"mkdir", expectArgs{"/sysroot/dev/shm", os.FileMode(0750)}, nil, nil}, + {"mkdir", expectArgs{"/sysroot/dev/pts", os.FileMode(0750)}, nil, nil}, + {"mount", expectArgs{"devpts", "/sysroot/dev/pts", "devpts", uintptr(0xa), "newinstance,ptmxmode=0666,mode=620"}, nil, nil}, + {"isatty", expectArgs{1}, true, nil}, + {"ensureFile", expectArgs{"/sysroot/dev/console", os.FileMode(0444), os.FileMode(0750)}, nil, nil}, + {"readlink", expectArgs{"/host/proc/self/fd/1"}, "/dev/pts/2", nil}, + {"bindMount", expectArgs{"/host/dev/pts/2", "/sysroot/dev/console", uintptr(0), false}, nil, nil}, + {"remount", expectArgs{"/sysroot/dev", uintptr(1)}, nil, errUnique}, + }, errUnique}, + {"success no mqueue", &Params{ParentPerm: 0750, RetainSession: true}, &MountDevOp{ Target: MustAbs("/dev/"), }, nil, nil, []kexpect{ diff --git a/container/initmkdir.go b/container/initmkdir.go index 2f77a52..40f00fc 100644 --- a/container/initmkdir.go +++ b/container/initmkdir.go @@ -23,7 +23,7 @@ type MkdirOp struct { func (m *MkdirOp) Valid() bool { return m != nil && m.Path != nil } func (m *MkdirOp) early(*setupState, syscallDispatcher) error { return nil } func (m *MkdirOp) apply(_ *setupState, k syscallDispatcher) error { - return wrapErrSelf(k.mkdirAll(toSysroot(m.Path.String()), m.Perm)) + return k.mkdirAll(toSysroot(m.Path.String()), m.Perm) } func (m *MkdirOp) Is(op Op) bool { diff --git a/container/initoverlay.go b/container/initoverlay.go index 2e648d8..f9daaaa 100644 --- a/container/initoverlay.go +++ b/container/initoverlay.go @@ -102,7 +102,7 @@ func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error { if o.Upper != nil { if v, err := k.evalSymlinks(o.Upper.String()); err != nil { - return wrapErrSelf(err) + return err } else { o.upper = EscapeOverlayDataSegment(toHost(v)) } @@ -110,7 +110,7 @@ func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error { if o.Work != nil { if v, err := k.evalSymlinks(o.Work.String()); err != nil { - return wrapErrSelf(err) + return err } else { o.work = EscapeOverlayDataSegment(toHost(v)) } @@ -120,7 +120,7 @@ func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error { o.lower = make([]string, len(o.Lower)) for i, a := range o.Lower { // nil checked in Valid if v, err := k.evalSymlinks(a.String()); err != nil { - return wrapErrSelf(err) + return err } else { o.lower[i] = EscapeOverlayDataSegment(toHost(v)) } @@ -134,17 +134,17 @@ func (o *MountOverlayOp) apply(state *setupState, k syscallDispatcher) error { target = toSysroot(target) } if err := k.mkdirAll(target, state.ParentPerm); err != nil { - return wrapErrSelf(err) + return err } if o.ephemeral { var err error // these directories are created internally, therefore early (absolute, symlink, prefix, escape) is bypassed if o.upper, err = k.mkdirTemp(FHSRoot, intermediatePatternOverlayUpper); err != nil { - return wrapErrSelf(err) + return err } if o.work, err = k.mkdirTemp(FHSRoot, intermediatePatternOverlayWork); err != nil { - return wrapErrSelf(err) + return err } } diff --git a/container/initoverlay_test.go b/container/initoverlay_test.go index 2c076f2..64b0bf3 100644 --- a/container/initoverlay_test.go +++ b/container/initoverlay_test.go @@ -31,7 +31,7 @@ func TestMountOverlayOp(t *testing.T) { }, nil, []kexpect{ {"mkdirAll", expectArgs{"/sysroot", os.FileMode(0705)}, nil, nil}, {"mkdirTemp", expectArgs{"/", "overlay.upper.*"}, "overlay.upper.32768", errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mkdirTemp work ephemeral", &Params{ParentPerm: 0705}, &MountOverlayOp{ Target: MustAbs("/"), @@ -47,7 +47,7 @@ func TestMountOverlayOp(t *testing.T) { {"mkdirAll", expectArgs{"/sysroot", os.FileMode(0705)}, nil, nil}, {"mkdirTemp", expectArgs{"/", "overlay.upper.*"}, "overlay.upper.32768", nil}, {"mkdirTemp", expectArgs{"/", "overlay.work.*"}, "overlay.work.32768", errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"success ephemeral", &Params{ParentPerm: 0705}, &MountOverlayOp{ Target: MustAbs("/"), @@ -138,7 +138,7 @@ func TestMountOverlayOp(t *testing.T) { Work: MustAbs("/mnt-root/nix/.rw-store/work"), }, []kexpect{ {"evalSymlinks", expectArgs{"/mnt-root/nix/.rw-store/upper"}, "/mnt-root/nix/.rw-store/.upper", errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"evalSymlinks work", &Params{ParentPerm: 0700}, &MountOverlayOp{ Target: MustAbs("/nix/store"), @@ -148,7 +148,7 @@ func TestMountOverlayOp(t *testing.T) { }, []kexpect{ {"evalSymlinks", expectArgs{"/mnt-root/nix/.rw-store/upper"}, "/mnt-root/nix/.rw-store/.upper", nil}, {"evalSymlinks", expectArgs{"/mnt-root/nix/.rw-store/work"}, "/mnt-root/nix/.rw-store/.work", errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"evalSymlinks lower", &Params{ParentPerm: 0700}, &MountOverlayOp{ Target: MustAbs("/nix/store"), @@ -159,7 +159,7 @@ func TestMountOverlayOp(t *testing.T) { {"evalSymlinks", expectArgs{"/mnt-root/nix/.rw-store/upper"}, "/mnt-root/nix/.rw-store/.upper", nil}, {"evalSymlinks", expectArgs{"/mnt-root/nix/.rw-store/work"}, "/mnt-root/nix/.rw-store/.work", nil}, {"evalSymlinks", expectArgs{"/mnt-root/nix/.ro-store"}, "/mnt-root/nix/ro-store", errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"mkdirAll", &Params{ParentPerm: 0700}, &MountOverlayOp{ Target: MustAbs("/nix/store"), @@ -172,7 +172,7 @@ func TestMountOverlayOp(t *testing.T) { {"evalSymlinks", expectArgs{"/mnt-root/nix/.ro-store"}, "/mnt-root/nix/ro-store", nil}, }, nil, []kexpect{ {"mkdirAll", expectArgs{"/sysroot/nix/store", os.FileMode(0700)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"mount", &Params{ParentPerm: 0700}, &MountOverlayOp{ Target: MustAbs("/nix/store"), diff --git a/container/initplace.go b/container/initplace.go index 8b88345..e26d8a9 100644 --- a/container/initplace.go +++ b/container/initplace.go @@ -39,13 +39,11 @@ func (t *TmpfileOp) early(*setupState, syscallDispatcher) error { return nil } func (t *TmpfileOp) apply(state *setupState, k syscallDispatcher) error { var tmpPath string if f, err := k.createTemp(FHSRoot, intermediatePatternTmpfile); err != nil { - return wrapErrSelf(err) + return err } else if _, err = f.Write(t.Data); err != nil { - return wrapErrSuffix(err, - "cannot write to intermediate file:") + return err } else if err = f.Close(); err != nil { - return wrapErrSuffix(err, - "cannot close intermediate file:") + return err } else { tmpPath = f.Name() } @@ -61,7 +59,7 @@ func (t *TmpfileOp) apply(state *setupState, k syscallDispatcher) error { ); err != nil { return err } else if err = k.remove(tmpPath); err != nil { - return wrapErrSelf(err) + return err } return nil } diff --git a/container/initplace_test.go b/container/initplace_test.go index 02c3733..07402de 100644 --- a/container/initplace_test.go +++ b/container/initplace_test.go @@ -18,21 +18,21 @@ func TestTmpfileOp(t *testing.T) { Data: sampleData, }, nil, nil, []kexpect{ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"Write", &Params{ParentPerm: 0700}, &TmpfileOp{ Path: samplePath, Data: sampleData, }, nil, nil, []kexpect{ {"createTemp", expectArgs{"/", "tmp.*"}, writeErrOsFile{errUnique}, nil}, - }, wrapErrSuffix(errUnique, "cannot write to intermediate file:")}, + }, errUnique}, {"Close", &Params{ParentPerm: 0700}, &TmpfileOp{ Path: samplePath, Data: sampleData, }, nil, nil, []kexpect{ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, errUnique), nil}, - }, wrapErrSuffix(errUnique, "cannot close intermediate file:")}, + }, errUnique}, {"ensureFile", &Params{ParentPerm: 0700}, &TmpfileOp{ Path: samplePath, @@ -59,7 +59,7 @@ func TestTmpfileOp(t *testing.T) { {"ensureFile", expectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil}, {"bindMount", expectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil}, {"remove", expectArgs{"tmp.32768"}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"success", &Params{ParentPerm: 0700}, &TmpfileOp{ Path: samplePath, diff --git a/container/initproc.go b/container/initproc.go index d003809..877349f 100644 --- a/container/initproc.go +++ b/container/initproc.go @@ -22,7 +22,7 @@ func (p *MountProcOp) early(*setupState, syscallDispatcher) error { return nil } func (p *MountProcOp) apply(state *setupState, k syscallDispatcher) error { target := toSysroot(p.Target.String()) if err := k.mkdirAll(target, state.ParentPerm); err != nil { - return wrapErrSelf(err) + return err } return k.mount(SourceProc, target, FstypeProc, MS_NOSUID|MS_NOEXEC|MS_NODEV, zeroString) } diff --git a/container/initproc_test.go b/container/initproc_test.go index 2d72bd7..ca90178 100644 --- a/container/initproc_test.go +++ b/container/initproc_test.go @@ -12,7 +12,7 @@ func TestMountProcOp(t *testing.T) { Target: MustAbs("/proc/"), }, nil, nil, []kexpect{ {"mkdirAll", expectArgs{"/sysroot/proc", os.FileMode(0755)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"success", &Params{ParentPerm: 0700}, &MountProcOp{ diff --git a/container/initsymlink.go b/container/initsymlink.go index 33e00e0..4d1f8e4 100644 --- a/container/initsymlink.go +++ b/container/initsymlink.go @@ -32,7 +32,7 @@ func (l *SymlinkOp) early(_ *setupState, k syscallDispatcher) error { return &AbsoluteError{l.LinkName} } if name, err := k.readlink(l.LinkName); err != nil { - return wrapErrSelf(err) + return err } else { l.LinkName = name } @@ -43,9 +43,9 @@ func (l *SymlinkOp) early(_ *setupState, k syscallDispatcher) error { func (l *SymlinkOp) apply(state *setupState, k syscallDispatcher) error { target := toSysroot(l.Target.String()) if err := k.mkdirAll(path.Dir(target), state.ParentPerm); err != nil { - return wrapErrSelf(err) + return err } - return wrapErrSelf(k.symlink(l.LinkName, target)) + return k.symlink(l.LinkName, target) } func (l *SymlinkOp) Is(op Op) bool { diff --git a/container/initsymlink_test.go b/container/initsymlink_test.go index 0687afd..db1c1a5 100644 --- a/container/initsymlink_test.go +++ b/container/initsymlink_test.go @@ -12,7 +12,7 @@ func TestSymlinkOp(t *testing.T) { LinkName: "/etc/static/nixos", }, nil, nil, []kexpect{ {"mkdirAll", expectArgs{"/sysroot/etc", os.FileMode(0700)}, nil, errUnique}, - }, wrapErrSelf(errUnique)}, + }, errUnique}, {"abs", &Params{ParentPerm: 0755}, &SymlinkOp{ Target: MustAbs("/etc/mtab"), @@ -26,7 +26,7 @@ func TestSymlinkOp(t *testing.T) { Dereference: true, }, []kexpect{ {"readlink", expectArgs{"/etc/mtab"}, "/proc/mounts", errUnique}, - }, wrapErrSelf(errUnique), nil, nil}, + }, errUnique, nil, nil}, {"success noderef", &Params{ParentPerm: 0700}, &SymlinkOp{ Target: MustAbs("/etc/nixos"), diff --git a/container/mount.go b/container/mount.go index fc510b4..fc2a16e 100644 --- a/container/mount.go +++ b/container/mount.go @@ -118,7 +118,7 @@ func (p *procPaths) remount(target string, flags uintptr) error { var targetFinal string if v, err := p.k.evalSymlinks(target); err != nil { - return wrapErrSelf(err) + return err } else { targetFinal = v if targetFinal != target { @@ -134,14 +134,12 @@ func (p *procPaths) remount(target string, flags uintptr) error { destFd, err = p.k.open(targetFinal, O_PATH|O_CLOEXEC, 0) return }); err != nil { - return wrapErrSuffix(err, - fmt.Sprintf("cannot open %q:", targetFinal)) + return &os.PathError{Op: "open", Path: targetFinal, Err: err} } if v, err := p.k.readlink(p.fd(destFd)); err != nil { - return wrapErrSelf(err) + return err } else if err = p.k.close(destFd); err != nil { - return wrapErrSuffix(err, - fmt.Sprintf("cannot close %q:", targetFinal)) + return &os.PathError{Op: "close", Path: targetFinal, Err: err} } else { targetKFinal = v } @@ -202,7 +200,7 @@ func mountTmpfs(k syscallDispatcher, fsname, target string, flags uintptr, size // syscallDispatcher.mountTmpfs must not be called from this function if err := k.mkdirAll(target, parentPerm(perm)); err != nil { - return wrapErrSelf(err) + return err } opt := fmt.Sprintf("mode=%#o", perm) if size > 0 { diff --git a/container/mount_test.go b/container/mount_test.go index c3d9ad3..e50af31 100644 --- a/container/mount_test.go +++ b/container/mount_test.go @@ -83,14 +83,14 @@ func TestRemount(t *testing.T) { return newProcPaths(k, hostPath).remount("/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) }, [][]kexpect{{ {"evalSymlinks", expectArgs{"/sysroot/nix"}, "/sysroot/nix", errUnique}, - }}, wrapErrSelf(errUnique)}, + }}, errUnique}, {"open", func(k syscallDispatcher) error { return newProcPaths(k, hostPath).remount("/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) }, [][]kexpect{{ {"evalSymlinks", expectArgs{"/sysroot/nix"}, "/sysroot/nix", nil}, {"open", expectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, errUnique}, - }}, wrapErrSuffix(errUnique, `cannot open "/sysroot/nix":`)}, + }}, errUnique}, {"readlink", func(k syscallDispatcher) error { return newProcPaths(k, hostPath).remount("/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) @@ -98,7 +98,7 @@ func TestRemount(t *testing.T) { {"evalSymlinks", expectArgs{"/sysroot/nix"}, "/sysroot/nix", nil}, {"open", expectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil}, {"readlink", expectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", errUnique}, - }}, wrapErrSelf(errUnique)}, + }}, errUnique}, {"close", func(k syscallDispatcher) error { return newProcPaths(k, hostPath).remount("/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) @@ -107,7 +107,7 @@ func TestRemount(t *testing.T) { {"open", expectArgs{"/sysroot/nix", 0x280000, uint32(0)}, 0xdeadbeef, nil}, {"readlink", expectArgs{"/host/proc/self/fd/3735928559"}, "/sysroot/nix", nil}, {"close", expectArgs{0xdeadbeef}, nil, errUnique}, - }}, wrapErrSuffix(errUnique, `cannot close "/sysroot/nix":`)}, + }}, errUnique}, {"mountinfo stale", func(k syscallDispatcher) error { return newProcPaths(k, hostPath).remount("/sysroot/nix", syscall.MS_REC|syscall.MS_RDONLY|syscall.MS_NODEV) @@ -243,7 +243,7 @@ func TestMountTmpfs(t *testing.T) { return mountTmpfs(k, "ephemeral", "/sysroot/run/user/1000", 0, 1<<10, 0700) }, [][]kexpect{{ {"mkdirAll", expectArgs{"/sysroot/run/user/1000", os.FileMode(0700)}, nil, errUnique}, - }}, wrapErrSelf(errUnique)}, + }}, errUnique}, {"success no size", func(k syscallDispatcher) error { return mountTmpfs(k, "ephemeral", "/sysroot/run/user/1000", 0, 0, 0710) diff --git a/container/output.go b/container/output.go index 6bedd55..4fd9f09 100644 --- a/container/output.go +++ b/container/output.go @@ -17,10 +17,3 @@ func wrapErrSuffix(err error, a ...any) error { } return msg.WrapErr(err, append(a, err)...) } - -func wrapErrSelf(err error) error { - if err == nil { - return nil - } - return msg.WrapErr(err, err.Error()) -} diff --git a/container/output_test.go b/container/output_test.go index 3fb2ac7..f6d629e 100644 --- a/container/output_test.go +++ b/container/output_test.go @@ -58,16 +58,6 @@ func TestWrapErr(t *testing.T) { t.Errorf("wrapErrSuffix: %v", err) } }, syscall.ENOTRECOVERABLE, []any{"\x00\x00", syscall.ENOTRECOVERABLE}}, - {"self nil", func(t *testing.T) { - if err := wrapErrSelf(nil); err != nil { - t.Errorf("wrapErrSelf: %v", err) - } - }, nil, nil}, - {"self val", func(t *testing.T) { - if err := wrapErrSelf(syscall.ENOTRECOVERABLE); err != syscall.ENOTRECOVERABLE { - t.Errorf("wrapErrSelf: %v", err) - } - }, syscall.ENOTRECOVERABLE, []any{"state not recoverable"}}, } for _, tc := range testCases { diff --git a/container/path.go b/container/path.go index 09db97a..4a436ab 100644 --- a/container/path.go +++ b/container/path.go @@ -2,7 +2,6 @@ package container import ( "errors" - "fmt" "io/fs" "os" "path" @@ -103,30 +102,29 @@ func toHost(name string) string { func createFile(name string, perm, pperm os.FileMode, content []byte) error { if err := os.MkdirAll(path.Dir(name), pperm); err != nil { - return wrapErrSelf(err) + return err } f, err := os.OpenFile(name, syscall.O_CREAT|syscall.O_EXCL|syscall.O_WRONLY, perm) if err != nil { - return wrapErrSelf(err) + return err } if content != nil { _, err = f.Write(content) } - return errors.Join(f.Close(), wrapErrSelf(err)) + return errors.Join(f.Close(), err) } func ensureFile(name string, perm, pperm os.FileMode) error { fi, err := os.Stat(name) if err != nil { if !os.IsNotExist(err) { - return wrapErrSelf(err) + return err } return createFile(name, perm, pperm, nil) } if mode := fi.Mode(); mode&fs.ModeDir != 0 || mode&fs.ModeSymlink != 0 { - err = msg.WrapErr(syscall.EISDIR, - fmt.Sprintf("path %q is a directory", name)) + err = &os.PathError{Op: "ensure", Path: name, Err: syscall.EISDIR} } return err } @@ -147,12 +145,12 @@ func (p *procPaths) stdout() string { return p.self + "/fd/1" } func (p *procPaths) fd(fd int) string { return p.self + "/fd/" + strconv.Itoa(fd) } func (p *procPaths) mountinfo(f func(d *vfs.MountInfoDecoder) error) error { if r, err := p.k.openNew(p.self + "/mountinfo"); err != nil { - return wrapErrSelf(err) + return err } else { d := vfs.NewMountInfoDecoder(r) err0 := f(d) if err = r.Close(); err != nil { - return wrapErrSelf(err) + return err } else if err = d.Err(); err != nil { return wrapErrSuffix(err, "cannot parse mountinfo:") diff --git a/container/path_test.go b/container/path_test.go index 3b2869e..c3b68b3 100644 --- a/container/path_test.go +++ b/container/path_test.go @@ -2,7 +2,6 @@ package container import ( "errors" - "fmt" "io" "math" "os" @@ -56,20 +55,27 @@ func InternalToHostOvlEscape(s string) string { return EscapeOverlayDataSegment( func TestCreateFile(t *testing.T) { t.Run("nonexistent", func(t *testing.T) { - if err := createFile(path.Join(Nonexistent, ":3"), 0644, 0755, nil); !errors.Is(err, wrapErrSelf(&os.PathError{ - Op: "mkdir", - Path: "/proc/nonexistent", - Err: syscall.ENOENT, - })) { - t.Errorf("createFile: error = %v", err) - } - if err := createFile(path.Join(Nonexistent), 0644, 0755, nil); !errors.Is(err, wrapErrSelf(&os.PathError{ - Op: "open", - Path: "/proc/nonexistent", - Err: syscall.ENOENT, - })) { - t.Errorf("createFile: error = %v", err) - } + t.Run("mkdir", func(t *testing.T) { + wantErr := &os.PathError{ + Op: "mkdir", + Path: "/proc/nonexistent", + Err: syscall.ENOENT, + } + if err := createFile(path.Join(Nonexistent, ":3"), 0644, 0755, nil); !reflect.DeepEqual(err, wantErr) { + t.Errorf("createFile: error = %#v, want %#v", err, wantErr) + } + }) + + t.Run("open", func(t *testing.T) { + wantErr := &os.PathError{ + Op: "open", + Path: "/proc/nonexistent", + Err: syscall.ENOENT, + } + if err := createFile(path.Join(Nonexistent), 0644, 0755, nil); !reflect.DeepEqual(err, wantErr) { + t.Errorf("createFile: error = %#v, want %#v", err, wantErr) + } + }) }) t.Run("touch", func(t *testing.T) { @@ -120,13 +126,13 @@ func TestEnsureFile(t *testing.T) { t.Fatalf("Chmod: error = %v", err) } - wantErr := wrapErrSelf(&os.PathError{ + wantErr := &os.PathError{ Op: "stat", Path: pathname, Err: syscall.EACCES, - }) - if err := ensureFile(pathname, 0644, 0755); !errors.Is(err, wantErr) { - t.Errorf("ensureFile: error = %v, want %v", err, wantErr) + } + if err := ensureFile(pathname, 0644, 0755); !reflect.DeepEqual(err, wantErr) { + t.Errorf("ensureFile: error = %#v, want %#v", err, wantErr) } if err := os.Chmod(tempDir, 0755); err != nil { @@ -136,9 +142,9 @@ func TestEnsureFile(t *testing.T) { t.Run("directory", func(t *testing.T) { pathname := t.TempDir() - wantErr := msg.WrapErr(syscall.EISDIR, fmt.Sprintf("path %q is a directory", pathname)) - if err := ensureFile(pathname, 0644, 0755); !errors.Is(err, wantErr) { - t.Errorf("ensureFile: error = %v, want %v", err, wantErr) + wantErr := &os.PathError{Op: "ensure", Path: pathname, Err: syscall.EISDIR} + if err := ensureFile(pathname, 0644, 0755); !reflect.DeepEqual(err, wantErr) { + t.Errorf("ensureFile: error = %#v, want %#v", err, wantErr) } }) @@ -177,12 +183,12 @@ func TestProcPaths(t *testing.T) { t.Run("mountinfo", func(t *testing.T) { t.Run("nonexistent", func(t *testing.T) { nonexistentProc := newProcPaths(direct{}, t.TempDir()) - wantErr := wrapErrSelf(&os.PathError{ + wantErr := &os.PathError{ Op: "open", Path: nonexistentProc.self + "/mountinfo", Err: syscall.ENOENT, - }) - if err := nonexistentProc.mountinfo(func(*vfs.MountInfoDecoder) error { return syscall.EINVAL }); !errors.Is(err, wantErr) { + } + if err := nonexistentProc.mountinfo(func(*vfs.MountInfoDecoder) error { return syscall.EINVAL }); !reflect.DeepEqual(err, wantErr) { t.Errorf("mountinfo: error = %v, want %v", err, wantErr) } }) @@ -217,11 +223,11 @@ func TestProcPaths(t *testing.T) { t.Run("closed", func(t *testing.T) { p := newProcPaths(direct{}, tempDir) - wantErr := wrapErrSelf(&os.PathError{ + wantErr := &os.PathError{ Op: "close", Path: p.self + "/mountinfo", Err: os.ErrClosed, - }) + } if err := p.mountinfo(func(d *vfs.MountInfoDecoder) error { v := reflect.ValueOf(d).Elem().FieldByName("s").Elem().FieldByName("r") v = reflect.NewAt(v.Type(), unsafe.Pointer(v.UnsafeAddr())) @@ -231,8 +237,8 @@ func TestProcPaths(t *testing.T) { } else { return f.Close() } - }); !errors.Is(err, wantErr) { - t.Errorf("mountinfo: error = %v, want %v", err, wantErr) + }); !reflect.DeepEqual(err, wantErr) { + t.Errorf("mountinfo: error = %#v, want %#v", err, wantErr) } })