From c74c269b66770f0eddde255d2805b79f274409e9 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sat, 28 Feb 2026 20:42:33 +0900 Subject: [PATCH] container: use /proc/self/exe directly This is a more reliable form of pathname to self and also cheaper than os.Executable. Signed-off-by: Ophestra --- cmd/sharefs/fuse.go | 8 ++------ container/container.go | 2 +- container/container_test.go | 5 ++--- container/executable.go | 3 +++ container/fhs/abs.go | 2 ++ container/fhs/fhs.go | 4 ++++ internal/lockedfile/internal/filelock/filelock_test.go | 4 ++-- internal/lockedfile/lockedfile_test.go | 4 ++-- 8 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cmd/sharefs/fuse.go b/cmd/sharefs/fuse.go index d35ff8b..a52ee03 100644 --- a/cmd/sharefs/fuse.go +++ b/cmd/sharefs/fuse.go @@ -33,6 +33,7 @@ import ( "hakurei.app/container" "hakurei.app/container/check" + "hakurei.app/container/fhs" "hakurei.app/container/std" "hakurei.app/hst" "hakurei.app/internal/helper/proc" @@ -441,12 +442,7 @@ func _main(s ...string) (exitCode int) { // keep fuse_parse_cmdline happy in the container z.Tmpfs(check.MustAbs(container.Nonexistent), 1<<10, 0755) - if a, err := check.NewAbs(container.MustExecutable(msg)); err != nil { - log.Println(err) - return 5 - } else { - z.Path = a - } + z.Path = fhs.AbsProcSelfExe z.Args = s z.ForwardCancel = true z.SeccompPresets |= std.PresetStrict diff --git a/container/container.go b/container/container.go index a645771..8b5ec01 100644 --- a/container/container.go +++ b/container/container.go @@ -525,7 +525,7 @@ func New(ctx context.Context, msg message.Msg) *Container { p := &Container{ctx: ctx, msg: msg, Params: Params{Ops: new(Ops)}} c, cancel := context.WithCancel(ctx) p.cancel = cancel - p.cmd = exec.CommandContext(c, MustExecutable(msg)) + p.cmd = exec.CommandContext(c, fhs.ProcSelfExe) return p } diff --git a/container/container_test.go b/container/container_test.go index 852304e..e00a63c 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -773,14 +773,13 @@ func TestMain(m *testing.M) { func helperNewContainerLibPaths(ctx context.Context, libPaths *[]*check.Absolute, args ...string) (c *container.Container) { msg := message.New(nil) msg.SwapVerbose(testing.Verbose()) - executable := check.MustAbs(container.MustExecutable(msg)) c = container.NewCommand(ctx, msg, absHelperInnerPath, "helper", args...) c.Env = append(c.Env, envDoCheck+"=1") - c.Bind(executable, absHelperInnerPath, 0) + c.Bind(fhs.AbsProcSelfExe, absHelperInnerPath, 0) // in case test has cgo enabled - if entries, err := ldd.Resolve(ctx, msg, executable); err != nil { + if entries, err := ldd.Resolve(ctx, msg, nil); err != nil { log.Fatalf("ldd: %v", err) } else { *libPaths = ldd.Path(entries) diff --git a/container/executable.go b/container/executable.go index 67c43a7..b825306 100644 --- a/container/executable.go +++ b/container/executable.go @@ -28,6 +28,9 @@ func copyExecutable(msg message.Msg) { } } +// MustExecutable calls [os.Executable] and terminates the process on error. +// +// Deprecated: This is no longer used and will be removed in 0.4. func MustExecutable(msg message.Msg) string { executableOnce.Do(func() { copyExecutable(msg) }) return executable diff --git a/container/fhs/abs.go b/container/fhs/abs.go index fda6971..45c50bf 100644 --- a/container/fhs/abs.go +++ b/container/fhs/abs.go @@ -42,6 +42,8 @@ var ( AbsDevShm = unsafeAbs(DevShm) // AbsProc is [Proc] as [check.Absolute]. AbsProc = unsafeAbs(Proc) + // AbsProcSelfExe is [ProcSelfExe] as [check.Absolute]. + AbsProcSelfExe = unsafeAbs(ProcSelfExe) // AbsSys is [Sys] as [check.Absolute]. AbsSys = unsafeAbs(Sys) ) diff --git a/container/fhs/fhs.go b/container/fhs/fhs.go index e0c1d86..6d098d0 100644 --- a/container/fhs/fhs.go +++ b/container/fhs/fhs.go @@ -41,6 +41,10 @@ const ( // ProcSys points to a hierarchy below /proc/ that exposes a number of // kernel tunables. ProcSys = Proc + "sys/" + // ProcSelf resolves to the process's own /proc/pid directory. + ProcSelf = Proc + "self/" + // ProcSelfExe is a symbolic link to program pathname. + ProcSelfExe = ProcSelf + "exe" // Sys points to a virtual kernel file system exposing discovered devices // and other functionality. Sys = "/sys/" diff --git a/internal/lockedfile/internal/filelock/filelock_test.go b/internal/lockedfile/internal/filelock/filelock_test.go index 4e40739..4498423 100644 --- a/internal/lockedfile/internal/filelock/filelock_test.go +++ b/internal/lockedfile/internal/filelock/filelock_test.go @@ -14,7 +14,7 @@ import ( "testing" "time" - "hakurei.app/container" + "hakurei.app/container/fhs" "hakurei.app/internal/lockedfile/internal/filelock" "hakurei.app/internal/lockedfile/internal/testexec" ) @@ -197,7 +197,7 @@ func TestLockNotDroppedByExecCommand(t *testing.T) { // Some kinds of file locks are dropped when a duplicated or forked file // descriptor is unlocked. Double-check that the approach used by os/exec does // not accidentally drop locks. - cmd := testexec.CommandContext(t, t.Context(), container.MustExecutable(nil), "-test.run=^$") + cmd := testexec.CommandContext(t, t.Context(), fhs.ProcSelfExe, "-test.run=^$") if err := cmd.Run(); err != nil { t.Fatalf("exec failed: %v", err) } diff --git a/internal/lockedfile/lockedfile_test.go b/internal/lockedfile/lockedfile_test.go index 6182dd9..7ad3c2c 100644 --- a/internal/lockedfile/lockedfile_test.go +++ b/internal/lockedfile/lockedfile_test.go @@ -15,7 +15,7 @@ import ( "testing" "time" - "hakurei.app/container" + "hakurei.app/container/fhs" "hakurei.app/internal/lockedfile" "hakurei.app/internal/lockedfile/internal/testexec" ) @@ -215,7 +215,7 @@ func TestSpuriousEDEADLK(t *testing.T) { t.Fatal(err) } - cmd := testexec.CommandContext(t, t.Context(), container.MustExecutable(nil), "-test.run=^"+t.Name()+"$") + cmd := testexec.CommandContext(t, t.Context(), fhs.ProcSelfExe, "-test.run=^"+t.Name()+"$") cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", dirVar, dir)) qDone := make(chan struct{})