Skip to content

Commit d8e9ed3

Browse files
committed
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 <[email protected]>
1 parent 3b47c5e commit d8e9ed3

File tree

5 files changed

+36
-37
lines changed

5 files changed

+36
-37
lines changed

libcontainer/userns/userns.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
package userns
22

33
// RunningInUserNS detects whether we are currently running in a user namespace.
4-
// Originally copied from github.com/lxc/lxd/shared/util.go
54
var RunningInUserNS = runningInUserNS

libcontainer/userns/userns_fuzzer.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@
33

44
package userns
55

6-
import (
7-
"strings"
8-
9-
"github.com/opencontainers/runc/libcontainer/user"
10-
)
11-
12-
func FuzzUIDMap(data []byte) int {
13-
uidmap, _ := user.ParseIDMap(strings.NewReader(string(data)))
14-
_ = uidMapInUserNS(uidmap)
6+
func FuzzUIDMap(uidmap []byte) int {
7+
_ = uidMapInUserNS(string(uidmap))
158
return 1
169
}
Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package userns
22

33
import (
4+
"bufio"
5+
"fmt"
6+
"os"
47
"sync"
5-
6-
"github.com/opencontainers/runc/libcontainer/user"
78
)
89

910
var (
@@ -12,26 +13,43 @@ var (
1213
)
1314

1415
// runningInUserNS detects whether we are currently running in a user namespace.
15-
// Originally copied from github.com/lxc/lxd/shared/util.go
16+
//
17+
// Originally copied from https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700.
1618
func runningInUserNS() bool {
1719
nsOnce.Do(func() {
18-
uidmap, err := user.CurrentProcessUIDMap()
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()
1929
if err != nil {
20-
// This kernel-provided file only exists if user namespaces are supported
2130
return
2231
}
23-
inUserNS = uidMapInUserNS(uidmap)
32+
33+
inUserNS = uidMapInUserNS(string(l))
2434
})
2535
return inUserNS
2636
}
2737

28-
func uidMapInUserNS(uidmap []user.IDMap) bool {
29-
/*
30-
* We assume we are in the initial user namespace if we have a full
31-
* range - 4294967295 uids starting at uid 0.
32-
*/
33-
if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 {
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.
3448
return false
3549
}
36-
return true
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
3755
}

libcontainer/userns/userns_linux_test.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package userns
22

3-
import (
4-
"strings"
5-
"testing"
6-
7-
"github.com/opencontainers/runc/libcontainer/user"
8-
)
3+
import "testing"
94

105
func TestUIDMapInUserNS(t *testing.T) {
116
cases := []struct {
@@ -31,11 +26,7 @@ func TestUIDMapInUserNS(t *testing.T) {
3126
},
3227
}
3328
for _, c := range cases {
34-
uidmap, err := user.ParseIDMap(strings.NewReader(c.s))
35-
if err != nil {
36-
t.Fatal(err)
37-
}
38-
actual := uidMapInUserNS(uidmap)
29+
actual := uidMapInUserNS(c.s)
3930
if c.expected != actual {
4031
t.Fatalf("expected %v, got %v for %q", c.expected, actual, c.s)
4132
}

libcontainer/userns/userns_unsupported.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
package userns
55

6-
import "github.com/opencontainers/runc/libcontainer/user"
7-
86
// runningInUserNS is a stub for non-Linux systems
97
// Always returns false
108
func runningInUserNS() bool {
@@ -13,6 +11,6 @@ func runningInUserNS() bool {
1311

1412
// uidMapInUserNS is a stub for non-Linux systems
1513
// Always returns false
16-
func uidMapInUserNS(uidmap []user.IDMap) bool {
14+
func uidMapInUserNS(uidMap string) bool {
1715
return false
1816
}

0 commit comments

Comments
 (0)