Skip to content

Commit

Permalink
libcontainer/system: move userns utilities to separate packaage
Browse files Browse the repository at this point in the history
Moving these utilities to a separate package, so that consumers of this
package don't have to pull in the whole "system" package.

Looking at uses of these utilities (outside of runc itself);

- `RunningInUserNS()` is used by [various external consumers][1]
- `UIDMapInUserNS()` is not used anywhere, [only internally][2],
  and should be un-exported / moved into `RunningInUserNS()`
- `GetParentNSeuid()` is not used by runc itself, and only used
  by a [single external project][3]. We should consider
  removing it.

[1]: https://grep.app/search?current=2&q=.RunningInUserNS
[2]: https://grep.app/search?q=.UIDMapInUserNS
[3]: https://grep.app/search?q=.GetParentNSeuid

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
thaJeztah committed Mar 13, 2021
1 parent 249bca0 commit f592c1e
Show file tree
Hide file tree
Showing 16 changed files with 130 additions and 96 deletions.
4 changes: 2 additions & 2 deletions checkpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

criu "github.com/checkpoint-restore/go-criu/v4/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"
Expand Down Expand Up @@ -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")
}

Expand Down
4 changes: 2 additions & 2 deletions libcontainer/cgroups/fs/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions libcontainer/cgroups/fs2/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions libcontainer/cgroups/systemd/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions libcontainer/cgroups/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions libcontainer/rootfs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {

Expand Down
49 changes: 0 additions & 49 deletions libcontainer/system/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
package system

import (
"os"
"os/exec"
"sync"
"unsafe"

"github.com/opencontainers/runc/libcontainer/user"
"golang.org/x/sys/unix"
)

Expand Down Expand Up @@ -87,52 +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
}

// GetParentNSeuid returns the euid within the parent user namespace
func GetParentNSeuid() int64 {
euid := int64(os.Geteuid())
uidmap, err := user.CurrentProcessUIDMap()
if err != nil {
// This kernel-provided file only exists if user namespaces are supported
return euid
}
for _, um := range uidmap {
if um.ID <= euid && euid <= um.ID+um.Count-1 {
return um.ParentID + euid - um.ID
}
}
return euid
}

// 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)
Expand Down
27 changes: 0 additions & 27 deletions libcontainer/system/unsupported.go

This file was deleted.

17 changes: 17 additions & 0 deletions libcontainer/system/userns_deprecated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package system

import "github.com/opencontainers/runc/libcontainer/userns"

var (
// RunningInUserNS detects whether we are currently running in a user namespace.
// Originally copied from github.com/lxc/lxd/shared/util.go
// Deprecated: use github.com/opencontainers/runc/libcontainer/userns.RunningInUserNS
RunningInUserNS = userns.RunningInUserNS

// Deprecated: use github.com/opencontainers/runc/libcontainer/userns.UIDMapInUserNS
UIDMapInUserNS = userns.RunningInUserNS

// GetParentNSeuid returns the euid within the parent user namespace
// Deprecated: use github.com/opencontainers/runc/libcontainer/userns.RunningInUserNS
GetParentNSeuid = userns.RunningInUserNS
)
12 changes: 12 additions & 0 deletions libcontainer/userns/userns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package userns

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

UIDMapInUserNS = uidMapInUserNS

// GetParentNSeuid returns the euid within the parent user namespace
GetParentNSeuid = getParentNSeuid
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build gofuzz

package system
package userns

import (
"strings"
Expand All @@ -10,6 +10,6 @@ import (

func FuzzUIDMap(data []byte) int {
uidmap, _ := user.ParseIDMap(strings.NewReader(string(data)))
_ = UIDMapInUserNS(uidmap)
_ = uidMapInUserNS(uidmap)
return 1
}
54 changes: 54 additions & 0 deletions libcontainer/userns/userns_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package userns

import (
"os"
"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
}

// getParentNSeuid returns the euid within the parent user namespace
func getParentNSeuid() int64 {
euid := int64(os.Geteuid())
uidmap, err := user.CurrentProcessUIDMap()
if err != nil {
// This kernel-provided file only exists if user namespaces are supported
return euid
}
for _, um := range uidmap {
if um.ID <= euid && euid <= um.ID+um.Count-1 {
return um.ParentID + euid - um.ID
}
}
return euid
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build linux

package system
package userns

import (
"strings"
Expand Down
27 changes: 27 additions & 0 deletions libcontainer/userns/userns_unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// +build !linux

package userns

import (
"os"

"github.com/opencontainers/runc/libcontainer/user"
)

// runningInUserNS is a stub for non-Linux systems
// Always returns false
func runningInUserNS() bool {
return false
}

// uidMapInUserNS is a stub for non-Linux systems
// Always returns false
func uidMapInUserNS(uidmap []user.IDMap) bool {
return false
}

// getParentNSeuid returns the euid within the parent user namespace
// Always returns os.Geteuid on non-linux
func getParentNSeuid() int {
return os.Geteuid()
}
4 changes: 2 additions & 2 deletions restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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")
}

Expand Down
6 changes: 3 additions & 3 deletions rootless_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -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
}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit f592c1e

Please sign in to comment.