container/fhs: move pathname constants
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m6s
Test / Hpkg (push) Successful in 4m1s
Test / Sandbox (race detector) (push) Successful in 4m29s
Test / Hakurei (race detector) (push) Successful in 3m5s
Test / Hakurei (push) Successful in 2m10s
Test / Flake checks (push) Successful in 1m21s

This allows referencing FHS pathnames without importing container.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-10-07 21:29:16 +09:00
parent 0e6c1a5026
commit 5d18af0007
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
33 changed files with 264 additions and 233 deletions

View File

@ -17,6 +17,7 @@ import (
"hakurei.app/command" "hakurei.app/command"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal" "hakurei.app/internal"
"hakurei.app/internal/app" "hakurei.app/internal/app"
@ -98,7 +99,7 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE
Gid: us, Gid: us,
Username: "chronos", Username: "chronos",
Name: "Hakurei Permissive Default", Name: "Hakurei Permissive Default",
HomeDir: container.FHSVarEmpty, HomeDir: fhs.VarEmpty,
} }
} else { } else {
passwd = u passwd = u
@ -107,7 +108,7 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE
) )
// paths are identical, resolve inner shell and program path // paths are identical, resolve inner shell and program path
shell := container.AbsFHSRoot.Append("bin", "sh") shell := fhs.AbsRoot.Append("bin", "sh")
if a, err := check.NewAbs(os.Getenv("SHELL")); err == nil { if a, err := check.NewAbs(os.Getenv("SHELL")); err == nil {
shell = a shell = a
} }
@ -151,8 +152,8 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE
Filesystem: []hst.FilesystemConfigJSON{ Filesystem: []hst.FilesystemConfigJSON{
// autoroot, includes the home directory // autoroot, includes the home directory
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Target: container.AbsFHSRoot, Target: fhs.AbsRoot,
Source: container.AbsFHSRoot, Source: fhs.AbsRoot,
Write: true, Write: true,
Special: true, Special: true,
}}, }},
@ -169,7 +170,7 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE
// bind GPU stuff // bind GPU stuff
if et&(hst.EX11|hst.EWayland) != 0 { if et&(hst.EX11|hst.EWayland) != 0 {
config.Container.Filesystem = append(config.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{ config.Container.Filesystem = append(config.Container.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{
Source: container.AbsFHSDev.Append("dri"), Source: fhs.AbsDev.Append("dri"),
Device: true, Device: true,
Optional: true, Optional: true,
}}) }})
@ -178,15 +179,15 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE
config.Container.Filesystem = append(config.Container.Filesystem, config.Container.Filesystem = append(config.Container.Filesystem,
// opportunistically bind kvm // opportunistically bind kvm
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{ hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{
Source: container.AbsFHSDev.Append("kvm"), Source: fhs.AbsDev.Append("kvm"),
Device: true, Device: true,
Optional: true, Optional: true,
}}, }},
// do autoetc last // do autoetc last
hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{ hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{
Target: container.AbsFHSEtc, Target: fhs.AbsEtc,
Source: container.AbsFHSEtc, Source: fhs.AbsEtc,
Special: true, Special: true,
}}, }},
) )

View File

@ -5,8 +5,8 @@ import (
"log" "log"
"os" "os"
"hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -86,18 +86,18 @@ func (app *appInfo) toHst(pathSet *appPathSet, pathname *check.Absolute, argv []
MapRealUID: app.MapRealUID, MapRealUID: app.MapRealUID,
Multiarch: app.Multiarch, Multiarch: app.Multiarch,
Filesystem: []hst.FilesystemConfigJSON{ Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Target: container.AbsFHSEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}}, {FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath.Append("store"), Target: pathNixStore}}, {FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath.Append("store"), Target: pathNixStore}},
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}}, {FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}}, {FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSLink{Target: container.AbsFHSUsrBin, Linkname: pathSwBin.String()}}, {FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSBind{Source: pathSet.metaPath, Target: hst.AbsTmp.Append("app")}}, {FilesystemConfig: &hst.FSBind{Source: pathSet.metaPath, Target: hst.AbsTmp.Append("app")}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSEtc.Append("resolv.conf"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsEtc.Append("resolv.conf"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("block"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("bus"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("class"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("dev"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("devices"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}}, {FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}},
}, },

View File

@ -13,6 +13,7 @@ import (
"hakurei.app/command" "hakurei.app/command"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -275,12 +276,12 @@ func main() {
"path:" + a.NixGL + "#nixVulkanNvidia", "path:" + a.NixGL + "#nixVulkanNvidia",
}, true, func(config *hst.Config) *hst.Config { }, true, func(config *hst.Config) *hst.Config {
config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{ config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSEtc.Append("resolv.conf"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsEtc.Append("resolv.conf"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("block"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("block"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("bus"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("bus"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("class"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("class"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("dev"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("dev"), Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSSys.Append("devices"), Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsSys.Append("devices"), Optional: true}},
}...) }...)
appendGPUFilesystem(config) appendGPUFilesystem(config)
return config return config

View File

@ -9,6 +9,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -23,16 +24,16 @@ func init() {
if a, err := check.NewAbs(os.Getenv("HAKUREI_DATA_HOME")); err == nil { if a, err := check.NewAbs(os.Getenv("HAKUREI_DATA_HOME")); err == nil {
dataHome = a dataHome = a
} else { } else {
dataHome = container.AbsFHSVarLib.Append("hakurei/" + strconv.Itoa(os.Getuid())) dataHome = fhs.AbsVarLib.Append("hakurei/" + strconv.Itoa(os.Getuid()))
} }
} }
var ( var (
pathBin = container.AbsFHSRoot.Append("bin") pathBin = fhs.AbsRoot.Append("bin")
pathNix = check.MustAbs("/nix/") pathNix = check.MustAbs("/nix/")
pathNixStore = pathNix.Append("store/") pathNixStore = pathNix.Append("store/")
pathCurrentSystem = container.AbsFHSRun.Append("current-system") pathCurrentSystem = fhs.AbsRun.Append("current-system")
pathSwBin = pathCurrentSystem.Append("sw/bin/") pathSwBin = pathCurrentSystem.Append("sw/bin/")
pathShell = pathSwBin.Append(bash) pathShell = pathSwBin.Append(bash)
@ -89,28 +90,28 @@ func pathSetByApp(id string) *appPathSet {
func appendGPUFilesystem(config *hst.Config) { func appendGPUFilesystem(config *hst.Config) {
config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{ config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfigJSON{
// flatpak commit 763a686d874dd668f0236f911de00b80766ffe79 // flatpak commit 763a686d874dd668f0236f911de00b80766ffe79
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("dri"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("dri"), Device: true, Optional: true}},
// mali // mali
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("mali"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("mali"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("mali0"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("mali0"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("umplock"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("umplock"), Device: true, Optional: true}},
// nvidia // nvidia
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidiactl"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidiactl"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia-modeset"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-modeset"), Device: true, Optional: true}},
// nvidia OpenCL/CUDA // nvidia OpenCL/CUDA
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia-uvm"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-uvm"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia-uvm-tools"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia-uvm-tools"), Device: true, Optional: true}},
// flatpak commit d2dff2875bb3b7e2cd92d8204088d743fd07f3ff // flatpak commit d2dff2875bb3b7e2cd92d8204088d743fd07f3ff
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia0"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia1"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia0"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia1"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia2"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia3"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia2"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia3"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia4"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia5"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia4"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia5"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia6"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia7"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia6"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia7"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia8"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia9"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia8"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia9"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia10"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia11"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia10"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia11"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia12"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia13"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia12"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia13"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia14"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia15"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia14"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia15"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia16"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia17"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia16"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia17"), Device: true, Optional: true}},
{FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia18"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: container.AbsFHSDev.Append("nvidia19"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia18"), Device: true, Optional: true}}, {FilesystemConfig: &hst.FSBind{Source: fhs.AbsDev.Append("nvidia19"), Device: true, Optional: true}},
}...) }...)
} }

