github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/userns/userns_linux.go (about) 1 package userns 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "sync" 8 ) 9 10 var ( 11 inUserNS bool 12 nsOnce sync.Once 13 ) 14 15 // runningInUserNS detects whether we are currently running in a user namespace. 16 // 17 // Originally copied from https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700. 18 func runningInUserNS() bool { 19 nsOnce.Do(func() { 20 file, err := os.Open("/proc/self/uid_map") 21 if err != nil { 22 // This kernel-provided file only exists if user namespaces are supported. 23 return 24 } 25 defer file.Close() 26 27 buf := bufio.NewReader(file) 28 l, _, err := buf.ReadLine() 29 if err != nil { 30 return 31 } 32 33 inUserNS = uidMapInUserNS(string(l)) 34 }) 35 return inUserNS 36 } 37 38 func uidMapInUserNS(uidMap string) bool { 39 if uidMap == "" { 40 // File exist but empty (the initial state when userns is created, 41 // see user_namespaces(7)). 42 return true 43 } 44 45 var a, b, c int64 46 if _, err := fmt.Sscanf(uidMap, "%d %d %d", &a, &b, &c); err != nil { 47 // Assume we are in a regular, non user namespace. 48 return false 49 } 50 51 // As per user_namespaces(7), /proc/self/uid_map of 52 // the initial user namespace shows 0 0 4294967295. 53 initNS := a == 0 && b == 0 && c == 4294967295 54 return !initNS 55 }