diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-10-19 15:09:33 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-10-19 15:09:33 +0900 |
| commit | 58913f00845903aa2068f6cb0778baa563d58d14 (patch) | |
| tree | 37c6d6e6f5245c6b9c636bef1bcd21373cd48cfa /container/sysctl.go | |
| parent | 4de395f11996d3c269e4dae1dc5f7de83c2b83e9 (diff) | |
container/sysctl: remove calls to logger
This behaviour is counterintuitive, the responses are cached, and only
the msg object of the first call is used. This change also improves
error message formatting of these functions.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container/sysctl.go')
| -rw-r--r-- | container/sysctl.go | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/container/sysctl.go b/container/sysctl.go index e4b7af23..2cf47258 100644 --- a/container/sysctl.go +++ b/container/sysctl.go @@ -2,14 +2,32 @@ package container import ( "bytes" + "fmt" "os" "strconv" "sync" "hakurei.app/fhs" - "hakurei.app/message" ) +// mustSysctlInt reads a sysctl path via proc, interprets it as a decimal +// representation of an integer, and terminates the program if the read was +// unsuccessful or the response is invalid. +func mustSysctlInt(path string) (v int) { + p, err := os.ReadFile(fhs.ProcSys + path) + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + + if v, err = strconv.Atoi(string(bytes.TrimSpace(p))); err != nil { + fmt.Printf("invalid sysctl response %q\n", string(p)) + os.Exit(1) + } + return +} + +// cached sysctl responses for populateSysctl var ( kernelOverflowuid int kernelOverflowgid int @@ -18,34 +36,31 @@ var ( sysctlOnce sync.Once ) -const ( - kernelOverflowuidPath = fhs.ProcSys + "kernel/overflowuid" - kernelOverflowgidPath = fhs.ProcSys + "kernel/overflowgid" - kernelCapLastCapPath = fhs.ProcSys + "kernel/cap_last_cap" -) - -func mustReadSysctl(msg message.Msg) { +// populateSysctl populates cached sysctl responses guarded by sysctlOnce. +func populateSysctl() { sysctlOnce.Do(func() { - if v, err := os.ReadFile(kernelOverflowuidPath); err != nil { - msg.GetLogger().Fatalf("cannot read %q: %v", kernelOverflowuidPath, err) - } else if kernelOverflowuid, err = strconv.Atoi(string(bytes.TrimSpace(v))); err != nil { - msg.GetLogger().Fatalf("cannot interpret %q: %v", kernelOverflowuidPath, err) - } + kernelOverflowuid = mustSysctlInt("kernel/overflowuid") + kernelOverflowgid = mustSysctlInt("kernel/overflowgid") + kernelCapLastCap = mustSysctlInt("kernel/cap_last_cap") + }) +} - if v, err := os.ReadFile(kernelOverflowgidPath); err != nil { - msg.GetLogger().Fatalf("cannot read %q: %v", kernelOverflowgidPath, err) - } else if kernelOverflowgid, err = strconv.Atoi(string(bytes.TrimSpace(v))); err != nil { - msg.GetLogger().Fatalf("cannot interpret %q: %v", kernelOverflowgidPath, err) - } +// OverflowUID returns the fixed uid returned by legacy 16-bit UID system calls. +// This value is also returned for unmapped UIDs in a user namespace. +func OverflowUID() int { + populateSysctl() + return kernelOverflowuid +} - if v, err := os.ReadFile(kernelCapLastCapPath); err != nil { - msg.GetLogger().Fatalf("cannot read %q: %v", kernelCapLastCapPath, err) - } else if kernelCapLastCap, err = strconv.Atoi(string(bytes.TrimSpace(v))); err != nil { - msg.GetLogger().Fatalf("cannot interpret %q: %v", kernelCapLastCapPath, err) - } - }) +// OverflowGID is like [OverflowUID], but for GID instead. +func OverflowGID() int { + populateSysctl() + return kernelOverflowgid } -func OverflowUid(msg message.Msg) int { mustReadSysctl(msg); return kernelOverflowuid } -func OverflowGid(msg message.Msg) int { mustReadSysctl(msg); return kernelOverflowgid } -func LastCap(msg message.Msg) uintptr { mustReadSysctl(msg); return uintptr(kernelCapLastCap) } +// lastcap returns the highest valid capability of the running kernel. Exports +// CAP_LAST_CAP from the kernel. +func lastcap() uintptr { + populateSysctl() + return uintptr(kernelCapLastCap) +} |