View File

@ -7,6 +7,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -33,11 +34,11 @@ func withNixDaemon(
Multiarch: true, Multiarch: true,
Tty: dropShell, Tty: dropShell,
Filesystem: []hst.FilesystemConfigJSON{ Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Target: container.AbsFHSEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}}, {FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: pathSet.cacheDir.Append("etc"), Special: true}},
{FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath, Target: pathNix, Write: true}}, {FilesystemConfig: &hst.FSBind{Source: pathSet.nixPath, Target: pathNix, Write: true}},
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}}, {FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}}, {FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSLink{Target: container.AbsFHSUsrBin, Linkname: pathSwBin.String()}}, {FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}}, {FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID), Source: pathSet.homeDir, Write: true, Ensure: true}},
}, },
@ -82,11 +83,11 @@ func withCacheDir(
Multiarch: true, Multiarch: true,
Tty: dropShell, Tty: dropShell,
Filesystem: []hst.FilesystemConfigJSON{ Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{Target: container.AbsFHSEtc, Source: workDir.Append(container.FHSEtc), Special: true}}, {FilesystemConfig: &hst.FSBind{Target: fhs.AbsEtc, Source: workDir.Append(fhs.Etc), Special: true}},
{FilesystemConfig: &hst.FSBind{Source: workDir.Append("nix"), Target: pathNix}}, {FilesystemConfig: &hst.FSBind{Source: workDir.Append("nix"), Target: pathNix}},
{FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}}, {FilesystemConfig: &hst.FSLink{Target: pathCurrentSystem, Linkname: app.CurrentSystem.String()}},
{FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}}, {FilesystemConfig: &hst.FSLink{Target: pathBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSLink{Target: container.AbsFHSUsrBin, Linkname: pathSwBin.String()}}, {FilesystemConfig: &hst.FSLink{Target: fhs.AbsUsrBin, Linkname: pathSwBin.String()}},
{FilesystemConfig: &hst.FSBind{Source: workDir, Target: hst.AbsTmp.Append("bundle")}}, {FilesystemConfig: &hst.FSBind{Source: workDir, Target: hst.AbsTmp.Append("bundle")}},
{FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID, "cache"), Source: pathSet.cacheDir, Write: true, Ensure: true}}, {FilesystemConfig: &hst.FSBind{Target: pathDataData.Append(app.ID, "cache"), Source: pathSet.cacheDir, Write: true, Ensure: true}},
}, },

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
func init() { gob.Register(new(AutoEtcOp)) } func init() { gob.Register(new(AutoEtcOp)) }
@ -13,7 +14,7 @@ func init() { gob.Register(new(AutoEtcOp)) }
// This is not a generic setup op. It is implemented here to reduce ipc overhead. // This is not a generic setup op. It is implemented here to reduce ipc overhead.
func (f *Ops) Etc(host *check.Absolute, prefix string) *Ops { func (f *Ops) Etc(host *check.Absolute, prefix string) *Ops {
e := &AutoEtcOp{prefix} e := &AutoEtcOp{prefix}
f.Mkdir(AbsFHSEtc, 0755) f.Mkdir(fhs.AbsEtc, 0755)
f.Bind(host, e.hostPath(), 0) f.Bind(host, e.hostPath(), 0)
*f = append(*f, e) *f = append(*f, e)
return f return f
@ -29,7 +30,7 @@ func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error {
} }
state.nonrepeatable |= nrAutoEtc state.nonrepeatable |= nrAutoEtc
const target = sysrootPath + FHSEtc const target = sysrootPath + fhs.Etc
rel := e.hostRel() + "/" rel := e.hostRel() + "/"
if err := k.mkdirAll(target, 0755); err != nil { if err := k.mkdirAll(target, 0755); err != nil {
@ -44,7 +45,7 @@ func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error {
case ".host", "passwd", "group": case ".host", "passwd", "group":
case "mtab": case "mtab":
if err = k.symlink(FHSProc+"mounts", target+n); err != nil { if err = k.symlink(fhs.Proc+"mounts", target+n); err != nil {
return err return err
} }
@ -59,7 +60,7 @@ func (e *AutoEtcOp) apply(state *setupState, k syscallDispatcher) error {
return nil return nil
} }
func (e *AutoEtcOp) hostPath() *check.Absolute { return AbsFHSEtc.Append(e.hostRel()) } func (e *AutoEtcOp) hostPath() *check.Absolute { return fhs.AbsEtc.Append(e.hostRel()) }
func (e *AutoEtcOp) hostRel() string { return ".host/" + e.Prefix } func (e *AutoEtcOp) hostRel() string { return ".host/" + e.Prefix }
func (e *AutoEtcOp) Is(op Op) bool { func (e *AutoEtcOp) Is(op Op) bool {

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
func init() { gob.Register(new(AutoRootOp)) } func init() { gob.Register(new(AutoRootOp)) }
@ -40,7 +41,7 @@ func (r *AutoRootOp) early(state *setupState, k syscallDispatcher) error {
// careful: the Valid method is skipped, make sure this is always valid // careful: the Valid method is skipped, make sure this is always valid
op := &BindMountOp{ op := &BindMountOp{
Source: r.Host.Append(name), Source: r.Host.Append(name),
Target: AbsFHSRoot.Append(name), Target: fhs.AbsRoot.Append(name),
Flags: r.Flags, Flags: r.Flags,
} }
if err = op.early(state, k); err != nil { if err = op.early(state, k); err != nil {

View File

@ -16,6 +16,7 @@ import (
"hakurei.app/container/bits" "hakurei.app/container/bits"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
) )
@ -200,7 +201,7 @@ func (p *Container) Start() error {
} else { } else {
p.cmd.Cancel = func() error { return p.cmd.Process.Signal(CancelSignal) } p.cmd.Cancel = func() error { return p.cmd.Process.Signal(CancelSignal) }
} }
p.cmd.Dir = FHSRoot p.cmd.Dir = fhs.Root
p.cmd.SysProcAttr = &SysProcAttr{ p.cmd.SysProcAttr = &SysProcAttr{
Setsid: !p.RetainSession, Setsid: !p.RetainSession,
Pdeathsig: SIGKILL, Pdeathsig: SIGKILL,
@ -316,7 +317,7 @@ func (p *Container) Serve() error {
// do not transmit nil // do not transmit nil
if p.Dir == nil { if p.Dir == nil {
p.Dir = AbsFHSRoot p.Dir = fhs.AbsRoot
} }
if p.SeccompRules == nil { if p.SeccompRules == nil {
p.SeccompRules = make([]seccomp.NativeRule, 0) p.SeccompRules = make([]seccomp.NativeRule, 0)

41
container/fhs/abs.go Normal file
View File

@ -0,0 +1,41 @@
package fhs
import (
_ "unsafe"
"hakurei.app/container/check"
)
/* constants in this file bypass abs check, be extremely careful when changing them! */
//go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs
func unsafeAbs(_ string) *check.Absolute
var (
// AbsRoot is [Root] as [check.Absolute].
AbsRoot = unsafeAbs(Root)
// AbsEtc is [Etc] as [check.Absolute].
AbsEtc = unsafeAbs(Etc)
// AbsTmp is [Tmp] as [check.Absolute].
AbsTmp = unsafeAbs(Tmp)
// AbsRun is [Run] as [check.Absolute].
AbsRun = unsafeAbs(Run)
// AbsRunUser is [RunUser] as [check.Absolute].
AbsRunUser = unsafeAbs(RunUser)
// AbsUsrBin is [UsrBin] as [check.Absolute].
AbsUsrBin = unsafeAbs(UsrBin)
// AbsVar is [Var] as [check.Absolute].
AbsVar = unsafeAbs(Var)
// AbsVarLib is [VarLib] as [check.Absolute].
AbsVarLib = unsafeAbs(VarLib)
// AbsDev is [Dev] as [check.Absolute].
AbsDev = unsafeAbs(Dev)
// AbsProc is [Proc] as [check.Absolute].
AbsProc = unsafeAbs(Proc)
// AbsSys is [Sys] as [check.Absolute].
AbsSys = unsafeAbs(Sys)
)

38
container/fhs/fhs.go Normal file
View File

@ -0,0 +1,38 @@
// Package fhs provides constant and checked pathname values for common FHS paths.
package fhs
const (
// Root points to the file system root.
Root = "/"
// Etc points to the directory for system-specific configuration.
Etc = "/etc/"
// Tmp points to the place for small temporary files.
Tmp = "/tmp/"
// Run points to a "tmpfs" file system for system packages to place runtime data, socket files, and similar.
Run = "/run/"
// RunUser points to a directory containing per-user runtime directories,
// each usually individually mounted "tmpfs" instances.
RunUser = Run + "user/"
// Usr points to vendor-supplied operating system resources.
Usr = "/usr/"
// UsrBin points to binaries and executables for user commands that shall appear in the $PATH search path.
UsrBin = Usr + "bin/"
// Var points to persistent, variable system data. Writable during normal system operation.
Var = "/var/"
// VarLib points to persistent system data.
VarLib = Var + "lib/"
// VarEmpty points to a nonstandard directory that is usually empty.
VarEmpty = Var + "empty/"
// Dev points to the root directory for device nodes.
Dev = "/dev/"
// Proc points to a virtual kernel file system exposing the process list and other functionality.
Proc = "/proc/"
// ProcSys points to a hierarchy below /proc/ that exposes a number of kernel tunables.
ProcSys = Proc + "sys/"
// Sys points to a virtual kernel file system exposing discovered devices and other functionality.
Sys = "/sys/"
)

View File

@ -12,6 +12,7 @@ import (
. "syscall" . "syscall"
"time" "time"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
) )
@ -30,7 +31,7 @@ const (
it should be noted that none of this should become relevant at any point since the resulting it should be noted that none of this should become relevant at any point since the resulting
intermediate root tmpfs should be effectively anonymous */ intermediate root tmpfs should be effectively anonymous */
intermediateHostPath = FHSProc + "self/fd" intermediateHostPath = fhs.Proc + "self/fd"
// setup params file descriptor // setup params file descriptor
setupEnv = "HAKUREI_SETUP" setupEnv = "HAKUREI_SETUP"
@ -146,17 +147,17 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
if err := k.setDumpable(SUID_DUMP_USER); err != nil { if err := k.setDumpable(SUID_DUMP_USER); err != nil {
k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err) k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err)
} }
if err := k.writeFile(FHSProc+"self/uid_map", if err := k.writeFile(fhs.Proc+"self/uid_map",
append([]byte{}, strconv.Itoa(params.Uid)+" "+strconv.Itoa(params.HostUid)+" 1\n"...), append([]byte{}, strconv.Itoa(params.Uid)+" "+strconv.Itoa(params.HostUid)+" 1\n"...),
0); err != nil { 0); err != nil {
k.fatalf(msg, "%v", err) k.fatalf(msg, "%v", err)
} }
if err := k.writeFile(FHSProc+"self/setgroups", if err := k.writeFile(fhs.Proc+"self/setgroups",
[]byte("deny\n"), []byte("deny\n"),
0); err != nil && !os.IsNotExist(err) { 0); err != nil && !os.IsNotExist(err) {
k.fatalf(msg, "%v", err) k.fatalf(msg, "%v", err)
} }
if err := k.writeFile(FHSProc+"self/gid_map", if err := k.writeFile(fhs.Proc+"self/gid_map",
append([]byte{}, strconv.Itoa(params.Gid)+" "+strconv.Itoa(params.HostGid)+" 1\n"...), append([]byte{}, strconv.Itoa(params.Gid)+" "+strconv.Itoa(params.HostGid)+" 1\n"...),
0); err != nil { 0); err != nil {
k.fatalf(msg, "%v", err) k.fatalf(msg, "%v", err)
@ -175,7 +176,7 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
// cache sysctl before pivot_root // cache sysctl before pivot_root
lastcap := k.lastcap(msg) lastcap := k.lastcap(msg)
if err := k.mount(zeroString, FHSRoot, zeroString, MS_SILENT|MS_SLAVE|MS_REC, zeroString); err != nil { if err := k.mount(zeroString, fhs.Root, zeroString, MS_SILENT|MS_SLAVE|MS_REC, zeroString); err != nil {
k.fatalf(msg, "cannot make / rslave: %v", err) k.fatalf(msg, "cannot make / rslave: %v", err)
} }
@ -220,7 +221,7 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
if err := k.pivotRoot(intermediateHostPath, hostDir); err != nil { if err := k.pivotRoot(intermediateHostPath, hostDir); err != nil {
k.fatalf(msg, "cannot pivot into intermediate root: %v", err) k.fatalf(msg, "cannot pivot into intermediate root: %v", err)
} }
if err := k.chdir(FHSRoot); err != nil { if err := k.chdir(fhs.Root); err != nil {
k.fatalf(msg, "cannot enter intermediate root: %v", err) k.fatalf(msg, "cannot enter intermediate root: %v", err)
} }
@ -253,7 +254,7 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
{ {
var fd int var fd int
if err := IgnoringEINTR(func() (err error) { if err := IgnoringEINTR(func() (err error) {
fd, err = k.open(FHSRoot, O_DIRECTORY|O_RDONLY, 0) fd, err = k.open(fhs.Root, O_DIRECTORY|O_RDONLY, 0)
return return
}); err != nil { }); err != nil {
k.fatalf(msg, "cannot open intermediate root: %v", err) k.fatalf(msg, "cannot open intermediate root: %v", err)
@ -271,7 +272,7 @@ func initEntrypoint(k syscallDispatcher, msg Msg) {
if err := k.unmount(".", MNT_DETACH); err != nil { if err := k.unmount(".", MNT_DETACH); err != nil {
k.fatalf(msg, "cannot unmount intermediate root: %v", err) k.fatalf(msg, "cannot unmount intermediate root: %v", err)
} }
if err := k.chdir(FHSRoot); err != nil { if err := k.chdir(fhs.Root); err != nil {
k.fatalf(msg, "cannot enter root: %v", err) k.fatalf(msg, "cannot enter root: %v", err)
} }

View File

@ -7,6 +7,7 @@ import (
. "syscall" . "syscall"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
func init() { gob.Register(new(MountDevOp)) } func init() { gob.Register(new(MountDevOp)) }
@ -49,7 +50,7 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error {
} }
if err := k.bindMount( if err := k.bindMount(
state, state,
toHost(FHSDev+name), toHost(fhs.Dev+name),
targetPath, targetPath,
0, 0,
); err != nil { ); err != nil {
@ -58,15 +59,15 @@ func (d *MountDevOp) apply(state *setupState, k syscallDispatcher) error {
} }
for i, name := range []string{"stdin", "stdout", "stderr"} { for i, name := range []string{"stdin", "stdout", "stderr"} {
if err := k.symlink( if err := k.symlink(
FHSProc+"self/fd/"+string(rune(i+'0')), fhs.Proc+"self/fd/"+string(rune(i+'0')),
path.Join(target, name), path.Join(target, name),
); err != nil { ); err != nil {
return err return err
} }
} }
for _, pair := range [][2]string{ for _, pair := range [][2]string{
{FHSProc + "self/fd", "fd"}, {fhs.Proc + "self/fd", "fd"},
{FHSProc + "kcore", "core"}, {fhs.Proc + "kcore", "core"},
{"pts/ptmx", "ptmx"}, {"pts/ptmx", "ptmx"},
} { } {
if err := k.symlink(pair[0], path.Join(target, pair[1])); err != nil { if err := k.symlink(pair[0], path.Join(target, pair[1])); err != nil {

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
const ( const (
@ -67,7 +68,7 @@ func (f *Ops) Overlay(target, state, work *check.Absolute, layers ...*check.Abso
// OverlayEphemeral appends an [Op] that mounts the overlay pseudo filesystem on [MountOverlayOp.Target] // OverlayEphemeral appends an [Op] that mounts the overlay pseudo filesystem on [MountOverlayOp.Target]
// with an ephemeral upperdir and workdir. // with an ephemeral upperdir and workdir.
func (f *Ops) OverlayEphemeral(target *check.Absolute, layers ...*check.Absolute) *Ops { func (f *Ops) OverlayEphemeral(target *check.Absolute, layers ...*check.Absolute) *Ops {
return f.Overlay(target, AbsFHSRoot, nil, layers...) return f.Overlay(target, fhs.AbsRoot, nil, layers...)
} }
// OverlayReadonly appends an [Op] that mounts the overlay pseudo filesystem readonly on [MountOverlayOp.Target] // OverlayReadonly appends an [Op] that mounts the overlay pseudo filesystem readonly on [MountOverlayOp.Target]
@ -85,7 +86,7 @@ type MountOverlayOp struct {
lower []string lower []string
// The upperdir is normally on a writable filesystem. // The upperdir is normally on a writable filesystem.
// //
// If Work is nil and Upper holds the special value [AbsFHSRoot], // If Work is nil and Upper holds the special value [fhs.AbsRoot],
// an ephemeral upperdir and workdir will be set up. // an ephemeral upperdir and workdir will be set up.
// //
// If both Work and Upper are nil, upperdir and workdir is omitted and the overlay is mounted readonly. // If both Work and Upper are nil, upperdir and workdir is omitted and the overlay is mounted readonly.
@ -119,7 +120,7 @@ func (o *MountOverlayOp) Valid() bool {
func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error { func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error {
if o.Work == nil && o.Upper != nil { if o.Work == nil && o.Upper != nil {
switch o.Upper.String() { switch o.Upper.String() {
case FHSRoot: // ephemeral case fhs.Root: // ephemeral
o.ephemeral = true // intermediate root not yet available o.ephemeral = true // intermediate root not yet available
default: default:
@ -174,10 +175,10 @@ func (o *MountOverlayOp) apply(state *setupState, k syscallDispatcher) error {
if o.ephemeral { if o.ephemeral {
var err error var err error
// these directories are created internally, therefore early (absolute, symlink, prefix, escape) is bypassed // these directories are created internally, therefore early (absolute, symlink, prefix, escape) is bypassed
if o.upper, err = k.mkdirTemp(FHSRoot, intermediatePatternOverlayUpper); err != nil { if o.upper, err = k.mkdirTemp(fhs.Root, intermediatePatternOverlayUpper); err != nil {
return err return err
} }
if o.work, err = k.mkdirTemp(FHSRoot, intermediatePatternOverlayWork); err != nil { if o.work, err = k.mkdirTemp(fhs.Root, intermediatePatternOverlayWork); err != nil {
return err return err
} }
} }

View File

@ -6,6 +6,7 @@ import (
"syscall" "syscall"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
const ( const (
@ -40,7 +41,7 @@ func (t *TmpfileOp) Valid() bool { return t != ni
func (t *TmpfileOp) early(*setupState, syscallDispatcher) error { return nil } func (t *TmpfileOp) early(*setupState, syscallDispatcher) error { return nil }
func (t *TmpfileOp) apply(state *setupState, k syscallDispatcher) error { func (t *TmpfileOp) apply(state *setupState, k syscallDispatcher) error {
var tmpPath string var tmpPath string
if f, err := k.createTemp(FHSRoot, intermediatePatternTmpfile); err != nil { if f, err := k.createTemp(fhs.Root, intermediatePatternTmpfile); err != nil {
return err return err
} else if _, err = f.Write(t.Data); err != nil { } else if _, err = f.Write(t.Data); err != nil {
return err return err

View File

@ -59,7 +59,6 @@ const (
FstypeNULL = zeroString FstypeNULL = zeroString
// FstypeProc represents the proc pseudo-filesystem. // FstypeProc represents the proc pseudo-filesystem.
// A fully visible instance of proc must be available in the mount namespace for proc to be mounted. // A fully visible instance of proc must be available in the mount namespace for proc to be mounted.
// This filesystem type is usually mounted on [FHSProc].
FstypeProc = "proc" FstypeProc = "proc"
// FstypeDevpts represents the devpts pseudo-filesystem. // FstypeDevpts represents the devpts pseudo-filesystem.
// This type of filesystem is usually mounted on /dev/pts. // This type of filesystem is usually mounted on /dev/pts.

View File

@ -8,90 +8,19 @@ import (
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
_ "unsafe"
"hakurei.app/container/check" "hakurei.app/container/fhs"
"hakurei.app/container/vfs" "hakurei.app/container/vfs"
) )
/* constants in this file bypass abs check, be extremely careful when changing them! */
//go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs
func unsafeAbs(_ string) *check.Absolute
const (
// FHSRoot points to the file system root.
FHSRoot = "/"
// FHSEtc points to the directory for system-specific configuration.
FHSEtc = "/etc/"
// FHSTmp points to the place for small temporary files.
FHSTmp = "/tmp/"
// FHSRun points to a "tmpfs" file system for system packages to place runtime data, socket files, and similar.
FHSRun = "/run/"
// FHSRunUser points to a directory containing per-user runtime directories,
// each usually individually mounted "tmpfs" instances.
FHSRunUser = FHSRun + "user/"
// FHSUsr points to vendor-supplied operating system resources.
FHSUsr = "/usr/"
// FHSUsrBin points to binaries and executables for user commands that shall appear in the $PATH search path.
FHSUsrBin = FHSUsr + "bin/"
// FHSVar points to persistent, variable system data. Writable during normal system operation.
FHSVar = "/var/"
// FHSVarLib points to persistent system data.
FHSVarLib = FHSVar + "lib/"
// FHSVarEmpty points to a nonstandard directory that is usually empty.
FHSVarEmpty = FHSVar + "empty/"
// FHSDev points to the root directory for device nodes.
FHSDev = "/dev/"
// FHSProc points to a virtual kernel file system exposing the process list and other functionality.
FHSProc = "/proc/"
// FHSProcSys points to a hierarchy below /proc/ that exposes a number of kernel tunables.
FHSProcSys = FHSProc + "sys/"
// FHSSys points to a virtual kernel file system exposing discovered devices and other functionality.
FHSSys = "/sys/"
)
var (
// AbsFHSRoot is [FHSRoot] as [Absolute].
AbsFHSRoot = unsafeAbs(FHSRoot)
// AbsFHSEtc is [FHSEtc] as [Absolute].
AbsFHSEtc = unsafeAbs(FHSEtc)
// AbsFHSTmp is [FHSTmp] as [Absolute].
AbsFHSTmp = unsafeAbs(FHSTmp)
// AbsFHSRun is [FHSRun] as [Absolute].
AbsFHSRun = unsafeAbs(FHSRun)
// AbsFHSRunUser is [FHSRunUser] as [Absolute].
AbsFHSRunUser = unsafeAbs(FHSRunUser)
// AbsFHSUsrBin is [FHSUsrBin] as [Absolute].
AbsFHSUsrBin = unsafeAbs(FHSUsrBin)
// AbsFHSVar is [FHSVar] as [Absolute].
AbsFHSVar = unsafeAbs(FHSVar)
// AbsFHSVarLib is [FHSVarLib] as [Absolute].
AbsFHSVarLib = unsafeAbs(FHSVarLib)
// AbsFHSDev is [FHSDev] as [Absolute].
AbsFHSDev = unsafeAbs(FHSDev)
// AbsFHSProc is [FHSProc] as [Absolute].
AbsFHSProc = unsafeAbs(FHSProc)
// AbsFHSSys is [FHSSys] as [Absolute].
AbsFHSSys = unsafeAbs(FHSSys)
)
const ( const (
// Nonexistent is a path that cannot exist. // Nonexistent is a path that cannot exist.
// /proc is chosen because a system with covered /proc is unsupported by this package. // /proc is chosen because a system with covered /proc is unsupported by this package.
Nonexistent = FHSProc + "nonexistent" Nonexistent = fhs.Proc + "nonexistent"
hostPath = FHSRoot + hostDir hostPath = fhs.Root + hostDir
hostDir = "host" hostDir = "host"
sysrootPath = FHSRoot + sysrootDir sysrootPath = fhs.Root + sysrootDir
sysrootDir = "sysroot" sysrootDir = "sysroot"
) )

View File

@ -5,6 +5,8 @@ import (
"os" "os"
"strconv" "strconv"
"sync" "sync"
"hakurei.app/container/fhs"
) )
var ( var (
@ -16,9 +18,9 @@ var (
) )
const ( const (
kernelOverflowuidPath = FHSProcSys + "kernel/overflowuid" kernelOverflowuidPath = fhs.ProcSys + "kernel/overflowuid"
kernelOverflowgidPath = FHSProcSys + "kernel/overflowgid" kernelOverflowgidPath = fhs.ProcSys + "kernel/overflowgid"
kernelCapLastCapPath = FHSProcSys + "kernel/cap_last_cap" kernelCapLastCapPath = fhs.ProcSys + "kernel/cap_last_cap"
) )
func mustReadSysctl(msg Msg) { func mustReadSysctl(msg Msg) {

View File

@ -8,6 +8,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/helper" "hakurei.app/helper"
) )
@ -35,9 +36,9 @@ func TestContainer(t *testing.T) {
return helper.New(ctx, nil, check.MustAbs(os.Args[0]), "helper", argsWt, stat, argF, func(z *container.Container) { return helper.New(ctx, nil, check.MustAbs(os.Args[0]), "helper", argsWt, stat, argF, func(z *container.Container) {
setOutput(&z.Stdout, &z.Stderr) setOutput(&z.Stdout, &z.Stderr)
z. z.
Bind(container.AbsFHSRoot, container.AbsFHSRoot, 0). Bind(fhs.AbsRoot, fhs.AbsRoot, 0).
Proc(container.AbsFHSProc). Proc(fhs.AbsProc).
Dev(container.AbsFHSDev, true) Dev(fhs.AbsDev, true)
}, nil) }, nil)
}) })
}) })

View File

@ -4,7 +4,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"hakurei.app/container" "hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -25,18 +25,18 @@ func TestConfigValidate(t *testing.T) {
{"home", &hst.Config{Container: &hst.ContainerConfig{}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull, {"home", &hst.Config{Container: &hst.ContainerConfig{}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to home directory"}}, Msg: "container configuration missing path to home directory"}},
{"shell", &hst.Config{Container: &hst.ContainerConfig{ {"shell", &hst.Config{Container: &hst.ContainerConfig{
Home: container.AbsFHSTmp, Home: fhs.AbsTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull, }}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to shell"}}, Msg: "container configuration missing path to shell"}},
{"path", &hst.Config{Container: &hst.ContainerConfig{ {"path", &hst.Config{Container: &hst.ContainerConfig{
Home: container.AbsFHSTmp, Home: fhs.AbsTmp,
Shell: container.AbsFHSTmp, Shell: fhs.AbsTmp,
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull, }}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
Msg: "container configuration missing path to initial program"}}, Msg: "container configuration missing path to initial program"}},
{"valid", &hst.Config{Container: &hst.ContainerConfig{ {"valid", &hst.Config{Container: &hst.ContainerConfig{
Home: container.AbsFHSTmp, Home: fhs.AbsTmp,
Shell: container.AbsFHSTmp, Shell: fhs.AbsTmp,
Path: container.AbsFHSTmp, Path: fhs.AbsTmp,
}}, nil}, }}, nil},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -56,14 +56,14 @@ func TestExtraPermConfig(t *testing.T) {
}{ }{
{"nil", nil, "<invalid>"}, {"nil", nil, "<invalid>"},
{"nil path", &hst.ExtraPermConfig{Path: nil}, "<invalid>"}, {"nil path", &hst.ExtraPermConfig{Path: nil}, "<invalid>"},
{"r", &hst.ExtraPermConfig{Path: container.AbsFHSRoot, Read: true}, "r--:/"}, {"r", &hst.ExtraPermConfig{Path: fhs.AbsRoot, Read: true}, "r--:/"},
{"r+", &hst.ExtraPermConfig{Ensure: true, Path: container.AbsFHSRoot, Read: true}, "r--+:/"}, {"r+", &hst.ExtraPermConfig{Ensure: true, Path: fhs.AbsRoot, Read: true}, "r--+:/"},
{"w", &hst.ExtraPermConfig{Path: hst.AbsTmp, Write: true}, "-w-:/.hakurei"}, {"w", &hst.ExtraPermConfig{Path: hst.AbsTmp, Write: true}, "-w-:/.hakurei"},
{"w+", &hst.ExtraPermConfig{Ensure: true, Path: hst.AbsTmp, Write: true}, "-w-+:/.hakurei"}, {"w+", &hst.ExtraPermConfig{Ensure: true, Path: hst.AbsTmp, Write: true}, "-w-+:/.hakurei"},
{"x", &hst.ExtraPermConfig{Path: container.AbsFHSRunUser, Execute: true}, "--x:/run/user/"}, {"x", &hst.ExtraPermConfig{Path: fhs.AbsRunUser, Execute: true}, "--x:/run/user/"},
{"x+", &hst.ExtraPermConfig{Ensure: true, Path: container.AbsFHSRunUser, Execute: true}, "--x+:/run/user/"}, {"x+", &hst.ExtraPermConfig{Ensure: true, Path: fhs.AbsRunUser, Execute: true}, "--x+:/run/user/"},
{"rwx", &hst.ExtraPermConfig{Path: container.AbsFHSTmp, Read: true, Write: true, Execute: true}, "rwx:/tmp/"}, {"rwx", &hst.ExtraPermConfig{Path: fhs.AbsTmp, Read: true, Write: true, Execute: true}, "rwx:/tmp/"},
{"rwx+", &hst.ExtraPermConfig{Ensure: true, Path: container.AbsFHSTmp, Read: true, Write: true, Execute: true}, "rwx+:/tmp/"}, {"rwx+", &hst.ExtraPermConfig{Ensure: true, Path: fhs.AbsTmp, Read: true, Write: true, Execute: true}, "rwx+:/tmp/"},
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@ -6,6 +6,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
func init() { gob.Register(new(FSBind)) } func init() { gob.Register(new(FSBind)) }
@ -29,19 +30,19 @@ type FSBind struct {
Optional bool `json:"optional,omitempty"` Optional bool `json:"optional,omitempty"`
// enable special behaviour: // enable special behaviour:
// for autoroot, Target must be set to [container.AbsFHSRoot]; // for autoroot, Target must be set to [fhs.AbsRoot];
// for autoetc, Target must be set to [container.AbsFHSEtc] // for autoetc, Target must be set to [fhs.AbsEtc]
Special bool `json:"special,omitempty"` Special bool `json:"special,omitempty"`
} }
// IsAutoRoot returns whether this FSBind has autoroot behaviour enabled. // IsAutoRoot returns whether this FSBind has autoroot behaviour enabled.
func (b *FSBind) IsAutoRoot() bool { func (b *FSBind) IsAutoRoot() bool {
return b.Valid() && b.Special && b.Target.String() == container.FHSRoot return b.Valid() && b.Special && b.Target.String() == fhs.Root
} }
// IsAutoEtc returns whether this FSBind has autoetc behaviour enabled. // IsAutoEtc returns whether this FSBind has autoetc behaviour enabled.
func (b *FSBind) IsAutoEtc() bool { func (b *FSBind) IsAutoEtc() bool {
return b.Valid() && b.Special && b.Target.String() == container.FHSEtc return b.Valid() && b.Special && b.Target.String() == fhs.Etc
} }
func (b *FSBind) Valid() bool { func (b *FSBind) Valid() bool {
@ -56,7 +57,7 @@ func (b *FSBind) Valid() bool {
return false return false
} else { } else {
switch b.Target.String() { switch b.Target.String() {
case container.FHSRoot, container.FHSEtc: case fhs.Root, fhs.Etc:
break break
default: default:
@ -138,7 +139,7 @@ func (b *FSBind) String() string {
if flagSym != "" { if flagSym != "" {
prefix += ":" + flagSym prefix += ":" + flagSym
} }
if b.Source.String() != container.FHSRoot { if b.Source.String() != fhs.Root {
return prefix + ":" + b.Source.String() return prefix + ":" + b.Source.String()
} }
return prefix return prefix

View File

@ -6,8 +6,8 @@ import (
"net" "net"
"os" "os"
"hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
) )
// An AppError is returned while starting an app according to [hst.Config]. // An AppError is returned while starting an app according to [hst.Config].
@ -85,8 +85,8 @@ func Template() *Config {
DirectWayland: false, DirectWayland: false,
ExtraPerms: []*ExtraPermConfig{ ExtraPerms: []*ExtraPermConfig{
{Path: container.AbsFHSVarLib.Append("hakurei/u0"), Ensure: true, Execute: true}, {Path: fhs.AbsVarLib.Append("hakurei/u0"), Ensure: true, Execute: true},
{Path: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), Read: true, Write: true, Execute: true}, {Path: fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"), Read: true, Write: true, Execute: true},
}, },
Identity: 9, Identity: 9,
@ -112,9 +112,9 @@ func Template() *Config {
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT", "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT",
}, },
Filesystem: []FilesystemConfigJSON{ Filesystem: []FilesystemConfigJSON{
{&FSBind{Target: container.AbsFHSRoot, Source: container.AbsFHSVarLib.Append("hakurei/base/org.debian"), Write: true, Special: true}}, {&FSBind{Target: fhs.AbsRoot, Source: fhs.AbsVarLib.Append("hakurei/base/org.debian"), Write: true, Special: true}},
{&FSBind{Target: container.AbsFHSEtc, Source: container.AbsFHSEtc, Special: true}}, {&FSBind{Target: fhs.AbsEtc, Source: fhs.AbsEtc, Special: true}},
{&FSEphemeral{Target: container.AbsFHSTmp, Write: true, Perm: 0755}}, {&FSEphemeral{Target: fhs.AbsTmp, Write: true, Perm: 0755}},
{&FSOverlay{ {&FSOverlay{
Target: check.MustAbs("/nix/store"), Target: check.MustAbs("/nix/store"),
Lower: []*check.Absolute{check.MustAbs("/mnt-root/nix/.ro-store")}, Lower: []*check.Absolute{check.MustAbs("/mnt-root/nix/.ro-store")},
@ -122,18 +122,18 @@ func Template() *Config {
Work: check.MustAbs("/mnt-root/nix/.rw-store/work"), Work: check.MustAbs("/mnt-root/nix/.rw-store/work"),
}}, }},
{&FSBind{Source: check.MustAbs("/nix/store")}}, {&FSBind{Source: check.MustAbs("/nix/store")}},
{&FSLink{Target: container.AbsFHSRun.Append("current-system"), Linkname: "/run/current-system", Dereference: true}}, {&FSLink{Target: fhs.AbsRun.Append("current-system"), Linkname: "/run/current-system", Dereference: true}},
{&FSLink{Target: container.AbsFHSRun.Append("opengl-driver"), Linkname: "/run/opengl-driver", Dereference: true}}, {&FSLink{Target: fhs.AbsRun.Append("opengl-driver"), Linkname: "/run/opengl-driver", Dereference: true}},
{&FSBind{Source: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), {&FSBind{Source: fhs.AbsVarLib.Append("hakurei/u0/org.chromium.Chromium"),
Target: check.MustAbs("/data/data/org.chromium.Chromium"), Write: true, Ensure: true}}, Target: check.MustAbs("/data/data/org.chromium.Chromium"), Write: true, Ensure: true}},
{&FSBind{Source: container.AbsFHSDev.Append("dri"), Device: true, Optional: true}}, {&FSBind{Source: fhs.AbsDev.Append("dri"), Device: true, Optional: true}},
}, },
Username: "chronos", Username: "chronos",
Shell: container.AbsFHSRun.Append("current-system/sw/bin/zsh"), Shell: fhs.AbsRun.Append("current-system/sw/bin/zsh"),
Home: check.MustAbs("/data/data/org.chromium.Chromium"), Home: check.MustAbs("/data/data/org.chromium.Chromium"),
Path: container.AbsFHSRun.Append("current-system/sw/bin/chromium"), Path: fhs.AbsRun.Append("current-system/sw/bin/chromium"),
Args: []string{ Args: []string{
"chromium", "chromium",
"--ignore-gpu-blocklist", "--ignore-gpu-blocklist",

View File

@ -17,6 +17,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/bits" "hakurei.app/container/bits"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/app/state" "hakurei.app/internal/app/state"
"hakurei.app/system" "hakurei.app/system"
@ -42,19 +43,19 @@ func TestApp(t *testing.T) {
Filesystem: []hst.FilesystemConfigJSON{ Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Target: container.AbsFHSRoot, Target: fhs.AbsRoot,
Source: container.AbsFHSRoot, Source: fhs.AbsRoot,
Write: true, Write: true,
Special: true, Special: true,
}}, }},
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Source: container.AbsFHSDev.Append("kvm"), Source: fhs.AbsDev.Append("kvm"),
Device: true, Device: true,
Optional: true, Optional: true,
}}, }},
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Target: container.AbsFHSEtc, Target: fhs.AbsEtc,
Source: container.AbsFHSEtc, Source: fhs.AbsEtc,
Special: true, Special: true,
}}, }},
}, },
@ -160,24 +161,24 @@ func TestApp(t *testing.T) {
Filesystem: []hst.FilesystemConfigJSON{ Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Target: container.AbsFHSRoot, Target: fhs.AbsRoot,
Source: container.AbsFHSRoot, Source: fhs.AbsRoot,
Write: true, Write: true,
Special: true, Special: true,
}}, }},
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Source: container.AbsFHSDev.Append("dri"), Source: fhs.AbsDev.Append("dri"),
Device: true, Device: true,
Optional: true, Optional: true,
}}, }},
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Source: container.AbsFHSDev.Append("kvm"), Source: fhs.AbsDev.Append("kvm"),
Device: true, Device: true,
Optional: true, Optional: true,
}}, }},
{FilesystemConfig: &hst.FSBind{ {FilesystemConfig: &hst.FSBind{
Target: container.AbsFHSEtc, Target: fhs.AbsEtc,
Source: container.AbsFHSEtc, Source: fhs.AbsEtc,
Special: true, Special: true,
}}, }},
}, },

View File

@ -7,6 +7,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/stub" "hakurei.app/container/stub"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -23,26 +24,26 @@ func TestEnvPaths(t *testing.T) {
{"zero", new(EnvPaths), hst.Paths{}, "attempting to use an invalid EnvPaths"}, {"zero", new(EnvPaths), hst.Paths{}, "attempting to use an invalid EnvPaths"},
{"nil tempdir", &EnvPaths{ {"nil tempdir", &EnvPaths{
RuntimePath: container.AbsFHSTmp, RuntimePath: fhs.AbsTmp,
}, hst.Paths{}, "attempting to use an invalid EnvPaths"}, }, hst.Paths{}, "attempting to use an invalid EnvPaths"},
{"nil runtime", &EnvPaths{ {"nil runtime", &EnvPaths{
TempDir: container.AbsFHSTmp, TempDir: fhs.AbsTmp,
}, hst.Paths{ }, hst.Paths{
TempDir: container.AbsFHSTmp, TempDir: fhs.AbsTmp,
SharePath: container.AbsFHSTmp.Append("hakurei.3735928559"), SharePath: fhs.AbsTmp.Append("hakurei.3735928559"),
RuntimePath: container.AbsFHSTmp.Append("hakurei.3735928559/run/compat"), RuntimePath: fhs.AbsTmp.Append("hakurei.3735928559/run/compat"),
RunDirPath: container.AbsFHSTmp.Append("hakurei.3735928559/run"), RunDirPath: fhs.AbsTmp.Append("hakurei.3735928559/run"),
}, ""}, }, ""},
{"full", &EnvPaths{ {"full", &EnvPaths{
TempDir: container.AbsFHSTmp, TempDir: fhs.AbsTmp,
RuntimePath: container.AbsFHSRunUser.Append("1000"), RuntimePath: fhs.AbsRunUser.Append("1000"),
}, hst.Paths{ }, hst.Paths{
TempDir: container.AbsFHSTmp, TempDir: fhs.AbsTmp,
SharePath: container.AbsFHSTmp.Append("hakurei.3735928559"), SharePath: fhs.AbsTmp.Append("hakurei.3735928559"),
RuntimePath: container.AbsFHSRunUser.Append("1000"), RuntimePath: fhs.AbsRunUser.Append("1000"),
RunDirPath: container.AbsFHSRunUser.Append("1000/hakurei"), RunDirPath: fhs.AbsRunUser.Append("1000/hakurei"),
}, ""}, }, ""},
} }
for _, tc := range testCases { for _, tc := range testCases {

View File

@ -16,6 +16,7 @@ import (
"syscall" "syscall"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/app/state" "hakurei.app/internal/app/state"
"hakurei.app/system" "hakurei.app/system"
@ -184,7 +185,7 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, id *state.ID,
// mount root read-only as the final setup Op // mount root read-only as the final setup Op
// TODO(ophestra): move this to spFilesystemOp after #8 and #9 // TODO(ophestra): move this to spFilesystemOp after #8 and #9
k.container.Remount(container.AbsFHSRoot, syscall.MS_RDONLY) k.container.Remount(fhs.AbsRoot, syscall.MS_RDONLY)
// append ExtraPerms last // append ExtraPerms last
for _, p := range config.ExtraPerms { for _, p := range config.ExtraPerms {

View File

@ -10,6 +10,7 @@ import (
"sync" "sync"
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -45,7 +46,7 @@ func (h *Hsu) ID() (int, error) {
cmd.Path = hsuPath cmd.Path = hsuPath
cmd.Stderr = os.Stderr // pass through fatal messages cmd.Stderr = os.Stderr // pass through fatal messages
cmd.Env = make([]string, 0) cmd.Env = make([]string, 0)
cmd.Dir = container.FHSRoot cmd.Dir = fhs.Root
var ( var (
p []byte p []byte
exitError *exec.ExitError exitError *exec.ExitError

View File

@ -14,6 +14,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal" "hakurei.app/internal"
"hakurei.app/internal/app/state" "hakurei.app/internal/app/state"
@ -253,7 +254,7 @@ func (k *outcome) main(msg container.Msg) {
ms.cmd = exec.CommandContext(ctx, hsuPath.String()) ms.cmd = exec.CommandContext(ctx, hsuPath.String())
ms.cmd.Stdin, ms.cmd.Stdout, ms.cmd.Stderr = os.Stdin, os.Stdout, os.Stderr ms.cmd.Stdin, ms.cmd.Stdout, ms.cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
ms.cmd.Dir = container.FHSRoot // container init enters final working directory ms.cmd.Dir = fhs.Root // container init enters final working directory
// shim runs in the same session as monitor; see shim.go for behaviour // shim runs in the same session as monitor; see shim.go for behaviour
ms.cmd.Cancel = func() error { return ms.cmd.Process.Signal(syscall.SIGCONT) } ms.cmd.Cancel = func() error { return ms.cmd.Process.Signal(syscall.SIGCONT) }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"syscall" "syscall"
"hakurei.app/container" "hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
) )
@ -34,14 +34,14 @@ func (s spAccountOp) toContainer(state *outcomeStateParams) error {
state.env["SHELL"] = state.Container.Shell.String() state.env["SHELL"] = state.Container.Shell.String()
state.params. state.params.
Place(container.AbsFHSEtc.Append("passwd"), Place(fhs.AbsEtc.Append("passwd"),
[]byte(state.Container.Username+":x:"+ []byte(state.Container.Username+":x:"+
state.mapuid.String()+":"+ state.mapuid.String()+":"+
state.mapgid.String()+ state.mapgid.String()+
":Hakurei:"+ ":Hakurei:"+
state.Container.Home.String()+":"+ state.Container.Home.String()+":"+
state.Container.Shell.String()+"\n")). state.Container.Shell.String()+"\n")).
Place(container.AbsFHSEtc.Append("group"), Place(fhs.AbsEtc.Append("group"),
[]byte("hakurei:x:"+state.mapgid.String()+":\n")) []byte("hakurei:x:"+state.mapgid.String()+":\n"))
return nil return nil

View File

@ -10,12 +10,13 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/bits" "hakurei.app/container/bits"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system/dbus" "hakurei.app/system/dbus"
) )
const varRunNscd = container.FHSVar + "run/nscd" const varRunNscd = fhs.Var + "run/nscd"
// spParamsOp initialises unordered fields of [container.Params] and the optional root filesystem. // spParamsOp initialises unordered fields of [container.Params] and the optional root filesystem.
// This outcomeOp is hardcoded to always run first. // This outcomeOp is hardcoded to always run first.
@ -98,15 +99,15 @@ func (s *spParamsOp) toContainer(state *outcomeStateParams) error {
// early mount points // early mount points
state.params. state.params.
Proc(container.AbsFHSProc). Proc(fhs.AbsProc).
Tmpfs(hst.AbsTmp, 1<<12, 0755) Tmpfs(hst.AbsTmp, 1<<12, 0755)
if !state.Container.Device { if !state.Container.Device {
state.params.DevWritable(container.AbsFHSDev, true) state.params.DevWritable(fhs.AbsDev, true)
} else { } else {
state.params.Bind(container.AbsFHSDev, container.AbsFHSDev, container.BindWritable|container.BindDevice) state.params.Bind(fhs.AbsDev, fhs.AbsDev, container.BindWritable|container.BindDevice)
} }
// /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it // /dev is mounted readonly later on, this prevents /dev/shm from going readonly with it
state.params.Tmpfs(container.AbsFHSDev.Append("shm"), 0, 01777) state.params.Tmpfs(fhs.AbsDev.Append("shm"), 0, 01777)
return nil return nil
} }
@ -142,7 +143,7 @@ func (s spFilesystemOp) toSystem(state *outcomeStateSys, _ *hst.Config) error {
if path.IsAbs(pair[1]) { if path.IsAbs(pair[1]) {
// get parent dir of socket // get parent dir of socket
dir := path.Dir(pair[1]) dir := path.Dir(pair[1])
if dir == "." || dir == container.FHSRoot { if dir == "." || dir == fhs.Root {
state.msg.Verbosef("dbus socket %q is in an unusual location", pair[1]) state.msg.Verbosef("dbus socket %q is in an unusual location", pair[1])
} }
hidePaths = append(hidePaths, dir) hidePaths = append(hidePaths, dir)
@ -267,7 +268,7 @@ func (s spFilesystemOp) toContainer(state *outcomeStateParams) error {
// no more configured paths beyond this point // no more configured paths beyond this point
if !state.Container.Device { if !state.Container.Device {
state.params.Remount(container.AbsFHSDev, syscall.MS_RDONLY) state.params.Remount(fhs.AbsDev, syscall.MS_RDONLY)
} }
return nil return nil
} }
@ -278,7 +279,7 @@ func resolveRoot(c *hst.ContainerConfig) (rootfs hst.FilesystemConfig, filesyste
// root filesystem special case // root filesystem special case
filesystem = c.Filesystem filesystem = c.Filesystem
// valid happens late, so root gets it here // valid happens late, so root gets it here
if len(filesystem) > 0 && filesystem[0].Valid() && filesystem[0].Path().String() == container.FHSRoot { if len(filesystem) > 0 && filesystem[0].Valid() && filesystem[0].Path().String() == fhs.Root {
// if the first element targets /, it is inserted early and excluded from path hiding // if the first element targets /, it is inserted early and excluded from path hiding
rootfs = filesystem[0].FilesystemConfig rootfs = filesystem[0].FilesystemConfig
filesystem = filesystem[1:] filesystem = filesystem[1:]

View File

@ -1,7 +1,7 @@
package app package app
import ( import (
"hakurei.app/container" "hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system/acl" "hakurei.app/system/acl"
"hakurei.app/system/dbus" "hakurei.app/system/dbus"
@ -42,7 +42,7 @@ func (s *spDBusOp) toContainer(state *outcomeStateParams) error {
state.env["DBUS_SESSION_BUS_ADDRESS"] = "unix:path=" + sessionInner.String() state.env["DBUS_SESSION_BUS_ADDRESS"] = "unix:path=" + sessionInner.String()
state.params.Bind(state.instancePath().Append("bus"), sessionInner, 0) state.params.Bind(state.instancePath().Append("bus"), sessionInner, 0)
if s.ProxySystem { if s.ProxySystem {
systemInner := container.AbsFHSRun.Append("dbus/system_bus_socket") systemInner := fhs.AbsRun.Append("dbus/system_bus_socket")
state.env["DBUS_SYSTEM_BUS_ADDRESS"] = "unix:path=" + systemInner.String() state.env["DBUS_SYSTEM_BUS_ADDRESS"] = "unix:path=" + systemInner.String()
state.params.Bind(state.instancePath().Append("system_bus_socket"), systemInner, 0) state.params.Bind(state.instancePath().Append("system_bus_socket"), systemInner, 0)
} }

View File

@ -3,6 +3,7 @@ package app
import ( import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
"hakurei.app/system/acl" "hakurei.app/system/acl"
@ -27,13 +28,13 @@ func (s spRuntimeOp) toContainer(state *outcomeStateParams) error {
xdgSessionType = "XDG_SESSION_TYPE" xdgSessionType = "XDG_SESSION_TYPE"
) )
state.runtimeDir = container.AbsFHSRunUser.Append(state.mapuid.String()) state.runtimeDir = fhs.AbsRunUser.Append(state.mapuid.String())
state.env[xdgRuntimeDir] = state.runtimeDir.String() state.env[xdgRuntimeDir] = state.runtimeDir.String()
state.env[xdgSessionClass] = "user" state.env[xdgSessionClass] = "user"
state.env[xdgSessionType] = "tty" state.env[xdgSessionType] = "tty"
_, runtimeDirInst := s.commonPaths(state.outcomeState) _, runtimeDirInst := s.commonPaths(state.outcomeState)
state.params.Tmpfs(container.AbsFHSRunUser, 1<<12, 0755) state.params.Tmpfs(fhs.AbsRunUser, 1<<12, 0755)
state.params.Bind(runtimeDirInst, state.runtimeDir, container.BindWritable) state.params.Bind(runtimeDirInst, state.runtimeDir, container.BindWritable)
return nil return nil
} }

View File

@ -3,6 +3,7 @@ package app
import ( import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system" "hakurei.app/system"
"hakurei.app/system/acl" "hakurei.app/system/acl"
@ -23,7 +24,7 @@ func (s spTmpdirOp) toSystem(state *outcomeStateSys, _ *hst.Config) error {
func (s spTmpdirOp) toContainer(state *outcomeStateParams) error { func (s spTmpdirOp) toContainer(state *outcomeStateParams) error {
// 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
_, tmpdirInst := s.commonPaths(state.outcomeState) _, tmpdirInst := s.commonPaths(state.outcomeState)
state.params.Bind(tmpdirInst, container.AbsFHSTmp, container.BindWritable) state.params.Bind(tmpdirInst, fhs.AbsTmp, container.BindWritable)
return nil return nil
} }

View File

@ -7,13 +7,13 @@ import (
"strconv" "strconv"
"strings" "strings"
"hakurei.app/container"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/system/acl" "hakurei.app/system/acl"
) )
var absX11SocketDir = container.AbsFHSTmp.Append(".X11-unix") var absX11SocketDir = fhs.AbsTmp.Append(".X11-unix")
// spX11Op exports the X11 display server to the container. // spX11Op exports the X11 display server to the container.
type spX11Op struct { type spX11Op struct {

View File

@ -11,6 +11,7 @@ import (
"hakurei.app/container" "hakurei.app/container"
"hakurei.app/container/bits" "hakurei.app/container/bits"
"hakurei.app/container/check" "hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp" "hakurei.app/container/seccomp"
) )
@ -43,9 +44,9 @@ func Exec(ctx context.Context, msg container.Msg, p string) ([]*Entry, error) {
z.Stdout = stdout z.Stdout = stdout
z.Stderr = stderr z.Stderr = stderr
z. z.
Bind(container.AbsFHSRoot, container.AbsFHSRoot, 0). Bind(fhs.AbsRoot, fhs.AbsRoot, 0).
Proc(container.AbsFHSProc). Proc(fhs.AbsProc).
Dev(container.AbsFHSDev, false) Dev(fhs.AbsDev, false)
if err := z.Start(); err != nil { if err := z.Start(); err != nil {
return nil, err return nil, err