diff --git a/libcontainer/userns/userns.go b/libcontainer/userns/userns.go index f6cb98e5e49..b225f18f2e2 100644 --- a/libcontainer/userns/userns.go +++ b/libcontainer/userns/userns.go @@ -1,5 +1,4 @@ package userns // RunningInUserNS detects whether we are currently running in a user namespace. -// Originally copied from github.com/lxc/lxd/shared/util.go var RunningInUserNS = runningInUserNS diff --git a/libcontainer/userns/userns_fuzzer.go b/libcontainer/userns/userns_fuzzer.go index 1e00ab8b505..bff03f8d859 100644 --- a/libcontainer/userns/userns_fuzzer.go +++ b/libcontainer/userns/userns_fuzzer.go @@ -3,14 +3,7 @@ package userns -import ( - "strings" - - "github.com/opencontainers/runc/libcontainer/user" -) - -func FuzzUIDMap(data []byte) int { - uidmap, _ := user.ParseIDMap(strings.NewReader(string(data))) - _ = uidMapInUserNS(uidmap) +func FuzzUIDMap(uidmap []byte) int { + _ = uidMapInUserNS(string(uidmap)) return 1 } diff --git a/libcontainer/userns/userns_linux.go b/libcontainer/userns/userns_linux.go index 724e6df0120..a6710b321be 100644 --- a/libcontainer/userns/userns_linux.go +++ b/libcontainer/userns/userns_linux.go @@ -1,9 +1,10 @@ package userns import ( + "bufio" + "fmt" + "os" "sync" - - "github.com/opencontainers/runc/libcontainer/user" ) var ( @@ -12,26 +13,43 @@ var ( ) // runningInUserNS detects whether we are currently running in a user namespace. -// Originally copied from github.com/lxc/lxd/shared/util.go +// +// Originally copied from https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700. func runningInUserNS() bool { nsOnce.Do(func() { - uidmap, err := user.CurrentProcessUIDMap() + file, err := os.Open("/proc/self/uid_map") + if err != nil { + // This kernel-provided file only exists if user namespaces are supported. + return + } + defer file.Close() + + buf := bufio.NewReader(file) + l, _, err := buf.ReadLine() if err != nil { - // This kernel-provided file only exists if user namespaces are supported return } - inUserNS = uidMapInUserNS(uidmap) + + inUserNS = uidMapInUserNS(string(l)) }) return inUserNS } -func uidMapInUserNS(uidmap []user.IDMap) bool { - /* - * We assume we are in the initial user namespace if we have a full - * range - 4294967295 uids starting at uid 0. - */ - if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 { +func uidMapInUserNS(uidMap string) bool { + if uidMap == "" { + // File exist but empty (the initial state when userns is created, + // see user_namespaces(7)). + return true + } + + var a, b, c int64 + if _, err := fmt.Sscanf(uidMap, "%d %d %d", &a, &b, &c); err != nil { + // Assume we are in a regular, non user namespace. return false } - return true + + // As per user_namespaces(7), /proc/self/uid_map of + // the initial user namespace shows 0 0 4294967295. + initNS := a == 0 && b == 0 && c == 4294967295 + return !initNS } diff --git a/libcontainer/userns/userns_linux_test.go b/libcontainer/userns/userns_linux_test.go index 90d9270db6f..25c4ac301de 100644 --- a/libcontainer/userns/userns_linux_test.go +++ b/libcontainer/userns/userns_linux_test.go @@ -1,11 +1,6 @@ package userns -import ( - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/user" -) +import "testing" func TestUIDMapInUserNS(t *testing.T) { cases := []struct { @@ -31,11 +26,7 @@ func TestUIDMapInUserNS(t *testing.T) { }, } for _, c := range cases { - uidmap, err := user.ParseIDMap(strings.NewReader(c.s)) - if err != nil { - t.Fatal(err) - } - actual := uidMapInUserNS(uidmap) + actual := uidMapInUserNS(c.s) if c.expected != actual { t.Fatalf("expected %v, got %v for %q", c.expected, actual, c.s) } diff --git a/libcontainer/userns/userns_unsupported.go b/libcontainer/userns/userns_unsupported.go index f35c13a10e0..391c811c680 100644 --- a/libcontainer/userns/userns_unsupported.go +++ b/libcontainer/userns/userns_unsupported.go @@ -3,8 +3,6 @@ package userns -import "github.com/opencontainers/runc/libcontainer/user" - // runningInUserNS is a stub for non-Linux systems // Always returns false func runningInUserNS() bool { @@ -13,6 +11,6 @@ func runningInUserNS() bool { // uidMapInUserNS is a stub for non-Linux systems // Always returns false -func uidMapInUserNS(uidmap []user.IDMap) bool { +func uidMapInUserNS(uidMap string) bool { return false }