aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/domain/infra/abi/system.go7
-rw-r--r--pkg/machine/ignition.go16
-rw-r--r--pkg/rootless/rootless_linux.go65
-rw-r--r--pkg/specgen/generate/container_create.go33
4 files changed, 111 insertions, 10 deletions
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 6319c1ab1..9bba0fa6c 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -21,6 +21,7 @@ import (
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/podman/v3/utils"
"github.com/containers/storage"
+ "github.com/containers/storage/pkg/unshare"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -58,7 +59,11 @@ func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) error {
// do it only after podman has already re-execed and running with uid==0.
- if os.Geteuid() == 0 {
+ hasCapSysAdmin, err := unshare.HasCapSysAdmin()
+ if err != nil {
+ return err
+ }
+ if hasCapSysAdmin {
ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
if err != nil {
logrus.Infof("Failed to detect the owner for the current cgroup: %v", err)
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index cc5c01de6..00068a136 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -168,6 +168,22 @@ func getFiles(usrName string) []File {
},
FileEmbedded1: FileEmbedded1{Mode: intToPtr(420)},
})
+
+ // Set machine_enabled to true to indicate we're in a VM
+ files = append(files, File{
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: "/etc/containers/containers.conf",
+ User: getNodeUsr("root"),
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ Contents: Resource{
+ Source: strToPtr("data:,%5Bengine%5D%0Amachine_enabled%3Dtrue%0A"),
+ },
+ Mode: intToPtr(420),
+ },
+ })
return files
}
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index dda230dbc..fdfeed854 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -4,6 +4,7 @@ package rootless
import (
"bufio"
+ "bytes"
"fmt"
"io"
"io/ioutil"
@@ -18,6 +19,7 @@ import (
"github.com/containers/podman/v3/pkg/errorhandling"
"github.com/containers/storage/pkg/idtools"
+ "github.com/containers/storage/pkg/unshare"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
@@ -67,6 +69,15 @@ func IsRootless() bool {
}
}
isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != ""
+ if !isRootless {
+ hasCapSysAdmin, err := unshare.HasCapSysAdmin()
+ if err != nil {
+ logrus.Warnf("failed to read CAP_SYS_ADMIN presence for the current process")
+ }
+ if err == nil && !hasCapSysAdmin {
+ isRootless = true
+ }
+ }
})
return isRootless
}
@@ -142,8 +153,12 @@ func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) err
// namespace of the specified PID without looking up its parent. Useful to join directly
// the conmon process.
func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) {
- if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
- return false, -1, nil
+ hasCapSysAdmin, err := unshare.HasCapSysAdmin()
+ if err != nil {
+ return false, 0, err
+ }
+ if hasCapSysAdmin || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
+ return false, 0, nil
}
cPausePid := C.CString(pausePid)
@@ -180,8 +195,11 @@ func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
}
mappings, err := idtools.NewIDMappings(username, username)
if err != nil {
- logrus.Errorf(
- "cannot find UID/GID for user %s: %v - check rootless mode in man pages.", username, err)
+ logLevel := logrus.ErrorLevel
+ if os.Geteuid() == 0 && GetRootlessUID() == 0 {
+ logLevel = logrus.DebugLevel
+ }
+ logrus.StandardLogger().Logf(logLevel, "cannot find UID/GID for user %s: %v - check rootless mode in man pages.", username, err)
} else {
uids = mappings.UIDs()
gids = mappings.GIDs()
@@ -189,8 +207,28 @@ func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
return uids, gids, nil
}
+func copyMappings(from, to string) error {
+ content, err := ioutil.ReadFile(from)
+ if err != nil {
+ return err
+ }
+ // Both runc and crun check whether the current process is in a user namespace
+ // by looking up 4294967295 in /proc/self/uid_map. If the mappings would be
+ // copied as they are, the check in the OCI runtimes would fail. So just split
+ // it in two different ranges.
+ if bytes.Contains(content, []byte("4294967295")) {
+ content = []byte("0 0 1\n1 1 4294967294\n")
+ }
+ return ioutil.WriteFile(to, content, 0600)
+}
+
func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ bool, _ int, retErr error) {
- if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
+ hasCapSysAdmin, err := unshare.HasCapSysAdmin()
+ if err != nil {
+ return false, 0, err
+ }
+
+ if hasCapSysAdmin || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
if os.Getenv("_CONTAINERS_USERNS_CONFIGURED") == "init" {
return false, 0, runInUser()
}
@@ -247,8 +285,16 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
return false, -1, err
}
+ uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
+ gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
+
uidsMapped := false
- if uids != nil {
+
+ if err := copyMappings("/proc/self/uid_map", uidMap); err == nil {
+ uidsMapped = true
+ }
+
+ if uids != nil && !uidsMapped {
err := tryMappingTool(true, pid, os.Geteuid(), uids)
// If some mappings were specified, do not ignore the error
if err != nil && len(uids) > 0 {
@@ -265,7 +311,6 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
}
logrus.Debugf("write setgroups file exited with 0")
- uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Geteuid())), 0666)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot write uid_map")
@@ -274,7 +319,10 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
}
gidsMapped := false
- if gids != nil {
+ if err := copyMappings("/proc/self/gid_map", gidMap); err == nil {
+ gidsMapped = true
+ }
+ if gids != nil && !gidsMapped {
err := tryMappingTool(false, pid, os.Getegid(), gids)
// If some mappings were specified, do not ignore the error
if err != nil && len(gids) > 0 {
@@ -283,7 +331,6 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
gidsMapped = err == nil
}
if !gidsMapped {
- gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getegid())), 0666)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot write gid_map")
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 13d4b4926..2f623bf10 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -6,12 +6,14 @@ import (
"path/filepath"
"strings"
+ cdi "github.com/container-orchestrated-devices/container-device-interface/pkg"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/image"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage/types"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -136,6 +138,11 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
options = append(options, libpod.WithNetworkAliases(s.Aliases))
}
+ if len(s.Devices) > 0 {
+ opts = extractCDIDevices(s)
+ options = append(options, opts...)
+ }
+
runtimeSpec, err := SpecGenToOCI(ctx, s, rt, rtc, newImage, finalMounts, pod, command)
if err != nil {
return nil, err
@@ -143,6 +150,32 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
return rt.NewContainer(ctx, runtimeSpec, options...)
}
+func extractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption {
+ devs := make([]spec.LinuxDevice, 0, len(s.Devices))
+ var cdiDevs []string
+ var options []libpod.CtrCreateOption
+
+ for _, device := range s.Devices {
+ isCDIDevice, err := cdi.HasDevice(device.Path)
+ if err != nil {
+ logrus.Debugf("CDI HasDevice Error: %v", err)
+ }
+ if err == nil && isCDIDevice {
+ cdiDevs = append(cdiDevs, device.Path)
+ continue
+ }
+
+ devs = append(devs, device)
+ }
+
+ s.Devices = devs
+ if len(cdiDevs) > 0 {
+ options = append(options, libpod.WithCDI(cdiDevs))
+ }
+
+ return options
+}
+
func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, overlays []*specgen.OverlayVolume, img *image.Image, command []string) ([]libpod.CtrCreateOption, error) {
var options []libpod.CtrCreateOption
var err error