diff --git a/checkpoint.go b/checkpoint.go index e80dcc4f597..3fe4541d777 100644 --- a/checkpoint.go +++ b/checkpoint.go @@ -11,7 +11,7 @@ import ( criu "github.com/checkpoint-restore/go-criu/v5/rpc" "github.com/opencontainers/runc/libcontainer" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -48,7 +48,7 @@ checkpointed.`, return err } // XXX: Currently this is untested with rootless containers. - if os.Geteuid() != 0 || system.RunningInUserNS() { + if os.Geteuid() != 0 || userns.RunningInUserNS() { logrus.Warn("runc checkpoint is untested with rootless containers") } diff --git a/libcontainer/cgroups/fs/devices.go b/libcontainer/cgroups/fs/devices.go index 9a37e68ec65..a098e3b793e 100644 --- a/libcontainer/cgroups/fs/devices.go +++ b/libcontainer/cgroups/fs/devices.go @@ -12,7 +12,7 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" ) type DevicesGroup struct { @@ -55,7 +55,7 @@ func buildEmulator(rules []*devices.Rule) (*cgroupdevices.Emulator, error) { } func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error { - if system.RunningInUserNS() || cgroup.SkipDevices { + if userns.RunningInUserNS() || cgroup.SkipDevices { return nil } diff --git a/libcontainer/cgroups/fs2/devices.go b/libcontainer/cgroups/fs2/devices.go index 99559fec5b3..61c00a96d6c 100644 --- a/libcontainer/cgroups/fs2/devices.go +++ b/libcontainer/cgroups/fs2/devices.go @@ -7,7 +7,7 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/pkg/errors" "golang.org/x/sys/unix" @@ -36,7 +36,7 @@ func canSkipEBPFError(cgroup *configs.Cgroup) bool { // have the necessary privileges to mknod(2) device inodes or access // host-level instances (though ideally we would be blocking device access // for rootless containers anyway). - if system.RunningInUserNS() { + if userns.RunningInUserNS() { return true } diff --git a/libcontainer/cgroups/systemd/user.go b/libcontainer/cgroups/systemd/user.go index 8fe91688477..450a2469402 100644 --- a/libcontainer/cgroups/systemd/user.go +++ b/libcontainer/cgroups/systemd/user.go @@ -13,7 +13,7 @@ import ( systemdDbus "github.com/coreos/go-systemd/v22/dbus" dbus "github.com/godbus/dbus/v5" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/pkg/errors" ) @@ -52,7 +52,7 @@ func NewUserSystemdDbus() (*systemdDbus.Conn, error) { // // Otherwise returns os.Getuid() . func DetectUID() (int, error) { - if !system.RunningInUserNS() { + if !userns.RunningInUserNS() { return os.Getuid(), nil } b, err := exec.Command("busctl", "--user", "--no-pager", "status").CombinedOutput() diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go index f6d04d58519..35ce2c1c2d4 100644 --- a/libcontainer/cgroups/utils.go +++ b/libcontainer/cgroups/utils.go @@ -16,7 +16,7 @@ import ( "time" "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -37,7 +37,7 @@ func IsCgroup2UnifiedMode() bool { var st unix.Statfs_t err := unix.Statfs(unifiedMountpoint, &st) if err != nil { - if os.IsNotExist(err) && system.RunningInUserNS() { + if os.IsNotExist(err) && userns.RunningInUserNS() { // ignore the "not found" error if running in userns logrus.WithError(err).Debugf("%s missing, assuming cgroup v1", unifiedMountpoint) isUnified = false diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 411496ab7c6..ed38e77219b 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -19,7 +19,7 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/opencontainers/runc/libcontainer/utils" libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runtime-spec/specs-go" @@ -603,7 +603,7 @@ func reOpenDevNull() error { // Create the device nodes in the container. func createDevices(config *configs.Config) error { - useBindMount := system.RunningInUserNS() || config.Namespaces.Contains(configs.NEWUSER) + useBindMount := userns.RunningInUserNS() || config.Namespaces.Contains(configs.NEWUSER) oldMask := unix.Umask(0000) for _, node := range config.Devices { diff --git a/libcontainer/system/linux.go b/libcontainer/system/linux.go index eb301073cde..4379a207088 100644 --- a/libcontainer/system/linux.go +++ b/libcontainer/system/linux.go @@ -4,10 +4,8 @@ package system import ( "os/exec" - "sync" "unsafe" - "github.com/opencontainers/runc/libcontainer/user" "golang.org/x/sys/unix" ) @@ -86,36 +84,6 @@ func Setctty() error { return nil } -var ( - inUserNS bool - nsOnce sync.Once -) - -// RunningInUserNS detects whether we are currently running in a user namespace. -// Originally copied from github.com/lxc/lxd/shared/util.go -func RunningInUserNS() bool { - nsOnce.Do(func() { - uidmap, err := user.CurrentProcessUIDMap() - if err != nil { - // This kernel-provided file only exists if user namespaces are supported - return - } - inUserNS = uidMapInUserNS(uidmap) - }) - 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 { - return false - } - return true -} - // SetSubreaper sets the value i as the subreaper setting for the calling process func SetSubreaper(i int) error { return unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0) diff --git a/libcontainer/system/userns_deprecated.go b/libcontainer/system/userns_deprecated.go new file mode 100644 index 00000000000..2de3462a506 --- /dev/null +++ b/libcontainer/system/userns_deprecated.go @@ -0,0 +1,5 @@ +package system + +import "github.com/opencontainers/runc/libcontainer/userns" + +var RunningInUserNS = userns.RunningInUserNS diff --git a/libcontainer/userns/userns.go b/libcontainer/userns/userns.go new file mode 100644 index 00000000000..f6cb98e5e49 --- /dev/null +++ b/libcontainer/userns/userns.go @@ -0,0 +1,5 @@ +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/system/system_fuzzer.go b/libcontainer/userns/userns_fuzzer.go similarity index 93% rename from libcontainer/system/system_fuzzer.go rename to libcontainer/userns/userns_fuzzer.go index 2354247ebef..529f8eaea2f 100644 --- a/libcontainer/system/system_fuzzer.go +++ b/libcontainer/userns/userns_fuzzer.go @@ -1,6 +1,6 @@ // +build gofuzz -package system +package userns import ( "strings" diff --git a/libcontainer/userns/userns_linux.go b/libcontainer/userns/userns_linux.go new file mode 100644 index 00000000000..724e6df0120 --- /dev/null +++ b/libcontainer/userns/userns_linux.go @@ -0,0 +1,37 @@ +package userns + +import ( + "sync" + + "github.com/opencontainers/runc/libcontainer/user" +) + +var ( + inUserNS bool + nsOnce sync.Once +) + +// runningInUserNS detects whether we are currently running in a user namespace. +// Originally copied from github.com/lxc/lxd/shared/util.go +func runningInUserNS() bool { + nsOnce.Do(func() { + uidmap, err := user.CurrentProcessUIDMap() + if err != nil { + // This kernel-provided file only exists if user namespaces are supported + return + } + inUserNS = uidMapInUserNS(uidmap) + }) + 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 { + return false + } + return true +} diff --git a/libcontainer/system/linux_test.go b/libcontainer/userns/userns_linux_test.go similarity index 98% rename from libcontainer/system/linux_test.go rename to libcontainer/userns/userns_linux_test.go index 08e2d6c3b92..2ddd3ff966d 100644 --- a/libcontainer/system/linux_test.go +++ b/libcontainer/userns/userns_linux_test.go @@ -1,6 +1,6 @@ // +build linux -package system +package userns import ( "strings" diff --git a/libcontainer/system/unsupported.go b/libcontainer/userns/userns_unsupported.go similarity index 55% rename from libcontainer/system/unsupported.go rename to libcontainer/userns/userns_unsupported.go index 829d9dac00e..f45bb0c3156 100644 --- a/libcontainer/system/unsupported.go +++ b/libcontainer/userns/userns_unsupported.go @@ -1,14 +1,12 @@ // +build !linux -package system +package userns -import ( - "github.com/opencontainers/runc/libcontainer/user" -) +import "github.com/opencontainers/runc/libcontainer/user" -// RunningInUserNS is a stub for non-Linux systems +// runningInUserNS is a stub for non-Linux systems // Always returns false -func RunningInUserNS() bool { +func runningInUserNS() bool { return false } diff --git a/restore.go b/restore.go index ec7308221f0..ed69d15e784 100644 --- a/restore.go +++ b/restore.go @@ -6,7 +6,7 @@ import ( "os" "github.com/opencontainers/runc/libcontainer" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -97,7 +97,7 @@ using the runc checkpoint command.`, return err } // XXX: Currently this is untested with rootless containers. - if os.Geteuid() != 0 || system.RunningInUserNS() { + if os.Geteuid() != 0 || userns.RunningInUserNS() { logrus.Warn("runc checkpoint is untested with rootless containers") } diff --git a/rootless_linux.go b/rootless_linux.go index 348f7c4ffca..3c21053846b 100644 --- a/rootless_linux.go +++ b/rootless_linux.go @@ -6,7 +6,7 @@ import ( "os" "github.com/opencontainers/runc/libcontainer/cgroups/systemd" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/userns" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -25,7 +25,7 @@ func shouldUseRootlessCgroupManager(context *cli.Context) (bool, error) { if os.Geteuid() != 0 { return true, nil } - if !system.RunningInUserNS() { + if !userns.RunningInUserNS() { // euid == 0 , in the initial ns (i.e. the real root) return false, nil } @@ -60,7 +60,7 @@ func shouldHonorXDGRuntimeDir() bool { if os.Geteuid() != 0 { return true } - if !system.RunningInUserNS() { + if !userns.RunningInUserNS() { // euid == 0 , in the initial ns (i.e. the real root) // in this case, we should use /run/runc and ignore // $XDG_RUNTIME_DIR (e.g. /run/user/0) for backward