app: share path setup on demand
Some checks failed
Test / Create distribution (push) Successful in 20s
Test / Sandbox (push) Successful in 33s
Test / Sandbox (race detector) (push) Successful in 33s
Test / Fortify (push) Successful in 41s
Test / Fpkg (push) Successful in 38s
Test / Fortify (race detector) (push) Failing after 2m37s
Test / Flake checks (push) Has been skipped
Some checks failed
Test / Create distribution (push) Successful in 20s
Test / Sandbox (push) Successful in 33s
Test / Sandbox (race detector) (push) Successful in 33s
Test / Fortify (push) Successful in 41s
Test / Fpkg (push) Successful in 38s
Test / Fortify (race detector) (push) Failing after 2m37s
Test / Flake checks (push) Has been skipped
This removes the unnecessary creation and destruction of share paths when none of the enablements making use of them are set. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
4036da3b5c
commit
f13ee88b74
@ -56,15 +56,15 @@ var testCasesNixos = []sealTestCase{
|
||||
},
|
||||
system.New(1000001).
|
||||
Ensure("/tmp/fortify.1971", 0711).
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", 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
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1", 0711).
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir/1", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/1", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", 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
|
||||
UpdatePermType(system.EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute).
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute).
|
||||
Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse").
|
||||
CopyFile(nil, "/home/ophestra/xdg/config/pulse/cookie", 256, 256).
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1", 0711).
|
||||
MustProxyDBus("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", &dbus.Config{
|
||||
Talk: []string{
|
||||
"org.freedesktop.FileManager1", "org.freedesktop.Notifications",
|
||||
|
@ -28,10 +28,6 @@ var testCasesPd = []sealTestCase{
|
||||
},
|
||||
system.New(1000000).
|
||||
Ensure("/tmp/fortify.1971", 0711).
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", 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
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/4a450b6596d7bc15bd01780eb9a607ac", 0711).
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/4a450b6596d7bc15bd01780eb9a607ac", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute),
|
||||
&sandbox.Params{
|
||||
@ -207,16 +203,16 @@ var testCasesPd = []sealTestCase{
|
||||
},
|
||||
system.New(1000009).
|
||||
Ensure("/tmp/fortify.1971", 0711).
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", 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
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c", 0711).
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir/9", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/9", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/wayland", 0711).
|
||||
Wayland(new(*os.File), "/tmp/fortify.1971/wayland/ebf083d1b175911782d413369b64ce7c", "/run/user/1971/wayland-0", "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", 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
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", acl.Execute).
|
||||
Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse").
|
||||
CopyFile(new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 256, 256).
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c", 0711).
|
||||
MustProxyDBus("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", &dbus.Config{
|
||||
Talk: []string{
|
||||
"org.freedesktop.Notifications",
|
||||
|
@ -85,6 +85,53 @@ type outcome struct {
|
||||
f atomic.Bool
|
||||
}
|
||||
|
||||
// shareHost holds optional share directory state that must not be accessed directly
|
||||
type shareHost struct {
|
||||
// whether XDG_RUNTIME_DIR is used post fsu
|
||||
useRuntimeDir bool
|
||||
// process-specific directory in tmpdir, empty if unused
|
||||
sharePath string
|
||||
// process-specific directory in XDG_RUNTIME_DIR, empty if unused
|
||||
runtimeSharePath string
|
||||
|
||||
seal *outcome
|
||||
sc fst.Paths
|
||||
}
|
||||
|
||||
// ensureRuntimeDir must be called if direct access to paths within XDG_RUNTIME_DIR is required
|
||||
func (share *shareHost) ensureRuntimeDir() {
|
||||
if share.useRuntimeDir {
|
||||
return
|
||||
}
|
||||
share.useRuntimeDir = true
|
||||
share.seal.sys.Ensure(share.sc.RunDirPath, 0700)
|
||||
share.seal.sys.UpdatePermType(system.User, share.sc.RunDirPath, acl.Execute)
|
||||
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, acl.Execute)
|
||||
}
|
||||
|
||||
// instance returns a process-specific share path within tmpdir
|
||||
func (share *shareHost) instance() string {
|
||||
if share.sharePath != "" {
|
||||
return share.sharePath
|
||||
}
|
||||
share.sharePath = path.Join(share.sc.SharePath, share.seal.id.String())
|
||||
share.seal.sys.Ephemeral(system.Process, share.sharePath, 0711)
|
||||
return share.sharePath
|
||||
}
|
||||
|
||||
// runtime returns a process-specific share path within XDG_RUNTIME_DIR
|
||||
func (share *shareHost) runtime() string {
|
||||
if share.runtimeSharePath != "" {
|
||||
return share.runtimeSharePath
|
||||
}
|
||||
share.ensureRuntimeDir()
|
||||
share.runtimeSharePath = path.Join(share.sc.RunDirPath, share.seal.id.String())
|
||||
share.seal.sys.Ephemeral(system.Process, share.runtimeSharePath, 0700)
|
||||
share.seal.sys.UpdatePerm(share.runtimeSharePath, acl.Execute)
|
||||
return share.runtimeSharePath
|
||||
}
|
||||
|
||||
// fsuUser stores post-fsu credentials and metadata
|
||||
type fsuUser struct {
|
||||
// application id
|
||||
@ -254,36 +301,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Initialise externals
|
||||
*/
|
||||
|
||||
sc := sys.Paths()
|
||||
seal.runDirPath = sc.RunDirPath
|
||||
seal.sys = system.New(seal.user.uid.unwrap())
|
||||
|
||||
/*
|
||||
Work directories
|
||||
*/
|
||||
|
||||
// base fortify share path
|
||||
seal.sys.Ensure(sc.SharePath, 0711)
|
||||
|
||||
// outer paths used by the main process
|
||||
seal.sys.Ensure(sc.RunDirPath, 0700)
|
||||
seal.sys.UpdatePermType(system.User, sc.RunDirPath, acl.Execute)
|
||||
seal.sys.Ensure(sc.RuntimePath, 0700) // ensure this dir in case XDG_RUNTIME_DIR is unset
|
||||
seal.sys.UpdatePermType(system.User, sc.RuntimePath, acl.Execute)
|
||||
|
||||
// outer process-specific share directory
|
||||
sharePath := path.Join(sc.SharePath, seal.id.String())
|
||||
seal.sys.Ephemeral(system.Process, sharePath, 0711)
|
||||
// similar to share but within XDG_RUNTIME_DIR
|
||||
sharePathLocal := path.Join(sc.RunDirPath, seal.id.String())
|
||||
seal.sys.Ephemeral(system.Process, sharePathLocal, 0700)
|
||||
seal.sys.UpdatePerm(sharePathLocal, acl.Execute)
|
||||
|
||||
// inner XDG_RUNTIME_DIR default formatting of `/run/user/%d` as post-fsu user
|
||||
// inner XDG_RUNTIME_DIR default formatting of `/run/user/%d` as mapped uid
|
||||
innerRuntimeDir := path.Join("/run/user", mapuid.String())
|
||||
seal.container.Tmpfs("/run/user", 1<<12, 0755)
|
||||
seal.container.Tmpfs(innerRuntimeDir, 1<<23, 0700)
|
||||
@ -291,45 +309,44 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.env[xdgSessionClass] = "user"
|
||||
seal.env[xdgSessionType] = "tty"
|
||||
|
||||
// outer path for inner /tmp
|
||||
share := &shareHost{seal: seal, sc: sys.Paths()}
|
||||
seal.runDirPath = share.sc.RunDirPath
|
||||
seal.sys = system.New(seal.user.uid.unwrap())
|
||||
|
||||
{
|
||||
tmpdir := path.Join(sc.SharePath, "tmpdir")
|
||||
seal.sys.Ensure(share.sc.SharePath, 0711)
|
||||
tmpdir := path.Join(share.sc.SharePath, "tmpdir")
|
||||
seal.sys.Ensure(tmpdir, 0700)
|
||||
seal.sys.UpdatePermType(system.User, tmpdir, acl.Execute)
|
||||
tmpdirInst := path.Join(tmpdir, seal.user.aid.String())
|
||||
seal.sys.Ensure(tmpdirInst, 01700)
|
||||
seal.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
|
||||
seal.container.Bind(tmpdirInst, "/tmp", sandbox.BindWritable)
|
||||
}
|
||||
|
||||
/*
|
||||
Passwd database
|
||||
*/
|
||||
{
|
||||
homeDir := "/var/empty"
|
||||
if seal.user.home != "" {
|
||||
homeDir = seal.user.home
|
||||
}
|
||||
username := "chronos"
|
||||
if seal.user.username != "" {
|
||||
username = seal.user.username
|
||||
}
|
||||
seal.container.Bind(seal.user.data, homeDir, sandbox.BindWritable)
|
||||
seal.container.Dir = homeDir
|
||||
seal.env["HOME"] = homeDir
|
||||
seal.env["USER"] = username
|
||||
seal.env[shell] = config.Confinement.Shell
|
||||
|
||||
homeDir := "/var/empty"
|
||||
if seal.user.home != "" {
|
||||
homeDir = seal.user.home
|
||||
seal.container.Place("/etc/passwd",
|
||||
[]byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Confinement.Shell+"\n"))
|
||||
seal.container.Place("/etc/group",
|
||||
[]byte("fortify:x:"+mapgid.String()+":\n"))
|
||||
}
|
||||
username := "chronos"
|
||||
if seal.user.username != "" {
|
||||
username = seal.user.username
|
||||
}
|
||||
seal.container.Bind(seal.user.data, homeDir, sandbox.BindWritable)
|
||||
seal.container.Dir = homeDir
|
||||
seal.env["HOME"] = homeDir
|
||||
seal.env["USER"] = username
|
||||
seal.env[shell] = config.Confinement.Shell
|
||||
|
||||
seal.container.Place("/etc/passwd",
|
||||
[]byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Confinement.Shell+"\n"))
|
||||
seal.container.Place("/etc/group",
|
||||
[]byte("fortify:x:"+mapgid.String()+":\n"))
|
||||
|
||||
/*
|
||||
Display servers
|
||||
*/
|
||||
|
||||
// pass $TERM for proper terminal I/O in shell
|
||||
// pass TERM for proper terminal I/O in initial process
|
||||
if t, ok := sys.LookupEnv(term); ok {
|
||||
seal.env[term] = t
|
||||
}
|
||||
@ -339,9 +356,9 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
var socketPath string
|
||||
if name, ok := sys.LookupEnv(wl.WaylandDisplay); !ok {
|
||||
fmsg.Verbose(wl.WaylandDisplay + " is not set, assuming " + wl.FallbackName)
|
||||
socketPath = path.Join(sc.RuntimePath, wl.FallbackName)
|
||||
socketPath = path.Join(share.sc.RuntimePath, wl.FallbackName)
|
||||
} else if !path.IsAbs(name) {
|
||||
socketPath = path.Join(sc.RuntimePath, name)
|
||||
socketPath = path.Join(share.sc.RuntimePath, name)
|
||||
} else {
|
||||
socketPath = name
|
||||
}
|
||||
@ -350,7 +367,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.env[wl.WaylandDisplay] = wl.FallbackName
|
||||
|
||||
if !config.Confinement.Sandbox.DirectWayland { // set up security-context-v1
|
||||
socketDir := path.Join(sc.SharePath, "wayland")
|
||||
socketDir := path.Join(share.sc.SharePath, "wayland")
|
||||
outerPath := path.Join(socketDir, seal.id.String())
|
||||
seal.sys.Ensure(socketDir, 0711)
|
||||
appID := config.ID
|
||||
@ -362,6 +379,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.container.Bind(outerPath, innerPath, 0)
|
||||
} else { // bind mount wayland socket (insecure)
|
||||
fmsg.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
||||
share.ensureRuntimeDir()
|
||||
seal.container.Bind(socketPath, innerPath, 0)
|
||||
seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
|
||||
}
|
||||
@ -378,13 +396,9 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PulseAudio server and authentication
|
||||
*/
|
||||
|
||||
if config.Confinement.Enablements&system.EPulse != 0 {
|
||||
// PulseAudio runtime directory (usually `/run/user/%d/pulse`)
|
||||
pulseRuntimeDir := path.Join(sc.RuntimePath, "pulse")
|
||||
pulseRuntimeDir := path.Join(share.sc.RuntimePath, "pulse")
|
||||
// PulseAudio socket (usually `/run/user/%d/pulse/native`)
|
||||
pulseSocket := path.Join(pulseRuntimeDir, "native")
|
||||
|
||||
@ -412,7 +426,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
|
||||
// hard link pulse socket into target-executable share
|
||||
innerPulseRuntimeDir := path.Join(sharePathLocal, "pulse")
|
||||
innerPulseRuntimeDir := path.Join(share.runtime(), "pulse")
|
||||
innerPulseSocket := path.Join(innerRuntimeDir, "pulse", "native")
|
||||
seal.sys.Link(pulseSocket, innerPulseRuntimeDir)
|
||||
seal.container.Bind(innerPulseRuntimeDir, innerPulseSocket, 0)
|
||||
@ -431,10 +445,6 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
D-Bus proxy
|
||||
*/
|
||||
|
||||
if config.Confinement.Enablements&system.EDBus != 0 {
|
||||
// ensure dbus session bus defaults
|
||||
if config.Confinement.SessionBus == nil {
|
||||
@ -442,6 +452,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
|
||||
// downstream socket paths
|
||||
sharePath := share.instance()
|
||||
sessionPath, systemPath := path.Join(sharePath, "bus"), path.Join(sharePath, "system_bus_socket")
|
||||
|
||||
// configure dbus proxy
|
||||
@ -467,10 +478,6 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Miscellaneous
|
||||
*/
|
||||
|
||||
for _, dest := range config.Confinement.Sandbox.Cover {
|
||||
seal.container.Tmpfs(dest, 1<<13, 0755)
|
||||
}
|
||||
|
14
test/test.py
14
test/test.py
@ -176,23 +176,25 @@ machine.send_chars("clear; wayland-info && touch /tmp/client-ok\n")
|
||||
machine.wait_for_file(tmpdir_path(0, "client-ok"), timeout=15)
|
||||
collect_state_ui("foot_wayland")
|
||||
check_state("ne-foot", 1)
|
||||
# Verify acl on XDG_RUNTIME_DIR:
|
||||
print(machine.succeed(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {aid(0) + 1000000}"))
|
||||
# Verify lack of acl on XDG_RUNTIME_DIR:
|
||||
machine.fail(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {aid(0) + 1000000}")
|
||||
machine.send_chars("exit\n")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
# Verify acl cleanup on XDG_RUNTIME_DIR:
|
||||
machine.wait_until_fails(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {aid(0) + 1000000}", timeout=5)
|
||||
machine.fail(f"getfacl --absolute-names --omit-header --numeric /run/user/1000 | grep {aid(0) + 1000000}", timeout=5)
|
||||
|
||||
# Start app (foot) with Wayland enablement from a terminal:
|
||||
swaymsg("exec foot $SHELL -c '(ne-foot) & sleep 1 && fortify show $(fortify ps --short) && touch /tmp/ps-show-ok && cat'")
|
||||
swaymsg("exec foot $SHELL -c '(ne-foot) & disown && exec $SHELL'")
|
||||
wait_for_window(f"u0_a{aid(0)}@machine")
|
||||
machine.send_chars("clear; wayland-info && touch /tmp/term-ok\n")
|
||||
machine.wait_for_file(tmpdir_path(0, "term-ok"), timeout=15)
|
||||
machine.send_key("alt-h")
|
||||
machine.send_chars("clear; fortify show $(fortify ps --short) && touch /tmp/ps-show-ok && exec cat\n")
|
||||
machine.wait_for_file("/tmp/ps-show-ok", timeout=5)
|
||||
collect_state_ui("foot_wayland_term")
|
||||
check_state("ne-foot", 1)
|
||||
machine.send_key("alt-l")
|
||||
machine.send_chars("exit\n")
|
||||
wait_for_window("foot")
|
||||
wait_for_window("alice@machine")
|
||||
machine.send_key("ctrl-c")
|
||||
machine.wait_until_fails("pgrep foot", timeout=5)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user