Skip to content

Commit

Permalink
rootless: fix pod stop|rm if uid in the container != 0
Browse files Browse the repository at this point in the history
join the user namespace where the pod is running, so that we can both
manage the storage and correctly send the kill signal to a process
which is not running as root in the namespace.

Closes: containers#2577

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Mar 11, 2019
1 parent fa7ebe6 commit 10290b0
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cmd/podman/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ var cmdsNotRequiringRootless = map[*cobra.Command]bool{
_mountCommand: true,
_killCommand: true,
_pauseCommand: true,
_podRmCommand: true,
_podKillCommand: true,
_podStatsCommand: true,
_podStopCommand: true,
_restartCommand: true,
_rmCommand: true,
_runCommand: true,
Expand Down
47 changes: 47 additions & 0 deletions cmd/podman/pod.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
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"
)

Expand Down Expand Up @@ -34,6 +39,48 @@ 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())
Expand Down
14 changes: 14 additions & 0 deletions cmd/podman/pod_rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ 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"
Expand Down Expand Up @@ -46,11 +48,23 @@ 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)
Expand Down
14 changes: 14 additions & 0 deletions cmd/podman/pod_stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ 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"
Expand Down Expand Up @@ -46,12 +48,24 @@ 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)
Expand Down
40 changes: 40 additions & 0 deletions pkg/adapter/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,43 @@ func IsImageNotFound(err error) bool {
func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (libpod.HealthCheckStatus, error) {
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)
}
7 changes: 7 additions & 0 deletions pkg/adapter/runtime_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,3 +751,10 @@ func IsImageNotFound(err error) bool {
func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (libpod.HealthCheckStatus, error) {
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
}

0 comments on commit 10290b0

Please sign in to comment.