Merge pull request #2706 from giuseppe/rootless-single-usernamespace

rootless: single user namespace
This commit is contained in:
OpenShift Merge Robot
2019-04-04 09:21:09 -07:00
committed by GitHub
29 changed files with 171 additions and 851 deletions

View File

@@ -1,10 +1,8 @@
package main
import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/containers/buildah/pkg/chrootuser"
@@ -12,7 +10,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive"
@@ -58,9 +55,6 @@ func cpCmd(c *cliconfig.CpValues) error {
if len(args) != 2 {
return errors.Errorf("you must provide a source path and a destination path")
}
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
@@ -90,34 +84,6 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
ctr = destCtr
}
if os.Geteuid() != 0 {
s, err := ctr.State()
if err != nil {
return err
}
var became bool
var ret int
if s == libpod.ContainerStateRunning || s == libpod.ContainerStatePaused {
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err != nil {
return errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return errors.Wrapf(err, "cannot parse PID %q", data)
}
became, ret, err = rootless.JoinDirectUserAndMountNS(uint(conmonPid))
} else {
became, ret, err = rootless.BecomeRootInUserNS()
}
if err != nil {
return err
}
if became {
os.Exit(ret)
}
}
mountPoint, err := ctr.Mount()
if err != nil {
return err

View File

@@ -2,12 +2,10 @@ package main
import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/pkg/rootless"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -54,10 +52,6 @@ func createCmd(c *cliconfig.CreateValues) error {
return err
}
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")

View File

@@ -10,7 +10,6 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared/parse"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -67,7 +66,6 @@ func execCmd(c *cliconfig.ExecValues) error {
if c.Latest {
argStart = 0
}
rootless.SetSkipStorageSetup(true)
cmd := args[argStart:]
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
@@ -107,32 +105,6 @@ func execCmd(c *cliconfig.ExecValues) error {
}
if os.Geteuid() != 0 {
var became bool
var ret int
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err == nil {
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return errors.Wrapf(err, "cannot parse PID %q", data)
}
became, ret, err = rootless.JoinDirectUserAndMountNS(uint(conmonPid))
} else {
pid, err := ctr.PID()
if err != nil {
return err
}
became, ret, err = rootless.JoinNS(uint(pid), c.PreserveFDs)
}
if err != nil {
return err
}
if became {
os.Exit(ret)
}
}
// ENVIRONMENT VARIABLES
env := map[string]string{}

View File

