aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/sysctl.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-10-19 15:09:33 +0900
committerOphestra <cat@gensokyo.uk>2026-10-19 15:09:33 +0900
commit58913f00845903aa2068f6cb0778baa563d58d14 (patch)
tree37c6d6e6f5245c6b9c636bef1bcd21373cd48cfa /container/sysctl.go
parent4de395f11996d3c269e4dae1dc5f7de83c2b83e9 (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.go69
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)
+}