diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2018-08-23 23:02:04 +0200 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-08-26 07:22:42 +0000 |
commit | 720eb85ba55d8c825262e9b2e058ec8a8e0e4d9f (patch) | |
tree | 73ef0abad027bc6bffe97d75b6936b8c7562cca8 | |
parent | 1ac4dbb50861d502cb819c63335848a60ffa7dec (diff) | |
download | podman-720eb85ba55d8c825262e9b2e058ec8a8e0e4d9f.tar.gz podman-720eb85ba55d8c825262e9b2e058ec8a8e0e4d9f.tar.bz2 podman-720eb85ba55d8c825262e9b2e058ec8a8e0e4d9f.zip |
rootless: fix exec
We cannot re-exec into a new user namespace to gain privileges and
access an existing as the new namespace is not the owner of the
existing container.
"unshare" is used to join the user namespace of the target container.
The current implementation assumes that the main process of the
container didn't create a new user namespace.
Since in the setup phase we are not running with euid=0, we must skip
the setup for containers/storage.
Closes: https://github.com/containers/libpod/issues/1329
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Closes: #1331
Approved by: rhatdan
-rw-r--r-- | cmd/podman/exec.go | 2 | ||||
-rw-r--r-- | cmd/podman/main.go | 2 | ||||
-rw-r--r-- | libpod/oci.go | 6 | ||||
-rw-r--r-- | libpod/runtime.go | 19 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 14 | ||||
-rw-r--r-- | pkg/rootless/rootless_unsupported.go | 9 | ||||
-rw-r--r-- | test/e2e/rootless_test.go | 13 |
7 files changed, 58 insertions, 7 deletions
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index 17a17f703..0cd6f98b7 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -6,6 +6,7 @@ import ( "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -66,6 +67,7 @@ func execCmd(c *cli.Context) error { if c.Bool("latest") { argStart = 0 } + rootless.SetSkipStorageSetup(true) cmd := args[argStart:] runtime, err := libpodruntime.GetRuntime(c) if err != nil { diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 053049266..1734a2c9e 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -25,7 +25,7 @@ var ( exitCode = 125 ) -var cmdsNotRequiringRootless = map[string]bool{"help": true, "version": true} +var cmdsNotRequiringRootless = map[string]bool{"help": true, "version": true, "exec": true} func main() { debug := false diff --git a/libpod/oci.go b/libpod/oci.go index 9021a522b..da054eceb 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -681,6 +681,12 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty logrus.Debugf("Starting runtime %s with following arguments: %v", r.path, args) execCmd := exec.Command(r.path, args...) + if rootless.IsRootless() { + args = append([]string{"--preserve-credentials", "-U", "-t", fmt.Sprintf("%d", c.state.PID), r.path}, args...) + // using nsenter might not be correct if the target PID joined a different user namespace. + // A better way would be to retrieve the parent ns (NS_GET_PARENT) until it is a child of the current namespace. + execCmd = exec.Command("nsenter", args...) + } execCmd.Stdout = os.Stdout execCmd.Stderr = os.Stderr execCmd.Stdin = os.Stdin diff --git a/libpod/runtime.go b/libpod/runtime.go index adeb901f2..2df4ef760 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -405,9 +405,14 @@ func makeRuntime(runtime *Runtime) (err error) { } // Set up containers/storage - store, err := storage.GetStore(runtime.config.StorageConfig) - if err != nil { - return err + var store storage.Store + if rootless.SkipStorageSetup() { + logrus.Debug("Not configuring container store") + } else { + store, err = storage.GetStore(runtime.config.StorageConfig) + if err != nil { + return err + } } runtime.store = store @@ -424,7 +429,7 @@ func makeRuntime(runtime *Runtime) (err error) { // Setting signaturepolicypath ir.SignaturePolicyPath = runtime.config.SignaturePolicyPath defer func() { - if err != nil { + if err != nil && store != nil { // Don't forcibly shut down // We could be opening a store in use by another libpod _, err2 := store.Shutdown(false) @@ -611,8 +616,10 @@ func (r *Runtime) Shutdown(force bool) error { } var lastError error - if _, err := r.store.Shutdown(force); err != nil { - lastError = errors.Wrapf(err, "Error shutting down container storage") + if r.store != nil { + if _, err := r.store.Shutdown(force); err != nil { + lastError = errors.Wrapf(err, "Error shutting down container storage") + } } if err := r.state.Close(); err != nil { if lastError != nil { diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 490ddc33e..26f4b0b18 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -34,6 +34,20 @@ func IsRootless() bool { return os.Getuid() != 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" } +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 +} + // GetRootlessUID returns the UID of the user in the parent userNS func GetRootlessUID() int { uidEnv := os.Getenv("_LIBPOD_ROOTLESS_UID") diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go index b1f075045..11dfd5aa4 100644 --- a/pkg/rootless/rootless_unsupported.go +++ b/pkg/rootless/rootless_unsupported.go @@ -21,3 +21,12 @@ func BecomeRootInUserNS() (bool, int, error) { 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 +} diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go index f77ad9924..8813d040d 100644 --- a/test/e2e/rootless_test.go +++ b/test/e2e/rootless_test.go @@ -102,6 +102,19 @@ var _ = Describe("Podman rootless", func() { cmd.WaitWithDefaultTimeout() Expect(cmd.LineInOutputContains("hello")).To(BeTrue()) Expect(cmd.ExitCode()).To(Equal(0)) + + allArgsD := append([]string{"run", "-d"}, args...) + allArgsD = append(allArgsD, "--rootfs", mountPath, "sleep", "1d") + cmd = podmanTest.PodmanAsUser(allArgsD, 1000, 1000, env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Equal(0)) + cid := cmd.OutputToStringArray()[0] + + allArgsE := []string{"exec", cid, "echo", "hello"} + cmd = podmanTest.PodmanAsUser(allArgsE, 1000, 1000, env) + cmd.WaitWithDefaultTimeout() + Expect(cmd.ExitCode()).To(Equal(0)) + Expect(cmd.LineInOutputContains("hello")).To(BeTrue()) } runRootless(mountPath) |