From 482b48c91c1a140870eba4bf010ee82391f1d5bd Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 22 Mar 2021 14:22:14 +0100 Subject: [PATCH] libcontainer/userns: simplify, and separate from "user" package. This makes libcontainer/userns self-dependent, largely returning to the original implementation from lxc. The `uiMapInUserNS` is kept as a separate function for unit-testing and fuzzing. Signed-off-by: Sebastiaan van Stijn --- libcontainer/userns/userns_fuzzer.go | 11 ++---- libcontainer/userns/userns_linux.go | 43 ++++++++++++++++------- libcontainer/userns/userns_linux_test.go | 13 ++----- libcontainer/userns/userns_unsupported.go | 4 +-- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/libcontainer/userns/userns_fuzzer.go b/libcontainer/userns/userns_fuzzer.go index 529f8eaea2f..b54031d7070 100644 --- a/libcontainer/userns/userns_fuzzer.go +++ b/libcontainer/userns/userns_fuzzer.go @@ -2,14 +2,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..94d284de6ed 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,42 @@ 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 github.com/lxc/lxd/shared/util.go. 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 2ddd3ff966d..e192e874cb8 100644 --- a/libcontainer/userns/userns_linux_test.go +++ b/libcontainer/userns/userns_linux_test.go @@ -2,12 +2,7 @@ package userns -import ( - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/user" -) +import "testing" func TestUIDMapInUserNS(t *testing.T) { cases := []struct { @@ -33,11 +28,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 f45bb0c3156..e15f3889c9c 100644 --- a/libcontainer/userns/userns_unsupported.go +++ b/libcontainer/userns/userns_unsupported.go @@ -2,8 +2,6 @@ package userns -import "github.com/opencontainers/runc/libcontainer/user" - // runningInUserNS is a stub for non-Linux systems // Always returns false func runningInUserNS() bool { @@ -12,6 +10,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 }