From c6be82bcf91fc4b6e61d9df40213e80367addbd8 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 3 Aug 2025 20:46:41 +0900 Subject: container/path: fhs path constants This increases readability since this can help disambiguate absolute paths from similarly named path segments. Signed-off-by: Ophestra --- container/autoetc.go | 8 ++++---- container/autoroot.go | 2 +- container/container.go | 8 ++------ container/init.go | 16 ++++++++-------- container/mount.go | 2 +- container/ops.go | 10 +++++----- container/path.go | 44 ++++++++++++++++++++++++++++++++++++++++++-- container/sysctl.go | 6 +++--- 8 files changed, 66 insertions(+), 30 deletions(-) (limited to 'container') diff --git a/container/autoetc.go b/container/autoetc.go index 103bd35b..3e23c160 100644 --- a/container/autoetc.go +++ b/container/autoetc.go @@ -12,7 +12,7 @@ func init() { gob.Register(new(AutoEtcOp)) } // This is not a generic setup op. It is implemented here to reduce ipc overhead. func (f *Ops) Etc(host, prefix string) *Ops { e := &AutoEtcOp{prefix} - f.Mkdir("/etc", 0755) + f.Mkdir(FHSEtc, 0755) f.Bind(host, e.hostPath(), 0) *f = append(*f, e) return f @@ -22,7 +22,7 @@ type AutoEtcOp struct{ Prefix string } func (e *AutoEtcOp) early(*Params) error { return nil } func (e *AutoEtcOp) apply(*Params) error { - const target = sysrootPath + "/etc/" + const target = sysrootPath + FHSEtc rel := e.hostRel() + "/" if err := os.MkdirAll(target, 0755); err != nil { @@ -40,7 +40,7 @@ func (e *AutoEtcOp) apply(*Params) error { case "group": case "mtab": - if err = os.Symlink("/proc/mounts", target+n); err != nil { + if err = os.Symlink(FHSProc+"mounts", target+n); err != nil { return wrapErrSelf(err) } @@ -54,7 +54,7 @@ func (e *AutoEtcOp) apply(*Params) error { return nil } -func (e *AutoEtcOp) hostPath() string { return "/etc/" + e.hostRel() } +func (e *AutoEtcOp) hostPath() string { return FHSEtc + e.hostRel() } func (e *AutoEtcOp) hostRel() string { return ".host/" + e.Prefix } func (e *AutoEtcOp) Is(op Op) bool { diff --git a/container/autoroot.go b/container/autoroot.go index b6375b8c..5ed9b6c7 100644 --- a/container/autoroot.go +++ b/container/autoroot.go @@ -42,7 +42,7 @@ func (r *AutoRootOp) early(params *Params) error { if IsAutoRootBindable(name) { op := &BindMountOp{ Source: path.Join(r.Host, name), - Target: "/" + name, + Target: FHSRoot + name, Flags: r.Flags, } if err = op.early(params); err != nil { diff --git a/container/container.go b/container/container.go index efbfc210..5a7858f1 100644 --- a/container/container.go +++ b/container/container.go @@ -18,10 +18,6 @@ import ( ) const ( - // Nonexistent is a path that cannot exist. - // /proc is chosen because a system with covered /proc is unsupported by this package. - Nonexistent = "/proc/nonexistent" - // CancelSignal is the signal expected by container init on context cancel. // A custom [Container.Cancel] function must eventually deliver this signal. CancelSignal = SIGTERM @@ -142,7 +138,7 @@ func (p *Container) Start() error { } else { p.cmd.Cancel = func() error { return p.cmd.Process.Signal(CancelSignal) } } - p.cmd.Dir = "/" + p.cmd.Dir = FHSRoot p.cmd.SysProcAttr = &SysProcAttr{ Setsid: !p.RetainSession, Pdeathsig: SIGKILL, @@ -251,6 +247,6 @@ func (p *Container) ProcessState() *os.ProcessState { func New(ctx context.Context, name string, args ...string) *Container { return &Container{name: name, ctx: ctx, - Params: Params{Args: append([]string{name}, args...), Dir: "/", Ops: new(Ops)}, + Params: Params{Args: append([]string{name}, args...), Dir: FHSRoot, Ops: new(Ops)}, } } diff --git a/container/init.go b/container/init.go index 8b178d8c..68132437 100644 --- a/container/init.go +++ b/container/init.go @@ -31,7 +31,7 @@ const ( it should be noted that none of this should become relevant at any point since the resulting intermediate root tmpfs should be effectively anonymous */ - intermediateHostPath = "/proc/self/fd" + intermediateHostPath = FHSProc + "self/fd" // setup params file descriptor setupEnv = "HAKUREI_SETUP" @@ -88,17 +88,17 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) { if err := SetDumpable(SUID_DUMP_USER); err != nil { log.Fatalf("cannot set SUID_DUMP_USER: %s", err) } - if err := os.WriteFile("/proc/self/uid_map", + if err := os.WriteFile(FHSProc+"self/uid_map", append([]byte{}, strconv.Itoa(params.Uid)+" "+strconv.Itoa(params.HostUid)+" 1\n"...), 0); err != nil { log.Fatalf("%v", err) } - if err := os.WriteFile("/proc/self/setgroups", + if err := os.WriteFile(FHSProc+"self/setgroups", []byte("deny\n"), 0); err != nil && !os.IsNotExist(err) { log.Fatalf("%v", err) } - if err := os.WriteFile("/proc/self/gid_map", + if err := os.WriteFile(FHSProc+"self/gid_map", append([]byte{}, strconv.Itoa(params.Gid)+" "+strconv.Itoa(params.HostGid)+" 1\n"...), 0); err != nil { log.Fatalf("%v", err) @@ -117,7 +117,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) { // cache sysctl before pivot_root LastCap() - if err := Mount("", "/", "", MS_SILENT|MS_SLAVE|MS_REC, ""); err != nil { + if err := Mount("", FHSRoot, "", MS_SILENT|MS_SLAVE|MS_REC, ""); err != nil { log.Fatalf("cannot make / rslave: %v", err) } @@ -159,7 +159,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) { if err := PivotRoot(intermediateHostPath, hostDir); err != nil { log.Fatalf("cannot pivot into intermediate root: %v", err) } - if err := os.Chdir("/"); err != nil { + if err := os.Chdir(FHSRoot); err != nil { log.Fatalf("%v", err) } @@ -189,7 +189,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) { { var fd int if err := IgnoringEINTR(func() (err error) { - fd, err = Open("/", O_DIRECTORY|O_RDONLY, 0) + fd, err = Open(FHSRoot, O_DIRECTORY|O_RDONLY, 0) return }); err != nil { log.Fatalf("cannot open intermediate root: %v", err) @@ -207,7 +207,7 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) { if err := Unmount(".", MNT_DETACH); err != nil { log.Fatalf("cannot unmount intemediate root: %v", err) } - if err := os.Chdir("/"); err != nil { + if err := os.Chdir(FHSRoot); err != nil { log.Fatalf("%v", err) } diff --git a/container/mount.go b/container/mount.go index 30ef7008..919b6e02 100644 --- a/container/mount.go +++ b/container/mount.go @@ -53,7 +53,7 @@ const ( FstypeNULL = zeroString // FstypeProc represents the proc pseudo-filesystem. // 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 /proc. + // This filesystem type is usually mounted on [FHSProc]. FstypeProc = "proc" // FstypeDevpts represents the devpts pseudo-filesystem. // This type of filesystem is usually mounted on /dev/pts. diff --git a/container/ops.go b/container/ops.go index e3eb45f8..8d9d1691 100644 --- a/container/ops.go +++ b/container/ops.go @@ -215,7 +215,7 @@ func (d *MountDevOp) apply(params *Params) error { return err } if err := hostProc.bindMount( - toHost("/dev/"+name), + toHost(FHSDev+name), targetPath, 0, true, @@ -225,15 +225,15 @@ func (d *MountDevOp) apply(params *Params) error { } for i, name := range []string{"stdin", "stdout", "stderr"} { if err := os.Symlink( - "/proc/self/fd/"+string(rune(i+'0')), + FHSProc+"self/fd/"+string(rune(i+'0')), path.Join(target, name), ); err != nil { return wrapErrSelf(err) } } for _, pair := range [][2]string{ - {"/proc/self/fd", "fd"}, - {"/proc/kcore", "core"}, + {FHSProc + "self/fd", "fd"}, + {FHSProc + "kcore", "core"}, {"pts/ptmx", "ptmx"}, } { if err := os.Symlink(pair[0], path.Join(target, pair[1])); err != nil { @@ -436,7 +436,7 @@ func (t *TmpfileOp) apply(params *Params) error { } var tmpPath string - if f, err := os.CreateTemp("/", "tmp.*"); err != nil { + if f, err := os.CreateTemp(FHSRoot, "tmp.*"); err != nil { return wrapErrSelf(err) } else if _, err = f.Write(t.Data); err != nil { return wrapErrSuffix(err, diff --git a/container/path.go b/container/path.go index 632892af..b1126fdd 100644 --- a/container/path.go +++ b/container/path.go @@ -14,9 +14,49 @@ import ( ) const ( - hostPath = "/" + hostDir + // 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/" +) + +const ( + // Nonexistent is a path that cannot exist. + // /proc is chosen because a system with covered /proc is unsupported by this package. + Nonexistent = FHSProc + "nonexistent" + + hostPath = FHSRoot + hostDir hostDir = "host" - sysrootPath = "/" + sysrootDir + sysrootPath = FHSRoot + sysrootDir sysrootDir = "sysroot" ) diff --git a/container/sysctl.go b/container/sysctl.go index 7fcb94bd..bfcf2788 100644 --- a/container/sysctl.go +++ b/container/sysctl.go @@ -17,9 +17,9 @@ var ( ) const ( - kernelOverflowuidPath = "/proc/sys/kernel/overflowuid" - kernelOverflowgidPath = "/proc/sys/kernel/overflowgid" - kernelCapLastCapPath = "/proc/sys/kernel/cap_last_cap" + kernelOverflowuidPath = FHSProcSys + "kernel/overflowuid" + kernelOverflowgidPath = FHSProcSys + "kernel/overflowgid" + kernelCapLastCapPath = FHSProcSys + "kernel/cap_last_cap" ) func mustReadSysctl() { -- cgit v1.3.1