From e99d7affb0c128fa82722f9b3d79c99b5e5918cd Mon Sep 17 00:00:00 2001 From: Ophestra Date: Mon, 11 Aug 2025 02:52:32 +0900 Subject: container: use absolute for pathname This is simultaneously more efficient and less error-prone. This change caused minor API changes in multiple other packages. Signed-off-by: Ophestra --- hst/config.go | 32 +++++++++++++++++++------------- hst/container.go | 25 +++++++++++++++---------- hst/paths.go | 10 +++++++--- hst/template.go | 36 ++++++++++++++++++------------------ hst/template_test.go | 10 +++++----- 5 files changed, 64 insertions(+), 49 deletions(-) (limited to 'hst') diff --git a/hst/config.go b/hst/config.go index 8c883c9a..73fb21b8 100644 --- a/hst/config.go +++ b/hst/config.go @@ -2,12 +2,15 @@ package hst import ( + "hakurei.app/container" "hakurei.app/system" "hakurei.app/system/dbus" ) const Tmp = "/.hakurei" +var AbsTmp = container.MustAbs(Tmp) + // Config is used to seal an app implementation. type Config struct { // reverse-DNS style arbitrary identifier string from config; @@ -16,7 +19,7 @@ type Config struct { ID string `json:"id"` // absolute path to executable file - Path string `json:"path,omitempty"` + Path *container.Absolute `json:"path,omitempty"` // final args passed to container init Args []string `json:"args"` @@ -35,12 +38,12 @@ type Config struct { // passwd username in container, defaults to passwd name of target uid or chronos Username string `json:"username,omitempty"` - // absolute path to shell, empty for host shell - Shell string `json:"shell,omitempty"` + // absolute path to shell + Shell *container.Absolute `json:"shell"` // absolute path to home directory in the init mount namespace - Data string `json:"data"` - // directory to enter and use as home in the container mount namespace, empty for Data - Dir string `json:"dir"` + Data *container.Absolute `json:"data"` + // directory to enter and use as home in the container mount namespace, nil for Data + Dir *container.Absolute `json:"dir,omitempty"` // extra acl ops, dispatches before container init ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"` @@ -55,21 +58,24 @@ type Config struct { // ExtraPermConfig describes an acl update op. type ExtraPermConfig struct { - Ensure bool `json:"ensure,omitempty"` - Path string `json:"path"` - Read bool `json:"r,omitempty"` - Write bool `json:"w,omitempty"` - Execute bool `json:"x,omitempty"` + Ensure bool `json:"ensure,omitempty"` + Path *container.Absolute `json:"path"` + Read bool `json:"r,omitempty"` + Write bool `json:"w,omitempty"` + Execute bool `json:"x,omitempty"` } func (e *ExtraPermConfig) String() string { - buf := make([]byte, 0, 5+len(e.Path)) + if e.Path == nil { + return "" + } + buf := make([]byte, 0, 5+len(e.Path.String())) buf = append(buf, '-', '-', '-') if e.Ensure { buf = append(buf, '+') } buf = append(buf, ':') - buf = append(buf, []byte(e.Path)...) + buf = append(buf, []byte(e.Path.String())...) if e.Read { buf[0] = 'r' } diff --git a/hst/container.go b/hst/container.go index ebce07b9..0b51e101 100644 --- a/hst/container.go +++ b/hst/container.go @@ -3,14 +3,11 @@ package hst import ( "time" + "hakurei.app/container" "hakurei.app/container/seccomp" ) const ( - // SourceTmpfs causes tmpfs to be mounted on [FilesystemConfig.Dst] - // when assigned to [FilesystemConfig.Src]. - SourceTmpfs = "tmpfs" - // TmpfsPerm is the permission bits for tmpfs mount points // configured through [FilesystemConfig]. TmpfsPerm = 0755 @@ -55,18 +52,18 @@ type ( // pass through all devices Device bool `json:"device,omitempty"` // container host filesystem bind mounts - Filesystem []*FilesystemConfig `json:"filesystem"` + Filesystem []FilesystemConfig `json:"filesystem"` // create symlinks inside container filesystem - Link [][2]string `json:"symlink"` + Link []LinkConfig `json:"symlink"` // automatically bind mount top-level directories to container root; // the zero value disables this behaviour - AutoRoot string `json:"auto_root,omitempty"` + AutoRoot *container.Absolute `json:"auto_root,omitempty"` // extra flags for AutoRoot RootFlags int `json:"root_flags,omitempty"` // read-only /etc directory - Etc string `json:"etc,omitempty"` + Etc *container.Absolute `json:"etc,omitempty"` // automatically set up /etc symlinks AutoEtc bool `json:"auto_etc"` } @@ -74,9 +71,9 @@ type ( // FilesystemConfig is an abstract representation of a bind mount. FilesystemConfig struct { // mount point in container, same as src if empty - Dst string `json:"dst,omitempty"` + Dst *container.Absolute `json:"dst,omitempty"` // host filesystem path to make available to the container - Src string `json:"src"` + Src *container.Absolute `json:"src"` // do not mount filesystem read-only Write bool `json:"write,omitempty"` // do not disable device files @@ -84,4 +81,12 @@ type ( // fail if the bind mount cannot be established for any reason Must bool `json:"require,omitempty"` } + + LinkConfig struct { + // symlink target in container + Target *container.Absolute `json:"target"` + // linkname the symlink points to; + // prepend '*' to dereference an absolute pathname on host + Linkname string `json:"linkname"` + } ) diff --git a/hst/paths.go b/hst/paths.go index 31c14df2..7410d7a0 100644 --- a/hst/paths.go +++ b/hst/paths.go @@ -1,11 +1,15 @@ package hst +import "hakurei.app/container" + // Paths contains environment-dependent paths used by hakurei. type Paths struct { + // temporary directory returned by [os.TempDir] (usually `/tmp`) + TempDir *container.Absolute `json:"temp_dir"` // path to shared directory (usually `/tmp/hakurei.%d`) - SharePath string `json:"share_path"` + SharePath *container.Absolute `json:"share_path"` // XDG_RUNTIME_DIR value (usually `/run/user/%d`) - RuntimePath string `json:"runtime_path"` + RuntimePath *container.Absolute `json:"runtime_path"` // application runtime directory (usually `/run/user/%d/hakurei`) - RunDirPath string `json:"run_dir_path"` + RunDirPath *container.Absolute `json:"run_dir_path"` } diff --git a/hst/template.go b/hst/template.go index 32d84cd4..dda43a03 100644 --- a/hst/template.go +++ b/hst/template.go @@ -12,7 +12,7 @@ func Template() *Config { return &Config{ ID: "org.chromium.Chromium", - Path: container.FHSRun + "current-system/sw/bin/chromium", + Path: container.AbsFHSRun.Append("current-system/sw/bin/chromium"), Args: []string{ "chromium", "--ignore-gpu-blocklist", @@ -46,12 +46,12 @@ func Template() *Config { DirectWayland: false, Username: "chronos", - Shell: container.FHSRun + "current-system/sw/bin/zsh", - Data: container.FHSVarLib + "hakurei/u0/org.chromium.Chromium", - Dir: "/data/data/org.chromium.Chromium", + Shell: container.AbsFHSRun.Append("current-system/sw/bin/zsh"), + Data: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), + Dir: container.MustAbs("/data/data/org.chromium.Chromium"), ExtraPerms: []*ExtraPermConfig{ - {Path: container.FHSVarLib + "hakurei/u0", Ensure: true, Execute: true}, - {Path: container.FHSVarLib + "hakurei/u0/org.chromium.Chromium", Read: true, Write: true, Execute: true}, + {Path: container.AbsFHSVarLib.Append("hakurei/u0"), Ensure: true, Execute: true}, + {Path: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), Read: true, Write: true, Execute: true}, }, Identity: 9, @@ -77,20 +77,20 @@ func Template() *Config { "GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com", "GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT", }, - Filesystem: []*FilesystemConfig{ - {Dst: container.FHSTmp, Src: SourceTmpfs, Write: true}, - {Src: "/nix/store"}, - {Src: container.FHSRun + "current-system"}, - {Src: container.FHSRun + "opengl-driver"}, - {Src: container.FHSVar + "db/nix-channels"}, - {Src: container.FHSVarLib + "hakurei/u0/org.chromium.Chromium", - Dst: "/data/data/org.chromium.Chromium", Write: true, Must: true}, - {Src: container.FHSDev + "dri", Device: true}, + Filesystem: []FilesystemConfig{ + {Dst: container.AbsFHSTmp, Src: container.AbsNonexistent, Write: true}, + {Src: container.MustAbs("/nix/store")}, + {Src: container.AbsFHSRun.Append("current-system")}, + {Src: container.AbsFHSRun.Append("opengl-driver")}, + {Src: container.AbsFHSVar.Append("db/nix-channels")}, + {Src: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), + Dst: container.MustAbs("/data/data/org.chromium.Chromium"), Write: true, Must: true}, + {Src: container.AbsFHSDev.Append("dri"), Device: true}, }, - Link: [][2]string{{container.FHSRunUser + "65534", container.FHSRunUser + "150"}}, - AutoRoot: container.FHSVarLib + "hakurei/base/org.debian", + Link: []LinkConfig{{container.AbsFHSRunUser.Append("65534"), container.FHSRunUser + "150"}}, + AutoRoot: container.AbsFHSVarLib.Append("hakurei/base/org.debian"), RootFlags: container.BindWritable, - Etc: container.FHSEtc, + Etc: container.AbsFHSEtc, AutoEtc: true, }, } diff --git a/hst/template_test.go b/hst/template_test.go index cf8ab81c..da119d4f 100644 --- a/hst/template_test.go +++ b/hst/template_test.go @@ -99,7 +99,7 @@ func TestTemplate(t *testing.T) { "filesystem": [ { "dst": "/tmp/", - "src": "tmpfs", + "src": "/proc/nonexistent", "write": true }, { @@ -126,10 +126,10 @@ func TestTemplate(t *testing.T) { } ], "symlink": [ - [ - "/run/user/65534", - "/run/user/150" - ] + { + "target": "/run/user/65534", + "linkname": "/run/user/150" + } ], "auto_root": "/var/lib/hakurei/base/org.debian", "root_flags": 2, -- cgit v1.3.1