system: enforce absolute paths
All checks were successful
Test / Create distribution (push) Successful in 1m17s
Test / Sandbox (push) Successful in 2m56s
Test / Hakurei (push) Successful in 3m54s
Test / Hpkg (push) Successful in 4m51s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 6m0s
Test / Flake checks (push) Successful in 1m38s

This is less error-prone, and is quite easy to integrate considering internal/app has already migrated to container.Absolute.

Closes #11.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-10-03 02:26:14 +09:00
parent e58181a930
commit d16da6da8c
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
15 changed files with 125 additions and 117 deletions

View File

@ -1,7 +1,6 @@
package app package app
import ( import (
"context"
"encoding/json" "encoding/json"
"io/fs" "io/fs"
"os" "os"
@ -37,12 +36,12 @@ func TestApp(t *testing.T) {
0xbd, 0x01, 0x78, 0x0e, 0xbd, 0x01, 0x78, 0x0e,
0xb9, 0xa6, 0x07, 0xac, 0xb9, 0xa6, 0x07, 0xac,
}, },
system.New(context.TODO(), container.NewMsg(nil), 1000000). system.New(t.Context(), container.NewMsg(nil), 1000000).
Ensure("/tmp/hakurei.0", 0711). Ensure(m("/tmp/hakurei.0"), 0711).
Ensure("/tmp/hakurei.0/runtime", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/runtime", acl.Execute). Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
Ensure("/tmp/hakurei.0/runtime/0", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/runtime/0", acl.Read, acl.Write, acl.Execute). Ensure(m("/tmp/hakurei.0/runtime/0"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/0"), acl.Read, acl.Write, acl.Execute).
Ensure("/tmp/hakurei.0/tmpdir", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/tmpdir", acl.Execute). Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
Ensure("/tmp/hakurei.0/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/hakurei.0/tmpdir/0", acl.Read, acl.Write, acl.Execute), Ensure(m("/tmp/hakurei.0/tmpdir/0"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/0"), acl.Read, acl.Write, acl.Execute),
&container.Params{ &container.Params{
Dir: m("/home/chronos"), Dir: m("/home/chronos"),
Path: m("/run/current-system/sw/bin/zsh"), Path: m("/run/current-system/sw/bin/zsh"),
@ -129,20 +128,20 @@ func TestApp(t *testing.T) {
0x82, 0xd4, 0x13, 0x36, 0x82, 0xd4, 0x13, 0x36,
0x9b, 0x64, 0xce, 0x7c, 0x9b, 0x64, 0xce, 0x7c,
}, },
system.New(context.TODO(), container.NewMsg(nil), 1000009). system.New(t.Context(), container.NewMsg(nil), 1000009).
Ensure("/tmp/hakurei.0", 0711). Ensure(m("/tmp/hakurei.0"), 0711).
Ensure("/tmp/hakurei.0/runtime", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/runtime", acl.Execute). Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
Ensure("/tmp/hakurei.0/runtime/9", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/runtime/9", acl.Read, acl.Write, acl.Execute). Ensure(m("/tmp/hakurei.0/runtime/9"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/9"), acl.Read, acl.Write, acl.Execute).
Ensure("/tmp/hakurei.0/tmpdir", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/tmpdir", acl.Execute). Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
Ensure("/tmp/hakurei.0/tmpdir/9", 01700).UpdatePermType(system.User, "/tmp/hakurei.0/tmpdir/9", acl.Read, acl.Write, acl.Execute). Ensure(m("/tmp/hakurei.0/tmpdir/9"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/9"), acl.Read, acl.Write, acl.Execute).
Ephemeral(system.Process, "/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c", 0711). Ephemeral(system.Process, m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c"), 0711).
Wayland(new(*os.File), "/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland", "/run/user/1971/wayland-0", "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c"). Wayland(new(*os.File), m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/wayland"), m("/run/user/1971/wayland-0"), "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
Ensure("/run/user/1971/hakurei", 0700).UpdatePermType(system.User, "/run/user/1971/hakurei", acl.Execute). Ensure(m("/run/user/1971/hakurei"), 0700).UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset Ensure(m("/run/user/1971"), 0700).UpdatePermType(system.User, m("/run/user/1971"), acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
Ephemeral(system.Process, "/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c", acl.Execute). Ephemeral(system.Process, m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c"), 0700).UpdatePermType(system.Process, m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c"), acl.Execute).
Link("/run/user/1971/pulse/native", "/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse"). Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse")).
CopyFile(new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 256, 256). CopyFile(new([]byte), m("/home/ophestra/xdg/config/pulse/cookie"), 256, 256).
MustProxyDBus("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus", &dbus.Config{ MustProxyDBus(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), &dbus.Config{
Talk: []string{ Talk: []string{
"org.freedesktop.Notifications", "org.freedesktop.Notifications",
"org.freedesktop.FileManager1", "org.freedesktop.FileManager1",
@ -164,7 +163,7 @@ func TestApp(t *testing.T) {
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*", "org.freedesktop.portal.*": "@/org/freedesktop/portal/*",
}, },
Filter: true, Filter: true,
}, "/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket", &dbus.Config{ }, m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), &dbus.Config{
Talk: []string{ Talk: []string{
"org.bluez", "org.bluez",
"org.freedesktop.Avahi", "org.freedesktop.Avahi",
@ -172,8 +171,8 @@ func TestApp(t *testing.T) {
}, },
Filter: true, Filter: true,
}). }).
UpdatePerm("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus", acl.Read, acl.Write). UpdatePerm(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/bus"), acl.Read, acl.Write).
UpdatePerm("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket", acl.Read, acl.Write), UpdatePerm(m("/tmp/hakurei.0/ebf083d1b175911782d413369b64ce7c/system_bus_socket"), acl.Read, acl.Write),
&container.Params{ &container.Params{
Dir: m("/home/chronos"), Dir: m("/home/chronos"),
Path: m("/run/current-system/sw/bin/zsh"), Path: m("/run/current-system/sw/bin/zsh"),
@ -280,20 +279,20 @@ func TestApp(t *testing.T) {
0x4c, 0xf0, 0x73, 0xbd, 0x4c, 0xf0, 0x73, 0xbd,
0xb4, 0x6e, 0xb5, 0xc1, 0xb4, 0x6e, 0xb5, 0xc1,
}, },
system.New(context.TODO(), container.NewMsg(nil), 1000001). system.New(t.Context(), container.NewMsg(nil), 1000001).
Ensure("/tmp/hakurei.0", 0711). Ensure(m("/tmp/hakurei.0"), 0711).
Ensure("/tmp/hakurei.0/runtime", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/runtime", acl.Execute). Ensure(m("/tmp/hakurei.0/runtime"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime"), acl.Execute).
Ensure("/tmp/hakurei.0/runtime/1", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/runtime/1", acl.Read, acl.Write, acl.Execute). Ensure(m("/tmp/hakurei.0/runtime/1"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/runtime/1"), acl.Read, acl.Write, acl.Execute).
Ensure("/tmp/hakurei.0/tmpdir", 0700).UpdatePermType(system.User, "/tmp/hakurei.0/tmpdir", acl.Execute). Ensure(m("/tmp/hakurei.0/tmpdir"), 0700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir"), acl.Execute).
Ensure("/tmp/hakurei.0/tmpdir/1", 01700).UpdatePermType(system.User, "/tmp/hakurei.0/tmpdir/1", acl.Read, acl.Write, acl.Execute). Ensure(m("/tmp/hakurei.0/tmpdir/1"), 01700).UpdatePermType(system.User, m("/tmp/hakurei.0/tmpdir/1"), acl.Read, acl.Write, acl.Execute).
Ensure("/run/user/1971/hakurei", 0700).UpdatePermType(system.User, "/run/user/1971/hakurei", acl.Execute). Ensure(m("/run/user/1971/hakurei"), 0700).UpdatePermType(system.User, m("/run/user/1971/hakurei"), acl.Execute).
Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset Ensure(m("/run/user/1971"), 0700).UpdatePermType(system.User, m("/run/user/1971"), acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
UpdatePermType(hst.EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute). UpdatePermType(hst.EWayland, m("/run/user/1971/wayland-0"), acl.Read, acl.Write, acl.Execute).
Ephemeral(system.Process, "/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute). Ephemeral(system.Process, m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1"), 0700).UpdatePermType(system.Process, m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1"), acl.Execute).
Link("/run/user/1971/pulse/native", "/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse"). Link(m("/run/user/1971/pulse/native"), m("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse")).
CopyFile(nil, "/home/ophestra/xdg/config/pulse/cookie", 256, 256). CopyFile(nil, m("/home/ophestra/xdg/config/pulse/cookie"), 256, 256).
Ephemeral(system.Process, "/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1", 0711). Ephemeral(system.Process, m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1"), 0711).
MustProxyDBus("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus", &dbus.Config{ MustProxyDBus(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), &dbus.Config{
Talk: []string{ Talk: []string{
"org.freedesktop.FileManager1", "org.freedesktop.Notifications", "org.freedesktop.FileManager1", "org.freedesktop.Notifications",
"org.freedesktop.ScreenSaver", "org.freedesktop.secrets", "org.freedesktop.ScreenSaver", "org.freedesktop.secrets",
@ -306,7 +305,7 @@ func TestApp(t *testing.T) {
}, },
Call: map[string]string{}, Broadcast: map[string]string{}, Call: map[string]string{}, Broadcast: map[string]string{},
Filter: true, Filter: true,
}, "/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", &dbus.Config{ }, m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), &dbus.Config{
Talk: []string{ Talk: []string{
"org.bluez", "org.bluez",
"org.freedesktop.Avahi", "org.freedesktop.Avahi",
@ -314,8 +313,8 @@ func TestApp(t *testing.T) {
}, },
Filter: true, Filter: true,
}). }).
UpdatePerm("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus", acl.Read, acl.Write). UpdatePerm(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/bus"), acl.Read, acl.Write).
UpdatePerm("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", acl.Read, acl.Write), UpdatePerm(m("/tmp/hakurei.0/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket"), acl.Read, acl.Write),
&container.Params{ &container.Params{
Uid: 1971, Uid: 1971,
Gid: 100, Gid: 100,

View File

@ -76,10 +76,10 @@ func (share *shareHost) ensureRuntimeDir() {
return return
} }
share.useRuntimeDir = true share.useRuntimeDir = true
share.seal.sys.Ensure(share.sc.RunDirPath.String(), 0700) share.seal.sys.Ensure(share.sc.RunDirPath, 0700)
share.seal.sys.UpdatePermType(system.User, share.sc.RunDirPath.String(), acl.Execute) share.seal.sys.UpdatePermType(system.User, share.sc.RunDirPath, acl.Execute)
share.seal.sys.Ensure(share.sc.RuntimePath.String(), 0700) // ensure this dir in case XDG_RUNTIME_DIR is unset share.seal.sys.Ensure(share.sc.RuntimePath, 0700) // ensure this dir in case XDG_RUNTIME_DIR is unset
share.seal.sys.UpdatePermType(system.User, share.sc.RuntimePath.String(), acl.Execute) share.seal.sys.UpdatePermType(system.User, share.sc.RuntimePath, acl.Execute)
} }
// instance returns a process-specific share path within tmpdir // instance returns a process-specific share path within tmpdir
@ -88,7 +88,7 @@ func (share *shareHost) instance() *container.Absolute {
return share.sharePath return share.sharePath
} }
share.sharePath = share.sc.SharePath.Append(share.seal.id.String()) share.sharePath = share.sc.SharePath.Append(share.seal.id.String())
share.seal.sys.Ephemeral(system.Process, share.sharePath.String(), 0711) share.seal.sys.Ephemeral(system.Process, share.sharePath, 0711)
return share.sharePath return share.sharePath
} }
@ -99,8 +99,8 @@ func (share *shareHost) runtime() *container.Absolute {
} }
share.ensureRuntimeDir() share.ensureRuntimeDir()
share.runtimeSharePath = share.sc.RunDirPath.Append(share.seal.id.String()) share.runtimeSharePath = share.sc.RunDirPath.Append(share.seal.id.String())
share.seal.sys.Ephemeral(system.Process, share.runtimeSharePath.String(), 0700) share.seal.sys.Ephemeral(system.Process, share.runtimeSharePath, 0700)
share.seal.sys.UpdatePerm(share.runtimeSharePath.String(), acl.Execute) share.seal.sys.UpdatePerm(share.runtimeSharePath, acl.Execute)
return share.runtimeSharePath return share.runtimeSharePath
} }
@ -308,26 +308,26 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
k.runDirPath = share.sc.RunDirPath k.runDirPath = share.sc.RunDirPath
k.sys = system.New(k.ctx, msg, k.user.uid.unwrap()) k.sys = system.New(k.ctx, msg, k.user.uid.unwrap())
k.sys.Ensure(share.sc.SharePath.String(), 0711) k.sys.Ensure(share.sc.SharePath, 0711)
{ {
runtimeDir := share.sc.SharePath.Append("runtime") runtimeDir := share.sc.SharePath.Append("runtime")
k.sys.Ensure(runtimeDir.String(), 0700) k.sys.Ensure(runtimeDir, 0700)
k.sys.UpdatePermType(system.User, runtimeDir.String(), acl.Execute) k.sys.UpdatePermType(system.User, runtimeDir, acl.Execute)
runtimeDirInst := runtimeDir.Append(k.user.identity.String()) runtimeDirInst := runtimeDir.Append(k.user.identity.String())
k.sys.Ensure(runtimeDirInst.String(), 0700) k.sys.Ensure(runtimeDirInst, 0700)
k.sys.UpdatePermType(system.User, runtimeDirInst.String(), acl.Read, acl.Write, acl.Execute) k.sys.UpdatePermType(system.User, runtimeDirInst, acl.Read, acl.Write, acl.Execute)
k.container.Tmpfs(container.AbsFHSRunUser, 1<<12, 0755) k.container.Tmpfs(container.AbsFHSRunUser, 1<<12, 0755)
k.container.Bind(runtimeDirInst, innerRuntimeDir, container.BindWritable) k.container.Bind(runtimeDirInst, innerRuntimeDir, container.BindWritable)
} }
{ {
tmpdir := share.sc.SharePath.Append("tmpdir") tmpdir := share.sc.SharePath.Append("tmpdir")
k.sys.Ensure(tmpdir.String(), 0700) k.sys.Ensure(tmpdir, 0700)
k.sys.UpdatePermType(system.User, tmpdir.String(), acl.Execute) k.sys.UpdatePermType(system.User, tmpdir, acl.Execute)
tmpdirInst := tmpdir.Append(k.user.identity.String()) tmpdirInst := tmpdir.Append(k.user.identity.String())
k.sys.Ensure(tmpdirInst.String(), 01700) k.sys.Ensure(tmpdirInst, 01700)
k.sys.UpdatePermType(system.User, tmpdirInst.String(), acl.Read, acl.Write, acl.Execute) k.sys.UpdatePermType(system.User, tmpdirInst, acl.Read, acl.Write, acl.Execute)
// mount inner /tmp from share so it shares persistence and storage behaviour of host /tmp // mount inner /tmp from share so it shares persistence and storage behaviour of host /tmp
k.container.Bind(tmpdirInst, container.AbsFHSTmp, container.BindWritable) k.container.Bind(tmpdirInst, container.AbsFHSTmp, container.BindWritable)
} }
@ -376,13 +376,13 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
} }
// downstream socket paths // downstream socket paths
outerPath := share.instance().Append("wayland") outerPath := share.instance().Append("wayland")
k.sys.Wayland(&k.sync, outerPath.String(), socketPath.String(), appID, k.id.String()) k.sys.Wayland(&k.sync, outerPath, socketPath, appID, k.id.String())
k.container.Bind(outerPath, innerPath, 0) k.container.Bind(outerPath, innerPath, 0)
} else { // bind mount wayland socket (insecure) } else { // bind mount wayland socket (insecure)
msg.Verbose("direct wayland access, PROCEED WITH CAUTION") msg.Verbose("direct wayland access, PROCEED WITH CAUTION")
share.ensureRuntimeDir() share.ensureRuntimeDir()
k.container.Bind(socketPath, innerPath, 0) k.container.Bind(socketPath, innerPath, 0)
k.sys.UpdatePermType(hst.EWayland, socketPath.String(), acl.Read, acl.Write, acl.Execute) k.sys.UpdatePermType(hst.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
} }
} }
@ -410,7 +410,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
return &hst.AppError{Step: fmt.Sprintf("access X11 socket %q", socketPath), Err: err} return &hst.AppError{Step: fmt.Sprintf("access X11 socket %q", socketPath), Err: err}
} }
} else { } else {
k.sys.UpdatePermType(hst.EX11, socketPath.String(), acl.Read, acl.Write, acl.Execute) k.sys.UpdatePermType(hst.EX11, socketPath, acl.Read, acl.Write, acl.Execute)
if !config.Container.HostAbstract { if !config.Container.HostAbstract {
d = "unix:" + socketPath.String() d = "unix:" + socketPath.String()
} }
@ -450,7 +450,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
// hard link pulse socket into target-executable share // hard link pulse socket into target-executable share
innerPulseRuntimeDir := share.runtime().Append("pulse") innerPulseRuntimeDir := share.runtime().Append("pulse")
innerPulseSocket := innerRuntimeDir.Append("pulse", "native") innerPulseSocket := innerRuntimeDir.Append("pulse", "native")
k.sys.Link(pulseSocket.String(), innerPulseRuntimeDir.String()) k.sys.Link(pulseSocket, innerPulseRuntimeDir)
k.container.Bind(innerPulseRuntimeDir, innerPulseSocket, 0) k.container.Bind(innerPulseRuntimeDir, innerPulseSocket, 0)
k.env[pulseServer] = "unix:" + innerPulseSocket.String() k.env[pulseServer] = "unix:" + innerPulseSocket.String()
@ -518,7 +518,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
k.env[pulseCookie] = innerDst.String() k.env[pulseCookie] = innerDst.String()
var payload *[]byte var payload *[]byte
k.container.PlaceP(innerDst, &payload) k.container.PlaceP(innerDst, &payload)
k.sys.CopyFile(payload, paCookiePath.String(), 256, 256) k.sys.CopyFile(payload, paCookiePath, 256, 256)
} else { } else {
msg.Verbose("cannot locate PulseAudio cookie (tried " + msg.Verbose("cannot locate PulseAudio cookie (tried " +
"$PULSE_COOKIE, " + "$PULSE_COOKIE, " +
@ -539,7 +539,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
// configure dbus proxy // configure dbus proxy
if f, err := k.sys.ProxyDBus( if f, err := k.sys.ProxyDBus(
config.SessionBus, config.SystemBus, config.SessionBus, config.SystemBus,
sessionPath.String(), systemPath.String(), sessionPath, systemPath,
); err != nil { ); err != nil {
return err return err
} else { } else {
@ -550,12 +550,12 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
sessionInner := innerRuntimeDir.Append("bus") sessionInner := innerRuntimeDir.Append("bus")
k.env[dbusSessionBusAddress] = "unix:path=" + sessionInner.String() k.env[dbusSessionBusAddress] = "unix:path=" + sessionInner.String()
k.container.Bind(sessionPath, sessionInner, 0) k.container.Bind(sessionPath, sessionInner, 0)
k.sys.UpdatePerm(sessionPath.String(), acl.Read, acl.Write) k.sys.UpdatePerm(sessionPath, acl.Read, acl.Write)
if config.SystemBus != nil { if config.SystemBus != nil {
systemInner := container.AbsFHSRun.Append("dbus/system_bus_socket") systemInner := container.AbsFHSRun.Append("dbus/system_bus_socket")
k.env[dbusSystemBusAddress] = "unix:path=" + systemInner.String() k.env[dbusSystemBusAddress] = "unix:path=" + systemInner.String()
k.container.Bind(systemPath, systemInner, 0) k.container.Bind(systemPath, systemInner, 0)
k.sys.UpdatePerm(systemPath.String(), acl.Read, acl.Write) k.sys.UpdatePerm(systemPath, acl.Read, acl.Write)
} }
} }
@ -569,7 +569,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
} }
if p.Ensure { if p.Ensure {
k.sys.Ensure(p.Path.String(), 0700) k.sys.Ensure(p.Path, 0700)
} }
perms := make(acl.Perms, 0, 3) perms := make(acl.Perms, 0, 3)
@ -582,7 +582,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, config *hst.C
if p.Execute { if p.Execute {
perms = append(perms, acl.Execute) perms = append(perms, acl.Execute)
} }
k.sys.UpdatePermType(system.User, p.Path.String(), perms...) k.sys.UpdatePermType(system.User, p.Path, perms...)
} }
// flatten and sort env for deterministic behaviour // flatten and sort env for deterministic behaviour

View File

@ -6,19 +6,20 @@ import (
"os" "os"
"slices" "slices"
"hakurei.app/container"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system/acl" "hakurei.app/system/acl"
) )
// UpdatePerm calls UpdatePermType with the [Process] criteria. // UpdatePerm calls UpdatePermType with the [Process] criteria.
func (sys *I) UpdatePerm(path string, perms ...acl.Perm) *I { func (sys *I) UpdatePerm(path *container.Absolute, perms ...acl.Perm) *I {
sys.UpdatePermType(Process, path, perms...) sys.UpdatePermType(Process, path, perms...)
return sys return sys
} }
// UpdatePermType maintains [acl.Perms] on a file until its [Enablement] is no longer satisfied. // UpdatePermType maintains [acl.Perms] on a file until its [Enablement] is no longer satisfied.
func (sys *I) UpdatePermType(et hst.Enablement, path string, perms ...acl.Perm) *I { func (sys *I) UpdatePermType(et hst.Enablement, path *container.Absolute, perms ...acl.Perm) *I {
sys.ops = append(sys.ops, &aclUpdateOp{et, path, perms}) sys.ops = append(sys.ops, &aclUpdateOp{et, path.String(), perms})
return sys return sys
} }

View File

@ -60,42 +60,42 @@ func TestACLUpdateOp(t *testing.T) {
0xdeadbeef, 0xdeadbeef,
func(_ *testing.T, sys *I) { func(_ *testing.T, sys *I) {
sys. sys.
UpdatePerm("/run/user/1971/hakurei", acl.Execute). UpdatePerm(m("/run/user/1971/hakurei"), acl.Execute).
UpdatePerm("/tmp/hakurei.0/tmpdir/150", acl.Read, acl.Write, acl.Execute) UpdatePerm(m("/tmp/hakurei.0/tmpdir/150"), acl.Read, acl.Write, acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{Process, "/run/user/1971/hakurei", []acl.Perm{acl.Execute}}, &aclUpdateOp{Process, "/run/user/1971/hakurei", []acl.Perm{acl.Execute}},
&aclUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, &aclUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"tmpdirp", 0xdeadbeef, func(_ *testing.T, sys *I) { {"tmpdirp", 0xdeadbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(User, "/tmp/hakurei.0/tmpdir", acl.Execute) sys.UpdatePermType(User, m("/tmp/hakurei.0/tmpdir"), acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{User, "/tmp/hakurei.0/tmpdir", []acl.Perm{acl.Execute}}, &aclUpdateOp{User, "/tmp/hakurei.0/tmpdir", []acl.Perm{acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"tmpdir", 0xdeadbeef, func(_ *testing.T, sys *I) { {"tmpdir", 0xdeadbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(User, "/tmp/hakurei.0/tmpdir/150", acl.Read, acl.Write, acl.Execute) sys.UpdatePermType(User, m("/tmp/hakurei.0/tmpdir/150"), acl.Read, acl.Write, acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{User, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, &aclUpdateOp{User, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"share", 0xdeadbeef, func(_ *testing.T, sys *I) { {"share", 0xdeadbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", acl.Execute) sys.UpdatePermType(Process, m("/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5"), acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", []acl.Perm{acl.Execute}}, &aclUpdateOp{Process, "/run/user/1971/hakurei/fcb8a12f7c482d183ade8288c3de78b5", []acl.Perm{acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},
{"passwd", 0xdeadbeef, func(_ *testing.T, sys *I) { {"passwd", 0xdeadbeef, func(_ *testing.T, sys *I) {
sys. sys.
UpdatePermType(Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd", acl.Read). UpdatePermType(Process, m("/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd"), acl.Read).
UpdatePermType(Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", acl.Read) UpdatePermType(Process, m("/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group"), acl.Read)
}, []Op{ }, []Op{
&aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd", []acl.Perm{acl.Read}}, &aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/passwd", []acl.Perm{acl.Read}},
&aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", []acl.Perm{acl.Read}}, &aclUpdateOp{Process, "/tmp/hakurei.0/fcb8a12f7c482d183ade8288c3de78b5/group", []acl.Perm{acl.Read}},
}, stub.Expect{}}, }, stub.Expect{}},
{"wayland", 0xdeadbeef, func(_ *testing.T, sys *I) { {"wayland", 0xdeadbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(hst.EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute) sys.UpdatePermType(hst.EWayland, m("/run/user/1971/wayland-0"), acl.Read, acl.Write, acl.Execute)
}, []Op{ }, []Op{
&aclUpdateOp{hst.EWayland, "/run/user/1971/wayland-0", []acl.Perm{acl.Read, acl.Write, acl.Execute}}, &aclUpdateOp{hst.EWayland, "/run/user/1971/wayland-0", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
}, stub.Expect{}}, }, stub.Expect{}},

View File

@ -21,7 +21,7 @@ var (
) )
// MustProxyDBus calls ProxyDBus and panics if an error is returned. // MustProxyDBus calls ProxyDBus and panics if an error is returned.
func (sys *I) MustProxyDBus(sessionPath string, session *dbus.Config, systemPath string, system *dbus.Config) *I { func (sys *I) MustProxyDBus(sessionPath *container.Absolute, session *dbus.Config, systemPath *container.Absolute, system *dbus.Config) *I {
if _, err := sys.ProxyDBus(session, system, sessionPath, systemPath); err != nil { if _, err := sys.ProxyDBus(session, system, sessionPath, systemPath); err != nil {
panic(err.Error()) panic(err.Error())
} else { } else {
@ -31,7 +31,7 @@ func (sys *I) MustProxyDBus(sessionPath string, session *dbus.Config, systemPath
// ProxyDBus finalises configuration ahead of time and starts xdg-dbus-proxy via [dbus] and terminates it on revert. // ProxyDBus finalises configuration ahead of time and starts xdg-dbus-proxy via [dbus] and terminates it on revert.
// This [Op] is always [Process] scoped. // This [Op] is always [Process] scoped.
func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath string) (func(), error) { func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath *container.Absolute) (func(), error) {
d := new(dbusProxyOp) d := new(dbusProxyOp)
// session bus is required as otherwise this is effectively a very expensive noop // session bus is required as otherwise this is effectively a very expensive noop
@ -45,7 +45,7 @@ func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath st
var sessionBus, systemBus dbus.ProxyPair var sessionBus, systemBus dbus.ProxyPair
sessionBus[0], systemBus[0] = sys.dbusAddress() sessionBus[0], systemBus[0] = sys.dbusAddress()
sessionBus[1], systemBus[1] = sessionPath, systemPath sessionBus[1], systemBus[1] = sessionPath.String(), systemPath.String()
d.out = &linePrefixWriter{println: log.Println, prefix: "(dbus) ", buf: new(strings.Builder)} d.out = &linePrefixWriter{println: log.Println, prefix: "(dbus) ", buf: new(strings.Builder)}
if final, err := sys.dbusFinalise(sessionBus, systemBus, session, system); err != nil { if final, err := sys.dbusFinalise(sessionBus, systemBus, session, system); err != nil {
if errors.Is(err, syscall.EINVAL) { if errors.Is(err, syscall.EINVAL) {

View File

@ -82,7 +82,7 @@ func TestDBusProxyOp(t *testing.T) {
Op: "dbus", Err: ErrDBusConfig, Op: "dbus", Err: ErrDBusConfig,
Msg: "attempted to create message bus proxy args without session bus config", Msg: "attempted to create message bus proxy args without session bus config",
} }
if f, err := sys.ProxyDBus(nil, new(dbus.Config), "", ""); !reflect.DeepEqual(err, wantErr) { if f, err := sys.ProxyDBus(nil, new(dbus.Config), nil, nil); !reflect.DeepEqual(err, wantErr) {
t.Errorf("ProxyDBus: error = %v, want %v", err, wantErr) t.Errorf("ProxyDBus: error = %v, want %v", err, wantErr)
} else if f != nil { } else if f != nil {
t.Errorf("ProxyDBus: f = %p", f) t.Errorf("ProxyDBus: f = %p", f)
@ -98,10 +98,10 @@ func TestDBusProxyOp(t *testing.T) {
}() }()
sys.MustProxyDBus( sys.MustProxyDBus(
"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus", &dbus.Config{ m("/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus"), &dbus.Config{
// use impossible value here as an implicit assert that it goes through the stub // use impossible value here as an implicit assert that it goes through the stub
Talk: []string{"session\x00"}, Filter: true, Talk: []string{"session\x00"}, Filter: true,
}, "/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/system_bus_socket", &dbus.Config{ }, m("/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/system_bus_socket"), &dbus.Config{
// use impossible value here as an implicit assert that it goes through the stub // use impossible value here as an implicit assert that it goes through the stub
Talk: []string{"system\x00"}, Filter: true, Talk: []string{"system\x00"}, Filter: true,
}) })
@ -128,8 +128,8 @@ func TestDBusProxyOp(t *testing.T) {
// use impossible value here as an implicit assert that it goes through the stub // use impossible value here as an implicit assert that it goes through the stub
Talk: []string{"system\x00"}, Filter: true, Talk: []string{"system\x00"}, Filter: true,
}, },
"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus", m("/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus"),
"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/system_bus_socket"); !reflect.DeepEqual(err, wantErr) { m("/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/system_bus_socket")); !reflect.DeepEqual(err, wantErr) {
t.Errorf("ProxyDBus: error = %v", err) t.Errorf("ProxyDBus: error = %v", err)
} else if f != nil { } else if f != nil {
t.Errorf("ProxyDBus: f = %p", f) t.Errorf("ProxyDBus: f = %p", f)
@ -146,10 +146,10 @@ func TestDBusProxyOp(t *testing.T) {
{"full", 0xcafebabe, func(_ *testing.T, sys *I) { {"full", 0xcafebabe, func(_ *testing.T, sys *I) {
sys.MustProxyDBus( sys.MustProxyDBus(
"/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus", &dbus.Config{ m("/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/bus"), &dbus.Config{
// use impossible value here as an implicit assert that it goes through the stub // use impossible value here as an implicit assert that it goes through the stub
Talk: []string{"session\x00"}, Filter: true, Talk: []string{"session\x00"}, Filter: true,
}, "/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/system_bus_socket", &dbus.Config{ }, m("/tmp/hakurei.0/99dd71ee2146369514e0d10783368f8f/system_bus_socket"), &dbus.Config{
// use impossible value here as an implicit assert that it goes through the stub // use impossible value here as an implicit assert that it goes through the stub
Talk: []string{"system\x00"}, Filter: true, Talk: []string{"system\x00"}, Filter: true,
}) })

View File

@ -3,15 +3,18 @@ package system
import ( import (
"fmt" "fmt"
"hakurei.app/container"
"hakurei.app/hst" "hakurei.app/hst"
) )
// Link calls LinkFileType with the [Process] criteria. // Link calls LinkFileType with the [Process] criteria.
func (sys *I) Link(oldname, newname string) *I { return sys.LinkFileType(Process, oldname, newname) } func (sys *I) Link(oldname, newname *container.Absolute) *I {
return sys.LinkFileType(Process, oldname, newname)
}
// LinkFileType maintains a hardlink until its [Enablement] is no longer satisfied. // LinkFileType maintains a hardlink until its [Enablement] is no longer satisfied.
func (sys *I) LinkFileType(et hst.Enablement, oldname, newname string) *I { func (sys *I) LinkFileType(et hst.Enablement, oldname, newname *container.Absolute) *I {
sys.ops = append(sys.ops, &hardlinkOp{et, newname, oldname}) sys.ops = append(sys.ops, &hardlinkOp{et, newname.String(), oldname.String()})
return sys return sys
} }

View File

@ -40,13 +40,13 @@ func TestHardlinkOp(t *testing.T) {
checkOpsBuilder(t, "LinkFileType", []opsBuilderTestCase{ checkOpsBuilder(t, "LinkFileType", []opsBuilderTestCase{
{"type", 0xcafebabe, func(_ *testing.T, sys *I) { {"type", 0xcafebabe, func(_ *testing.T, sys *I) {
sys.LinkFileType(User, "/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse") sys.LinkFileType(User, m("/run/user/1000/pulse/native"), m("/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"))
}, []Op{ }, []Op{
&hardlinkOp{User, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, &hardlinkOp{User, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
}, stub.Expect{}}, }, stub.Expect{}},
{"link", 0xcafebabe, func(_ *testing.T, sys *I) { {"link", 0xcafebabe, func(_ *testing.T, sys *I) {
sys.Link("/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse") sys.Link(m("/run/user/1000/pulse/native"), m("/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"))
}, []Op{ }, []Op{
&hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
}, stub.Expect{}}, }, stub.Expect{}},

View File

@ -5,18 +5,19 @@ import (
"fmt" "fmt"
"os" "os"
"hakurei.app/container"
"hakurei.app/hst" "hakurei.app/hst"
) )
// Ensure ensures the existence of a directory. // Ensure ensures the existence of a directory.
func (sys *I) Ensure(name string, perm os.FileMode) *I { func (sys *I) Ensure(name *container.Absolute, perm os.FileMode) *I {
sys.ops = append(sys.ops, &mkdirOp{User, name, perm, false}) sys.ops = append(sys.ops, &mkdirOp{User, name.String(), perm, false})
return sys return sys
} }
// Ephemeral ensures the existence of a directory until its [Enablement] is no longer satisfied. // Ephemeral ensures the existence of a directory until its [Enablement] is no longer satisfied.
func (sys *I) Ephemeral(et hst.Enablement, name string, perm os.FileMode) *I { func (sys *I) Ephemeral(et hst.Enablement, name *container.Absolute, perm os.FileMode) *I {
sys.ops = append(sys.ops, &mkdirOp{et, name, perm, true}) sys.ops = append(sys.ops, &mkdirOp{et, name.String(), perm, true})
return sys return sys
} }

View File

@ -57,13 +57,13 @@ func TestMkdirOp(t *testing.T) {
checkOpsBuilder(t, "EnsureEphemeral", []opsBuilderTestCase{ checkOpsBuilder(t, "EnsureEphemeral", []opsBuilderTestCase{
{"ensure", 0xcafebabe, func(_ *testing.T, sys *I) { {"ensure", 0xcafebabe, func(_ *testing.T, sys *I) {
sys.Ensure("/tmp/hakurei.0", 0700) sys.Ensure(m("/tmp/hakurei.0"), 0700)
}, []Op{ }, []Op{
&mkdirOp{User, "/tmp/hakurei.0", 0700, false}, &mkdirOp{User, "/tmp/hakurei.0", 0700, false},
}, stub.Expect{}}, }, stub.Expect{}},
{"ephemeral", 0xcafebabe, func(_ *testing.T, sys *I) { {"ephemeral", 0xcafebabe, func(_ *testing.T, sys *I) {
sys.Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711) sys.Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711)
}, []Op{ }, []Op{
&mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}, &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true},
}, stub.Expect{}}, }, stub.Expect{}},

View File

@ -133,34 +133,34 @@ func TestEqual(t *testing.T) {
ChangeHosts("chronos"), ChangeHosts("chronos"),
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
Ensure("/run", 0755), Ensure(m("/run"), 0755),
false}, false},
{"op value mismatch", {"op value mismatch",
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
Ensure("/run", 0644), Ensure(m("/run"), 0644),
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
Ensure("/run", 0755), Ensure(m("/run"), 0755),
false}, false},
{"op type mismatch", {"op type mismatch",
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
CopyFile(new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 0, 256), CopyFile(new([]byte), m("/home/ophestra/xdg/config/pulse/cookie"), 0, 256),
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
Ensure("/run", 0755), Ensure(m("/run"), 0755),
false}, false},
{"op equals", {"op equals",
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
Ensure("/run", 0755), Ensure(m("/run"), 0755),
New(t.Context(), container.NewMsg(nil), 150). New(t.Context(), container.NewMsg(nil), 150).
ChangeHosts("chronos"). ChangeHosts("chronos").
Ensure("/run", 0755), Ensure(m("/run"), 0755),
true}, true},
} }
@ -187,7 +187,7 @@ func TestCommitRevert(t *testing.T) {
}{ }{
{"apply xhost partial mkdir", func(sys *I) { {"apply xhost partial mkdir", func(sys *I) {
sys. sys.
Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711).
ChangeHosts("chronos") ChangeHosts("chronos")
}, 0xff, []stub.Call{ }, 0xff, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
@ -202,7 +202,7 @@ func TestCommitRevert(t *testing.T) {
{"apply xhost", func(sys *I) { {"apply xhost", func(sys *I) {
sys. sys.
Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711).
ChangeHosts("chronos") ChangeHosts("chronos")
}, 0xff, []stub.Call{ }, 0xff, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
@ -216,7 +216,7 @@ func TestCommitRevert(t *testing.T) {
{"revert multi", func(sys *I) { {"revert multi", func(sys *I) {
sys. sys.
Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711).
ChangeHosts("chronos") ChangeHosts("chronos")
}, 0xff, []stub.Call{ }, 0xff, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
@ -234,7 +234,7 @@ func TestCommitRevert(t *testing.T) {
{"success", func(sys *I) { {"success", func(sys *I) {
sys. sys.
Ephemeral(Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711). Ephemeral(Process, m("/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9"), 0711).
ChangeHosts("chronos") ChangeHosts("chronos")
}, 0xff, []stub.Call{ }, 0xff, []stub.Call{
call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil), call("verbose", stub.ExpectArgs{[]any{"ensuring directory", &mkdirOp{Process, "/tmp/hakurei.0/f2f3bcd492d0266438fa9bf164fe90d9", 0711, true}}}, nil, nil),
@ -312,3 +312,5 @@ func TestNop(t *testing.T) {
new(noCopy).Unlock() new(noCopy).Unlock()
new(noCopy).Lock() new(noCopy).Lock()
} }
func m(pathname string) *container.Absolute { return container.MustAbs(pathname) }

View File

@ -8,14 +8,15 @@ import (
"os" "os"
"syscall" "syscall"
"hakurei.app/container"
"hakurei.app/hst" "hakurei.app/hst"
) )
// CopyFile reads up to n bytes from src and writes the resulting byte slice to payloadP. // CopyFile reads up to n bytes from src and writes the resulting byte slice to payloadP.
func (sys *I) CopyFile(payloadP *[]byte, src string, cap int, n int64) *I { func (sys *I) CopyFile(payloadP *[]byte, src *container.Absolute, cap int, n int64) *I {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.Grow(cap) buf.Grow(cap)
sys.ops = append(sys.ops, &tmpfileOp{payloadP, src, n, buf}) sys.ops = append(sys.ops, &tmpfileOp{payloadP, src.String(), n, buf})
return sys return sys
} }

View File

@ -98,7 +98,7 @@ func TestTmpfileOp(t *testing.T) {
checkOpsBuilder(t, "CopyFile", []opsBuilderTestCase{ checkOpsBuilder(t, "CopyFile", []opsBuilderTestCase{
{"pulse", 0xcafebabe, func(_ *testing.T, sys *I) { {"pulse", 0xcafebabe, func(_ *testing.T, sys *I) {
sys.CopyFile(new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 1<<8, 1<<8) sys.CopyFile(new([]byte), m("/home/ophestra/xdg/config/pulse/cookie"), 1<<8, 1<<8)
}, []Op{&tmpfileOp{ }, []Op{&tmpfileOp{
new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 1 << 8, new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 1 << 8,
func() *bytes.Buffer { buf := new(bytes.Buffer); buf.Grow(1 << 8); return buf }(), func() *bytes.Buffer { buf := new(bytes.Buffer); buf.Grow(1 << 8); return buf }(),

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"hakurei.app/container"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system/acl" "hakurei.app/system/acl"
"hakurei.app/system/wayland" "hakurei.app/system/wayland"
@ -19,8 +20,8 @@ type waylandConn interface {
// Wayland maintains a wayland socket with security-context-v1 attached via [wayland]. // Wayland maintains a wayland socket with security-context-v1 attached via [wayland].
// The socket stops accepting connections once the pipe referred to by sync is closed. // The socket stops accepting connections once the pipe referred to by sync is closed.
// The socket is pathname only and is destroyed on revert. // The socket is pathname only and is destroyed on revert.
func (sys *I) Wayland(syncFd **os.File, dst, src, appID, instanceID string) *I { func (sys *I) Wayland(syncFd **os.File, dst, src *container.Absolute, appID, instanceID string) *I {
sys.ops = append(sys.ops, &waylandOp{syncFd, dst, src, appID, instanceID, new(wayland.Conn)}) sys.ops = append(sys.ops, &waylandOp{syncFd, dst.String(), src.String(), appID, instanceID, new(wayland.Conn)})
return sys return sys
} }

View File

@ -218,8 +218,8 @@ func TestWaylandOp(t *testing.T) {
{"chromium", 0xcafe, func(_ *testing.T, sys *I) { {"chromium", 0xcafe, func(_ *testing.T, sys *I) {
sys.Wayland( sys.Wayland(
new(*os.File), new(*os.File),
"/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", m("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland"),
"/run/user/1971/wayland-0", m("/run/user/1971/wayland-0"),
"org.chromium.Chromium", "org.chromium.Chromium",
"ebf083d1b175911782d413369b64ce7c", "ebf083d1b175911782d413369b64ce7c",
) )