@@ -6,7 +6,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared/parse"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -41,10 +40,6 @@ func init() {
// exportCmd saves a container to a tarball on disk
func exportCmd(c *cliconfig.ExportValues) error {
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")

View File

@@ -4,12 +4,10 @@ import (
"fmt"
"reflect"
"github.com/containers/libpod/pkg/adapter"
"github.com/opentracing/opentracing-go"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/adapter"
"github.com/docker/docker/pkg/signal"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -63,7 +61,6 @@ func killCmd(c *cliconfig.KillValues) error {
return err
}
rootless.SetSkipStorageSetup(true)
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")

View File

@@ -3,13 +3,16 @@ package main
import (
"context"
"io"
"io/ioutil"
"log/syslog"
"os"
"runtime/pprof"
"strconv"
"strings"
"syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
_ "github.com/containers/libpod/pkg/hooks/0.1.0"
"github.com/containers/libpod/pkg/rootless"
@@ -60,36 +63,6 @@ var mainCommands = []*cobra.Command{
systemCommand.Command,
}
var cmdsNotRequiringRootless = map[*cobra.Command]bool{
_versionCommand: true,
_createCommand: true,
_execCommand: true,
_cpCommand: true,
_exportCommand: true,
//// `info` must be executed in an user namespace.
//// If this change, please also update libpod.refreshRootless()
_loginCommand: true,
_logoutCommand: true,
_mountCommand: true,
_killCommand: true,
_pauseCommand: true,
_podRmCommand: true,
_podKillCommand: true,
_podRestartCommand: true,
_podStatsCommand: true,
_podStopCommand: true,
_podTopCommand: true,
_restartCommand: true,
&_psCommand: true,
_rmCommand: true,
_runCommand: true,
_unpauseCommand: true,
_searchCommand: true,
_statsCommand: true,
_stopCommand: true,
_topCommand: true,
}
var rootCmd = &cobra.Command{
Use: "podman",
Long: "manage pods and images",
@@ -153,18 +126,52 @@ func before(cmd *cobra.Command, args []string) error {
logrus.Errorf(err.Error())
os.Exit(1)
}
if rootless.IsRootless() {
notRequireRootless := cmdsNotRequiringRootless[cmd]
if !notRequireRootless && !strings.HasPrefix(cmd.Use, "help") {
became, ret, err := rootless.BecomeRootInUserNS()
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
if became {
os.Exit(ret)
if os.Geteuid() != 0 && cmd != _searchCommand && cmd != _versionCommand && !strings.HasPrefix(cmd.Use, "help") {
podmanCmd := cliconfig.PodmanCommand{
cmd,
args,
MainGlobalOpts,
}
runtime, err := libpodruntime.GetRuntime(&podmanCmd)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
ctrs, err := runtime.GetRunningContainers()
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
var became bool
var ret int
if len(ctrs) == 0 {
became, ret, err = rootless.BecomeRootInUserNS()
} else {
for _, ctr := range ctrs {
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
became, ret, err = rootless.JoinUserAndMountNS(uint(conmonPid))
if err == nil {
break
}
}
}
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
if became {
os.Exit(ret)
}
}
if MainGlobalOpts.Syslog {

View File

@@ -60,10 +60,6 @@ type jsonMountPoint struct {
}
func mountCmd(c *cliconfig.MountValues) error {
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")

View File

@@ -1,12 +1,7 @@
package main
import (
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -39,48 +34,6 @@ var podSubCommands = []*cobra.Command{
_podUnpauseCommand,
}
func joinPodNS(runtime *adapter.LocalRuntime, all, latest bool, inputArgs []string) ([]string, bool, bool, error) {
if rootless.IsRootless() {
if os.Geteuid() == 0 {
return []string{rootless.Argument()}, false, false, nil
} else {
var err error
var pods []*adapter.Pod
if all {
pods, err = runtime.GetAllPods()
if err != nil {
return nil, false, false, errors.Wrapf(err, "unable to get pods")
}
} else if latest {
pod, err := runtime.GetLatestPod()
if err != nil {
return nil, false, false, errors.Wrapf(err, "unable to get latest pod")
}
pods = append(pods, pod)
} else {
for _, i := range inputArgs {
pod, err := runtime.LookupPod(i)
if err != nil {
return nil, false, false, errors.Wrapf(err, "unable to lookup pod %s", i)
}
pods = append(pods, pod)
}
}
for _, p := range pods {
_, ret, err := runtime.JoinOrCreateRootlessPod(p)
if err != nil {
return nil, false, false, err
}
if ret != 0 {
os.Exit(ret)
}
}
os.Exit(0)
}
}
return inputArgs, all, latest, nil
}
func init() {
podCommand.AddCommand(podSubCommands...)
podCommand.SetHelpTemplate(HelpTemplate())

View File

@@ -6,7 +6,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/docker/docker/pkg/signal"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -49,7 +48,6 @@ func init() {
// podKillCmd kills one or more pods with a signal
func podKillCmd(c *cliconfig.PodKillValues) error {
rootless.SetSkipStorageSetup(true)
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")

View File

@@ -2,11 +2,9 @@ package main
import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -48,24 +46,12 @@ func init() {
func podRestartCmd(c *cliconfig.PodRestartValues) error {
var lastError error
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
if rootless.IsRootless() {
var err error
c.InputArgs, c.All, c.Latest, err = joinPodNS(runtime, c.All, c.Latest, c.InputArgs)
if err != nil {
return err
}
}
restartIDs, conErrors, restartErrors := runtime.RestartPods(getContext(), c)
for _, p := range restartIDs {

View File

@@ -2,11 +2,9 @@ package main
import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -48,23 +46,12 @@ func init() {
// podRmCmd deletes pods
func podRmCmd(c *cliconfig.PodRmValues) error {
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
if rootless.IsRootless() {
var err error
c.InputArgs, c.All, c.Latest, err = joinPodNS(runtime, c.All, c.Latest, c.InputArgs)
if err != nil {
return err
}
}
podRmIds, podRmErrors := runtime.RemovePods(getContext(), c)
for _, p := range podRmIds {
fmt.Println(p)

View File

@@ -2,11 +2,9 @@ package main
import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -48,24 +46,12 @@ func init() {
}
func podStopCmd(c *cliconfig.PodStopValues) error {
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
if rootless.IsRootless() {
var err error
c.InputArgs, c.All, c.Latest, err = joinPodNS(runtime, c.All, c.Latest, c.InputArgs)
if err != nil {
return err
}
}
podStopIds, podStopErrors := runtime.StopPods(getContext(), c)
for _, p := range podStopIds {
fmt.Println(p)

View File

@@ -9,7 +9,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -54,10 +53,6 @@ func podTopCmd(c *cliconfig.PodTopValues) error {
)
args := c.InputArgs
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
if c.ListDescriptors {
descriptors, err := libpod.GetContainerPidInformationDescriptors()
if err != nil {
@@ -83,26 +78,6 @@ func podTopCmd(c *cliconfig.PodTopValues) error {
descriptors = args[1:]
}
if os.Geteuid() != 0 {
var pod *adapter.Pod
var err error
if c.Latest {
pod, err = runtime.GetLatestPod()
} else {
pod, err = runtime.LookupPod(c.InputArgs[0])
}
if err != nil {
return errors.Wrapf(err, "unable to lookup requested container")
}
became, ret, err := runtime.JoinOrCreateRootlessPod(pod)
if err != nil {
return err
}
if became {
os.Exit(ret)
}
}
w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
psOutput, err := runtime.PodTop(c, descriptors)
if err != nil {

View File

@@ -17,7 +17,6 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-units"
@@ -202,9 +201,6 @@ func init() {
}
func psCmd(c *cliconfig.PsValues) error {
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
if c.Bool("trace") {
span, _ := opentracing.StartSpanFromContext(Ctx, "psCmd")
defer span.Finish()

View File

@@ -1,13 +1,10 @@
package main
import (
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -57,19 +54,6 @@ func restartCmd(c *cliconfig.RestartValues) error {
restartContainers []*libpod.Container
)
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
if rootless.IsRootless() {
// If we are in the re-execed rootless environment,
// override the arg to deal only with one container.
if os.Geteuid() == 0 {
c.All = false
c.Latest = false
c.InputArgs = []string{rootless.Argument()}
}
}
args := c.InputArgs
runOnly := c.Running
all := c.All
@@ -115,20 +99,6 @@ func restartCmd(c *cliconfig.RestartValues) error {
}
}
if os.Geteuid() != 0 {
// In rootless mode we can deal with one container at at time.
for _, c := range restartContainers {
_, ret, err := joinContainerOrCreateRootlessUserNS(runtime, c)
if err != nil {
return err
}
if ret != 0 {
os.Exit(ret)
}
}
os.Exit(0)
}
maxWorkers := shared.Parallelize("restart")
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalFlags.MaxWorks

View File

@@ -2,16 +2,12 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -52,39 +48,11 @@ func init() {
markFlagHiddenForRemoteClient("latest", flags)
}
func joinContainerOrCreateRootlessUserNS(runtime *libpod.Runtime, ctr *libpod.Container) (bool, int, error) {
if os.Geteuid() == 0 {
return false, 0, nil
}
s, err := ctr.State()
if err != nil {
return false, -1, err
}
opts := rootless.Opts{
Argument: ctr.ID(),
}
if s == libpod.ContainerStateRunning || s == libpod.ContainerStatePaused {
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return false, -1, errors.Wrapf(err, "cannot parse PID %q", data)
}
return rootless.JoinDirectUserAndMountNSWithOpts(uint(conmonPid), &opts)
}
return rootless.BecomeRootInUserNSWithOpts(&opts)
}
// saveCmd saves the image to either docker-archive or oci
func rmCmd(c *cliconfig.RmValues) error {
var (
deleteFuncs []shared.ParallelWorkerInput
)
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
ctx := getContext()
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
@@ -93,58 +61,6 @@ func rmCmd(c *cliconfig.RmValues) error {
}
defer runtime.Shutdown(false)
if rootless.IsRootless() {
// When running in rootless mode we cannot manage different containers and
// user namespaces from the same context, so be sure to re-exec once for each
// container we are dealing with.
// What we do is to first collect all the containers we want to delete, then
// we re-exec in each of the container namespaces and from there remove the single
// container.
var container *libpod.Container
if os.Geteuid() == 0 {
// We are in the namespace, override InputArgs with the single
// argument that was passed down to us.
c.All = false
c.Latest = false
c.InputArgs = []string{rootless.Argument()}
} else {
exitCode = 0
var containers []*libpod.Container
if c.All {
containers, err = runtime.GetContainers()
} else if c.Latest {
container, err = runtime.GetLatestContainer()
if err != nil {
return errors.Wrapf(err, "unable to get latest pod")
}
containers = append(containers, container)
} else {
for _, c := range c.InputArgs {
container, err = runtime.LookupContainer(c)
if err != nil {
if errors.Cause(err) == libpod.ErrNoSuchCtr {
exitCode = 1
continue
}
return err
}
containers = append(containers, container)
}
}
// Now we really delete the containers.
for _, c := range containers {
_, ret, err := joinContainerOrCreateRootlessUserNS(runtime, c)
if err != nil {
return err
}
if ret != 0 {
os.Exit(ret)
}
}
os.Exit(exitCode)
}
}
failureCnt := 0
delContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil {

View File

@@ -12,7 +12,6 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -57,9 +56,6 @@ func runCmd(c *cliconfig.RunValues) error {
if err := createInit(&c.PodmanCommand); err != nil {
return err
}
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -75,7 +74,8 @@ func CreateContainer(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
imageName := ""
var data *inspect.ImageData = nil
if rootfs == "" && !rootless.SkipStorageSetup() {
// Set the storage if we are running as euid == 0 and there is no rootfs specified
if rootfs == "" && os.Geteuid() == 0 {
var writer io.Writer
if !c.Bool("quiet") {
writer = os.Stderr
@@ -758,71 +758,6 @@ type namespace interface {
Container() string
}
func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *libpod.Runtime) (bool, int, error) {
if os.Geteuid() == 0 {
return false, 0, nil
}
if createConfig.Pod != "" {
pod, err := runtime.LookupPod(createConfig.Pod)
if err != nil {
return false, -1, err
}
inspect, err := pod.Inspect()
for _, ctr := range inspect.Containers {
prevCtr, err := runtime.LookupContainer(ctr.ID)
if err != nil {
return false, -1, err
}
s, err := prevCtr.State()
if err != nil {
return false, -1, err
}
if s != libpod.ContainerStateRunning && s != libpod.ContainerStatePaused {
continue
}
data, err := ioutil.ReadFile(prevCtr.Config().ConmonPidFile)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot read conmon PID file %q", prevCtr.Config().ConmonPidFile)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return false, -1, errors.Wrapf(err, "cannot parse PID %q", data)
}
return rootless.JoinDirectUserAndMountNS(uint(conmonPid))
}
}
namespacesStr := []string{string(createConfig.IpcMode), string(createConfig.NetMode), string(createConfig.UsernsMode), string(createConfig.PidMode), string(createConfig.UtsMode)}
for _, i := range namespacesStr {
if cc.IsNS(i) {
return rootless.JoinNSPath(cc.NS(i))
}
}
namespaces := []namespace{createConfig.IpcMode, createConfig.NetMode, createConfig.UsernsMode, createConfig.PidMode, createConfig.UtsMode}
for _, i := range namespaces {
if i.IsContainer() {
ctr, err := runtime.LookupContainer(i.Container())
if err != nil {
return false, -1, err
}
pid, err := ctr.PID()
if err != nil {
return false, -1, err
}
if pid == 0 {
if createConfig.Pod != "" {
continue
}
return false, -1, errors.Errorf("dependency container %s is not running", ctr.ID())
}
return rootless.JoinNS(uint(pid), 0)
}
}
return rootless.BecomeRootInUserNS()
}
func CreateContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context, pod *libpod.Pod) (*libpod.Container, error) {
runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
if err != nil {
@@ -833,13 +768,6 @@ func CreateContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateC
if err != nil {
return nil, err
}
became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, r)
if err != nil {
return nil, err
}
if became {
os.Exit(ret)
}
ctr, err := r.NewContainer(ctx, runtimeSpec, options...)
if err != nil {

View File

@@ -7,7 +7,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -59,7 +58,6 @@ func stopCmd(c *cliconfig.StopValues) error {
defer span.Finish()
}
rootless.SetSkipStorageSetup(true)
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")

View File

@@ -9,7 +9,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -77,7 +76,6 @@ func topCmd(c *cliconfig.TopValues) error {
return errors.Errorf("you must provide the name or id of a running container")
}
rootless.SetSkipStorageSetup(true)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
@@ -104,18 +102,6 @@ func topCmd(c *cliconfig.TopValues) error {
if conStat != libpod.ContainerStateRunning {
return errors.Errorf("top can only be used on running containers")
}
pid, err := container.PID()
if err != nil {
return err
}
became, ret, err := rootless.JoinNS(uint(pid), 0)
if err != nil {
return err
}
if became {
os.Exit(ret)
}
psOutput, err := container.GetContainerPidInformation(descriptors)
if err != nil {
return err

View File

@@ -4,7 +4,6 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"sync"
"syscall"
@@ -742,7 +741,7 @@ func makeRuntime(runtime *Runtime) (err error) {
// Set up containers/storage
var store storage.Store
if rootless.SkipStorageSetup() {
if os.Geteuid() != 0 {
logrus.Debug("Not configuring container store")
} else {
store, err = storage.GetStore(runtime.config.StorageConfig)
@@ -926,16 +925,8 @@ func makeRuntime(runtime *Runtime) (err error) {
// If we need to refresh the state, do it now - things are guaranteed to
// be set up by now.
if doRefresh {
if os.Geteuid() != 0 {
aliveLock.Unlock()
locked = false
if err2 := runtime.refreshRootless(); err2 != nil {
return err2
}
} else {
if err2 := runtime.refresh(runtimeAliveFile); err2 != nil {
return err2
}
if err2 := runtime.refresh(runtimeAliveFile); err2 != nil {
return err2
}
}
@@ -1009,21 +1000,6 @@ func (r *Runtime) Shutdown(force bool) error {
return lastError
}
// Reconfigures the runtime after a reboot for a rootless process
func (r *Runtime) refreshRootless() error {
// Take advantage of a command that requires a new userns
// so that we are running as the root user and able to use refresh()
cmd := exec.Command(os.Args[0], "info")
if output, err := cmd.CombinedOutput(); err != nil {
if _, ok := err.(*exec.ExitError); !ok {
return errors.Wrapf(err, "Error waiting for info while refreshing state: %s", os.Args[0])
}
return errors.Wrapf(err, "Error running %s info while refreshing state: %s", os.Args[0], output)
}
return nil
}
// Reconfigures the runtime after a reboot
// Refreshes the state, recreating temporary files
// Does not check validity as the runtime is not valid until after this has run

View File

@@ -2,11 +2,9 @@ package libpod
import (
"context"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
@@ -564,37 +562,6 @@ func (r *Runtime) Export(name string, path string) error {
if err != nil {
return err
}
if os.Geteuid() != 0 {
state, err := ctr.State()
if err != nil {
return errors.Wrapf(err, "cannot read container state %q", ctr.ID())
}
if state == ContainerStateRunning || state == ContainerStatePaused {
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err != nil {
return errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return errors.Wrapf(err, "cannot parse PID %q", data)
}
became, ret, err := rootless.JoinDirectUserAndMountNS(uint(conmonPid))
if err != nil {
return err
}
if became {
os.Exit(ret)
}
} else {
became, ret, err := rootless.BecomeRootInUserNS()
if err != nil {
return err
}
if became {
os.Exit(ret)
}
}
}
return ctr.Export(path)
}

View File

@@ -8,7 +8,6 @@ import (
"io"
"io/ioutil"
"os"
"strconv"
"text/template"
"github.com/containers/buildah"
@@ -124,38 +123,6 @@ func (r *LocalRuntime) Export(name string, path string) error {
if err != nil {
return errors.Wrapf(err, "error looking up container %q", name)
}
if os.Geteuid() != 0 {
state, err := ctr.State()
if err != nil {
return errors.Wrapf(err, "cannot read container state %q", ctr.ID())
}
if state == libpod.ContainerStateRunning || state == libpod.ContainerStatePaused {
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err != nil {
return errors.Wrapf(err, "cannot read conmon PID file %q", ctr.Config().ConmonPidFile)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return errors.Wrapf(err, "cannot parse PID %q", data)
}
became, ret, err := rootless.JoinDirectUserAndMountNS(uint(conmonPid))
if err != nil {
return err
}
if became {
os.Exit(ret)
}
} else {
became, ret, err := rootless.BecomeRootInUserNS()
if err != nil {
return err
}
if became {
os.Exit(ret)
}
}
}
return ctr.Export(path)
}
@@ -343,46 +310,6 @@ func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (libpod.Healt
return r.Runtime.HealthCheck(c.InputArgs[0])
}
// JoinOrCreateRootlessPod joins the specified pod if it is running or it creates a new user namespace
// if the pod is stopped
func (r *LocalRuntime) JoinOrCreateRootlessPod(pod *Pod) (bool, int, error) {
if os.Geteuid() == 0 {
return false, 0, nil
}
opts := rootless.Opts{
Argument: pod.ID(),
}
inspect, err := pod.Inspect()
if err != nil {
return false, 0, err
}
for _, ctr := range inspect.Containers {
prevCtr, err := r.LookupContainer(ctr.ID)
if err != nil {
return false, -1, err
}
s, err := prevCtr.State()
if err != nil {
return false, -1, err
}
if s != libpod.ContainerStateRunning && s != libpod.ContainerStatePaused {
continue
}
data, err := ioutil.ReadFile(prevCtr.Config().ConmonPidFile)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot read conmon PID file %q", prevCtr.Config().ConmonPidFile)
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
return false, -1, errors.Wrapf(err, "cannot parse PID %q", data)
}
return rootless.JoinDirectUserAndMountNSWithOpts(uint(conmonPid), &opts)
}
return rootless.BecomeRootInUserNSWithOpts(&opts)
}
// Events is a wrapper to libpod to obtain libpod/podman events
func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
var (

View File

@@ -755,13 +755,6 @@ func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (libpod.Healt
return -1, libpod.ErrNotImplemented
}
// JoinOrCreateRootlessPod joins the specified pod if it is running or it creates a new user namespace
// if the pod is stopped
func (r *LocalRuntime) JoinOrCreateRootlessPod(pod *Pod) (bool, int, error) {
// Nothing to do in the remote case
return true, 0, nil
}
// Events monitors libpod/podman events over a varlink connection
func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
var more uint64

View File

@@ -1,9 +0,0 @@
package rootless
// Opts allows to customize how re-execing to a rootless process is done
type Opts struct {
// Argument overrides the arguments on the command line
// for the re-execed process. The process in the namespace
// must use rootless.Argument() to read its value.
Argument string
}

View File

@@ -13,10 +13,36 @@
#include <sys/wait.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <dirent.h>
static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces";
static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
static int n_files;
static void __attribute__((constructor)) init()
{
DIR *d;
/* Store how many FDs were open before the Go runtime kicked in. */
d = opendir ("/proc/self/fd");
if (d)
{
struct dirent *ent;
for (ent = readdir (d); ent; ent = readdir (d))
{
int fd = atoi (ent->d_name);
if (fd > n_files && fd != dirfd (d))
n_files = fd;
}
closedir (d);
}
}
static int
syscall_setresuid (uid_t ruid, uid_t euid, uid_t suid)
{
@@ -133,12 +159,25 @@ reexec_userns_join (int userns, int mountns)
pid = fork ();
if (pid < 0)
fprintf (stderr, "cannot fork: %s\n", strerror (errno));
if (pid)
return pid;
{
/* We passed down these fds, close them. */
int f;
for (f = 3; f < n_files; f++)
close (f);
return pid;
}
setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
setenv ("_CONTAINERS_ROOTLESS_UID", uid, 1);
if (prctl (PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) < 0)
{
fprintf (stderr, "cannot prctl(PR_SET_PDEATHSIG): %s\n", strerror (errno));
_exit (EXIT_FAILURE);
}
if (setns (userns, 0) < 0)
{
fprintf (stderr, "cannot setns: %s\n", strerror (errno));

View File

@@ -46,25 +46,6 @@ func IsRootless() bool {
return isRootless
}
var (
skipStorageSetup = false
)
// SetSkipStorageSetup tells the runtime to not setup containers/storage
func SetSkipStorageSetup(v bool) {
skipStorageSetup = v
}
// SkipStorageSetup tells if we should skip the containers/storage setup
func SkipStorageSetup() bool {
return skipStorageSetup
}
// Argument returns the argument that was set for the rootless session.
func Argument() string {
return os.Getenv("_CONTAINERS_ROOTLESS_ARG")
}
// GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int {
uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
@@ -104,51 +85,86 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
return nil
}
// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
// PID.
func JoinNS(pid uint, preserveFDs int) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
return false, -1, nil
}
userNS, err := getUserNSForPid(pid)
func readUserNs(path string) (string, error) {
b := make([]byte, 256)
_, err := syscall.Readlink(path, b)
if err != nil {
return false, -1, err
return "", err
}
defer userNS.Close()
return string(b), nil
}
pidC := C.reexec_userns_join(C.int(userNS.Fd()), -1)
if int(pidC) < 0 {
return false, -1, errors.Errorf("cannot re-exec process")
func readUserNsFd(fd uintptr) (string, error) {
return readUserNs(fmt.Sprintf("/proc/self/fd/%d", fd))
}
func getParentUserNs(fd uintptr) (uintptr, error) {
const nsGetParent = 0xb702
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(nsGetParent), 0)
if errno != 0 {
return 0, errno
}
if preserveFDs > 0 {
for fd := 3; fd < 3+preserveFDs; fd++ {
// These fds were passed down to the runtime. Close them
// and not interfere
os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close()
return (uintptr)(unsafe.Pointer(ret)), nil
}
// getUserNSFirstChild returns an open FD for the first direct child user namespace that created the process
// Each container creates a new user namespace where the runtime runs. The current process in the container
// might have created new user namespaces that are child of the initial namespace we created.
// This function finds the initial namespace created for the container that is a child of the current namespace.
//
// current ns
// / \
// TARGET -> a [other containers]
// /
// b
// /
// NS READ USING THE PID -> c
func getUserNSFirstChild(fd uintptr) (*os.File, error) {
currentNS, err := readUserNs("/proc/self/ns/user")
if err != nil {
return nil, err
}
ns, err := readUserNsFd(fd)
if err != nil {
return nil, errors.Wrapf(err, "cannot read user namespace")
}
if ns == currentNS {
return nil, errors.New("process running in the same user namespace")
}
for {
nextFd, err := getParentUserNs(fd)
if err != nil {
return nil, errors.Wrapf(err, "cannot get parent user namespace")
}
}
ret := C.reexec_in_user_namespace_wait(pidC)
if ret < 0 {
return false, -1, errors.New("error waiting for the re-exec process")
}
ns, err = readUserNsFd(nextFd)
if err != nil {
return nil, errors.Wrapf(err, "cannot read user namespace")
}
return true, int(ret), nil
if ns == currentNS {
syscall.Close(int(nextFd))
// Drop O_CLOEXEC for the fd.
_, _, errno := syscall.Syscall(syscall.SYS_FCNTL, fd, syscall.F_SETFD, 0)
if errno != 0 {
syscall.Close(int(fd))
return nil, errno
}
return os.NewFile(fd, "userns child"), nil
}
syscall.Close(int(fd))
fd = nextFd
}
}
// JoinDirectUserAndMountNS re-exec podman in a new userNS and join the user and mount
// JoinUserAndMountNS re-exec podman in a new userNS and join the user and mount
// namespace of the specified PID without looking up its parent. Useful to join directly
// the conmon process. It is a convenience function for JoinDirectUserAndMountNSWithOpts
// with a default configuration.
func JoinDirectUserAndMountNS(pid uint) (bool, int, error) {
return JoinDirectUserAndMountNSWithOpts(pid, nil)
}
// JoinDirectUserAndMountNSWithOpts re-exec podman in a new userNS and join the user and
// mount namespace of the specified PID without looking up its parent. Useful to join
// directly the conmon process.
func JoinDirectUserAndMountNSWithOpts(pid uint, opts *Opts) (bool, int, error) {
// the conmon process.
func JoinUserAndMountNS(pid uint) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
return false, -1, nil
}
@@ -165,39 +181,11 @@ func JoinDirectUserAndMountNSWithOpts(pid uint, opts *Opts) (bool, int, error) {
}
defer userNS.Close()
if opts != nil && opts.Argument != "" {
if err := os.Setenv("_CONTAINERS_ROOTLESS_ARG", opts.Argument); err != nil {
return false, -1, err
}
}
pidC := C.reexec_userns_join(C.int(userNS.Fd()), C.int(mountNS.Fd()))
if int(pidC) < 0 {
return false, -1, errors.Errorf("cannot re-exec process")
}
ret := C.reexec_in_user_namespace_wait(pidC)
if ret < 0 {
return false, -1, errors.New("error waiting for the re-exec process")
}
return true, int(ret), nil
}
// JoinNSPath re-exec podman in a new userNS and join the owner user namespace of the
// specified path.
func JoinNSPath(path string) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
return false, -1, nil
}
userNS, err := getUserNSForPath(path)
fd, err := getUserNSFirstChild(userNS.Fd())
if err != nil {
return false, -1, err
}
defer userNS.Close()
pidC := C.reexec_userns_join(C.int(userNS.Fd()), -1)
pidC := C.reexec_userns_join(C.int(fd.Fd()), C.int(mountNS.Fd()))
if int(pidC) < 0 {
return false, -1, errors.Errorf("cannot re-exec process")
}
@@ -213,16 +201,8 @@ func JoinNSPath(path string) (bool, int, error) {
// BecomeRootInUserNS re-exec podman in a new userNS. It returns whether podman was re-executed
// into a new user namespace and the return code from the re-executed podman process.
// If podman was re-executed the caller needs to propagate the error code returned by the child
// process. It is a convenience function for BecomeRootInUserNSWithOpts with a default configuration.
func BecomeRootInUserNS() (bool, int, error) {
return BecomeRootInUserNSWithOpts(nil)
}
// BecomeRootInUserNSWithOpts re-exec podman in a new userNS. It returns whether podman was
// re-execute into a new user namespace and the return code from the re-executed podman process.
// If podman was re-executed the caller needs to propagate the error code returned by the child
// process.
func BecomeRootInUserNSWithOpts(opts *Opts) (bool, int, error) {
func BecomeRootInUserNS() (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
if os.Getenv("_CONTAINERS_USERNS_CONFIGURED") == "init" {
return false, 0, runInUser()
@@ -241,12 +221,6 @@ func BecomeRootInUserNSWithOpts(opts *Opts) (bool, int, error) {
defer w.Close()
defer w.Write([]byte("0"))
if opts != nil && opts.Argument != "" {
if err := os.Setenv("_CONTAINERS_ROOTLESS_ARG", opts.Argument); err != nil {
return false, -1, err
}
}
pidC := C.reexec_in_user_namespace(C.int(r.Fd()))
pid := int(pidC)
if pid < 0 {
@@ -328,112 +302,3 @@ func BecomeRootInUserNSWithOpts(opts *Opts) (bool, int, error) {
return true, int(ret), nil
}
func readUserNs(path string) (string, error) {
b := make([]byte, 256)
_, err := syscall.Readlink(path, b)
if err != nil {
return "", err
}
return string(b), nil
}
func readUserNsFd(fd uintptr) (string, error) {
return readUserNs(fmt.Sprintf("/proc/self/fd/%d", fd))
}
func getOwner(fd uintptr) (uintptr, error) {
const nsGetUserns = 0xb701
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(nsGetUserns), 0)
if errno != 0 {
return 0, errno
}
return (uintptr)(unsafe.Pointer(ret)), nil
}
func getParentUserNs(fd uintptr) (uintptr, error) {
const nsGetParent = 0xb702
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(nsGetParent), 0)
if errno != 0 {
return 0, errno
}
return (uintptr)(unsafe.Pointer(ret)), nil
}
func getUserNSForPath(path string) (*os.File, error) {
u, err := os.Open(path)
if err != nil {
return nil, errors.Wrapf(err, "cannot open %s", path)
}
defer u.Close()
fd, err := getOwner(u.Fd())
if err != nil {
return nil, err
}
return getUserNSFirstChild(fd)
}
func getUserNSForPid(pid uint) (*os.File, error) {
path := fmt.Sprintf("/proc/%d/ns/user", pid)
u, err := os.Open(path)
if err != nil {
return nil, errors.Wrapf(err, "cannot open %s", path)
}
return getUserNSFirstChild(u.Fd())
}
// getUserNSFirstChild returns an open FD for the first direct child user namespace that created the process
// Each container creates a new user namespace where the runtime runs. The current process in the container
// might have created new user namespaces that are child of the initial namespace we created.
// This function finds the initial namespace created for the container that is a child of the current namespace.
//
// current ns
// / \
// TARGET -> a [other containers]
// /
// b
// /
// NS READ USING THE PID -> c
func getUserNSFirstChild(fd uintptr) (*os.File, error) {
currentNS, err := readUserNs("/proc/self/ns/user")
if err != nil {
return nil, err
}
ns, err := readUserNsFd(fd)
if err != nil {
return nil, errors.Wrapf(err, "cannot read user namespace")
}
if ns == currentNS {
return nil, errors.New("process running in the same user namespace")
}
for {
nextFd, err := getParentUserNs(fd)
if err != nil {
return nil, errors.Wrapf(err, "cannot get parent user namespace")
}
ns, err = readUserNsFd(nextFd)
if err != nil {
return nil, errors.Wrapf(err, "cannot read user namespace")
}
if ns == currentNS {
syscall.Close(int(nextFd))
// Drop O_CLOEXEC for the fd.
_, _, errno := syscall.Syscall(syscall.SYS_FCNTL, fd, syscall.F_SETFD, 0)
if errno != 0 {
syscall.Close(int(fd))
return nil, errno
}
return os.NewFile(fd, "userns child"), nil
}
syscall.Close(int(fd))
fd = nextFd
}
}

View File

@@ -19,54 +19,15 @@ func BecomeRootInUserNS() (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
// BecomeRootInUserNS is a stub function that always returns false and an
// error on unsupported OS's
func BecomeRootInUserNSWithOpts(opts *Opts) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
// GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int {
return -1
}
// SetSkipStorageSetup tells the runtime to not setup containers/storage
func SetSkipStorageSetup(bool) {
}
// SkipStorageSetup tells if we should skip the containers/storage setup
func SkipStorageSetup() bool {
return false
}
// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
// PID.
func JoinNS(pid uint, preserveFDs int) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
// JoinNSPath re-exec podman in a new userNS and join the owner user namespace of the
// specified path.
func JoinNSPath(path string) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
// JoinDirectUserAndMountNSWithOpts re-exec podman in a new userNS and join the user and
// mount namespace of the specified PID without looking up its parent. Useful to join
// directly the conmon process.
func JoinDirectUserAndMountNSWithOpts(pid uint, opts *Opts) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
// JoinDirectUserAndMountNS re-exec podman in a new userNS and join the user and mount
// JoinUserAndMountNS re-exec podman in a new userNS and join the user and mount
// namespace of the specified PID without looking up its parent. Useful to join directly
// the conmon process. It is a convenience function for JoinDirectUserAndMountNSWithOpts
// the conmon process. It is a convenience function for JoinUserAndMountNSWithOpts
// with a default configuration.
func JoinDirectUserAndMountNS(pid uint) (bool, int, error) {
func JoinUserAndMountNS(pid uint) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
// Argument returns the argument that was set for the rootless session.
func Argument() string {
return ""
}

View File

@@ -12,7 +12,6 @@ import (
"github.com/containers/image/manifest"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/namespaces"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
"github.com/cri-o/ocicni/pkg/ocicni"
@@ -271,7 +270,7 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e
func (c *CreateConfig) GetVolumesFrom() error {
var options string
if rootless.SkipStorageSetup() {
if os.Geteuid() != 0 {
return nil
}