diff --git a/cmd/app/app.go b/cmd/app/app.go index fa895896..b5e5ee92 100644 --- a/cmd/app/app.go +++ b/cmd/app/app.go @@ -83,6 +83,8 @@ func parse(id string, base *check.Absolute, r io.Reader) (*hst.Config, error) { Home: home, Path: shell, Args: []string{"zsh", "-c"}, + + Flags: hst.FCoverRun, }, } diff --git a/cmd/app/app_test.go b/cmd/app/app_test.go index 7c8c9ede..7a83bcc8 100644 --- a/cmd/app/app_test.go +++ b/cmd/app/app_test.go @@ -122,7 +122,7 @@ talk com.canonical.Unity "exec Discord --ozone-platform-hint=wayland", }, - Flags: hst.FUserns | hst.FHostNet | hst.FMapRealUID | + Flags: hst.FCoverRun | hst.FUserns | hst.FHostNet | hst.FMapRealUID | hst.FShareRuntime | hst.FShareTmpdir, }, }, nil}, diff --git a/cmd/hakurei/print_test.go b/cmd/hakurei/print_test.go index f947fced..71eb8caa 100644 --- a/cmd/hakurei/print_test.go +++ b/cmd/hakurei/print_test.go @@ -64,7 +64,7 @@ func TestPrintShowInstance(t *testing.T) { Identity: 9 (org.chromium.Chromium) Enablements: wayland, dbus, pipewire Groups: video, dialout, plugdev - Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir + Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir Home: /data/data/org.chromium.Chromium Hostname: localhost Path: /run/current-system/sw/bin/chromium @@ -161,7 +161,7 @@ App Identity: 9 (org.chromium.Chromium) Enablements: wayland, dbus, pipewire Groups: video, dialout, plugdev - Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir + Flags: multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir Home: /data/data/org.chromium.Chromium Hostname: localhost Path: /run/current-system/sw/bin/chromium @@ -355,6 +355,7 @@ App "multiarch": true, "map_real_uid": true, "device": true, + "cover_run": true, "share_runtime": true, "share_tmpdir": true }, @@ -506,6 +507,7 @@ App "multiarch": true, "map_real_uid": true, "device": true, + "cover_run": true, "share_runtime": true, "share_tmpdir": true } @@ -704,6 +706,7 @@ func TestPrintPs(t *testing.T) { "multiarch": true, "map_real_uid": true, "device": true, + "cover_run": true, "share_runtime": true, "share_tmpdir": true }, diff --git a/hst/container.go b/hst/container.go index f985f393..a34efc32 100644 --- a/hst/container.go +++ b/hst/container.go @@ -69,6 +69,8 @@ const ( // FDevice mount /dev/ from the init mount namespace as is in the container // mount namespace. FDevice + // FCoverRun covers /run/ in the container mount namespace early. + FCoverRun // FShareRuntime shares XDG_RUNTIME_DIR between containers under the same identity. FShareRuntime @@ -101,6 +103,8 @@ func (flags Flags) String() string { return "mapuid" case FDevice: return "device" + case FCoverRun: + return "cover_run" case FShareRuntime: return "runtime" case FShareTmpdir: @@ -196,6 +200,8 @@ type containerConfigJSON = struct { // Corresponds to [FDevice]. Device bool `json:"device,omitempty"` + // Corresponds to [FCoverRun]. + CoverRun bool `json:"cover_run,omitempty"` // Corresponds to [FShareRuntime]. ShareRuntime bool `json:"share_runtime,omitempty"` @@ -219,6 +225,7 @@ func (c *ContainerConfig) MarshalJSON() ([]byte, error) { Multiarch: c.Flags&FMultiarch != 0, MapRealUID: c.Flags&FMapRealUID != 0, Device: c.Flags&FDevice != 0, + CoverRun: c.Flags&FCoverRun != 0, ShareRuntime: c.Flags&FShareRuntime != 0, ShareTmpdir: c.Flags&FShareTmpdir != 0, }) @@ -262,6 +269,9 @@ func (c *ContainerConfig) UnmarshalJSON(data []byte) error { if v.Device { c.Flags |= FDevice } + if v.CoverRun { + c.Flags |= FCoverRun + } if v.ShareRuntime { c.Flags |= FShareRuntime } diff --git a/hst/container_test.go b/hst/container_test.go index df84827e..309c0a63 100644 --- a/hst/container_test.go +++ b/hst/container_test.go @@ -21,8 +21,8 @@ func TestFlagsString(t *testing.T) { }{ {"none", 0, "none"}, {"none high", hst.FAll + 1, "none"}, - {"all", hst.FAll, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir"}, - {"all high", math.MaxUint, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, runtime, tmpdir"}, + {"all", hst.FAll, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir"}, + {"all high", math.MaxUint, "multiarch, compat, devel, userns, net, abstract, tty, mapuid, device, cover_run, runtime, tmpdir"}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -53,7 +53,7 @@ func TestContainerConfig(t *testing.T) { {"hostnet hostabstract mapuid", &hst.ContainerConfig{Flags: hst.FHostNet | hst.FHostAbstract | hst.FMapRealUID}, `{"env":null,"filesystem":null,"shell":null,"home":null,"args":null,"host_net":true,"host_abstract":true,"map_real_uid":true}`}, {"all", &hst.ContainerConfig{Flags: hst.FAll}, - `{"env":null,"filesystem":null,"shell":null,"home":null,"args":null,"seccomp_compat":true,"devel":true,"userns":true,"host_net":true,"host_abstract":true,"tty":true,"multiarch":true,"map_real_uid":true,"device":true,"share_runtime":true,"share_tmpdir":true}`}, + `{"env":null,"filesystem":null,"shell":null,"home":null,"args":null,"seccomp_compat":true,"devel":true,"userns":true,"host_net":true,"host_abstract":true,"tty":true,"multiarch":true,"map_real_uid":true,"device":true,"cover_run":true,"share_runtime":true,"share_tmpdir":true}`}, } for _, tc := range testCases { diff --git a/hst/hst_test.go b/hst/hst_test.go index 54a81284..c5e2cb12 100644 --- a/hst/hst_test.go +++ b/hst/hst_test.go @@ -245,6 +245,7 @@ func TestTemplate(t *testing.T) { "multiarch": true, "map_real_uid": true, "device": true, + "cover_run": true, "share_runtime": true, "share_tmpdir": true } diff --git a/internal/outcome/run_test.go b/internal/outcome/run_test.go index 77738641..faa322ec 100644 --- a/internal/outcome/run_test.go +++ b/internal/outcome/run_test.go @@ -136,6 +136,7 @@ func TestOutcomeRun(t *testing.T) { Tmpfs(fhs.AbsDevShm, 0, 01777). // spRuntimeOp + Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755). Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755). Bind(m("/tmp/hakurei.0/runtime/9"), m("/run/user/1971"), std.BindWritable). diff --git a/internal/outcome/shim_test.go b/internal/outcome/shim_test.go index 6d9a9f3d..2dc7a4cd 100644 --- a/internal/outcome/shim_test.go +++ b/internal/outcome/shim_test.go @@ -71,6 +71,7 @@ func TestShimEntrypoint(t *testing.T) { Tmpfs(fhs.AbsDevShm, 0, 01777). // spRuntimeOp + Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755). Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755). Bind(m("/tmp/hakurei.10/runtime/9999"), m("/run/user/1000"), std.BindWritable). diff --git a/internal/outcome/spruntime.go b/internal/outcome/spruntime.go index 15974a44..c08bfe81 100644 --- a/internal/outcome/spruntime.go +++ b/internal/outcome/spruntime.go @@ -113,6 +113,9 @@ func (s *spRuntimeOp) toContainer(state *outcomeStateParams) error { } + if state.Container.Flags&hst.FCoverRun != 0 { + state.params.Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755) + } state.params.Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755) if state.Container.Flags&hst.FShareRuntime != 0 { _, runtimeDirInst := s.commonPaths(state.outcomeState) diff --git a/internal/outcome/spruntime_test.go b/internal/outcome/spruntime_test.go index e083f7c3..25f2684c 100644 --- a/internal/outcome/spruntime_test.go +++ b/internal/outcome/spruntime_test.go @@ -40,6 +40,7 @@ func TestSpRuntimeOp(t *testing.T) { // this op configures the container state and does not make calls during toContainer }, &container.Params{ Ops: new(container.Ops). + Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755). Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755). Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable), }, paramsWantEnv(config, map[string]string{ @@ -67,6 +68,7 @@ func TestSpRuntimeOp(t *testing.T) { // this op configures the container state and does not make calls during toContainer }, &container.Params{ Ops: new(container.Ops). + Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755). Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755). Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable), }, paramsWantEnv(config, map[string]string{ @@ -94,6 +96,7 @@ func TestSpRuntimeOp(t *testing.T) { // this op configures the container state and does not make calls during toContainer }, &container.Params{ Ops: new(container.Ops). + Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755). Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755). Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable), }, paramsWantEnv(config, map[string]string{ @@ -117,6 +120,7 @@ func TestSpRuntimeOp(t *testing.T) { // this op configures the container state and does not make calls during toContainer }, &container.Params{ Ops: new(container.Ops). + Tmpfs(fhs.AbsRun, xdgRuntimeDirSize, 0755). Tmpfs(fhs.AbsRunUser, xdgRuntimeDirSize, 0755). Bind(m("/proc/nonexistent/tmp/hakurei.0/runtime/9"), m("/run/user/1000"), std.BindWritable), }, paramsWantEnv(config, map[string]string{