diff options
-rw-r--r-- | cmd/podman/create.go | 28 | ||||
-rw-r--r-- | cmd/podman/libpodruntime/runtime.go | 6 | ||||
-rw-r--r-- | cmd/podman/play_kube.go | 2 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 2 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 15 | ||||
-rw-r--r-- | pkg/varlinkapi/containers_create.go | 4 | ||||
-rwxr-xr-x | test/test_podman_baseline.sh | 24 | ||||
-rwxr-xr-x | test/test_podman_pods.sh | 8 | ||||
-rw-r--r-- | troubleshooting.md | 20 |
9 files changed, 71 insertions, 38 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go index d98b78bd4..1aa3425a5 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io/ioutil" "os" "path/filepath" "strconv" @@ -144,7 +145,7 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container return nil, nil, err } - ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx) + ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx, nil) if err != nil { return nil, nil, err } @@ -421,6 +422,16 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim } if c.IsSet("pod") { if strings.HasPrefix(originalPodName, "new:") { + if rootless.IsRootless() { + // To create a new pod, we must immediately create the userns. + became, ret, err := rootless.BecomeRootInUserNS() + if err != nil { + return nil, err + } + if became { + os.Exit(ret) + } + } // pod does not exist; lets make it var podOptions []libpod.PodCreateOption podOptions = append(podOptions, libpod.WithPodName(podName), libpod.WithInfraContainer(), libpod.WithPodCgroups()) @@ -785,11 +796,15 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l if s != libpod.ContainerStateRunning && s != libpod.ContainerStatePaused { continue } - pid, err := prevCtr.PID() + data, err := ioutil.ReadFile(prevCtr.Config().ConmonPidFile) if err != nil { - return false, -1, err + return false, -1, errors.Wrapf(err, "cannot read conmon PID file %q", prevCtr.Config().ConmonPidFile) } - return rootless.JoinNS(uint(pid)) + 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)) } } @@ -817,17 +832,16 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l return rootless.BecomeRootInUserNS() } -func createContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context) (*libpod.Container, error) { +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 { return nil, err } - options, err := createConfig.GetContainerCreateOptions(r) + options, err := createConfig.GetContainerCreateOptions(r, pod) if err != nil { return nil, err } - became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, r) if err != nil { return nil, err diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index d7a0dd931..dca2f5022 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -4,17 +4,15 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" - "github.com/containers/storage" "github.com/pkg/errors" "github.com/urfave/cli" ) // GetRuntime generates a new libpod runtime configured by command line options func GetRuntime(c *cli.Context) (*libpod.Runtime, error) { - storageOpts := new(storage.StoreOptions) options := []libpod.RuntimeOption{} - _, volumePath, err := util.GetDefaultStoreOptions() + storageOpts, volumePath, err := util.GetDefaultStoreOptions() if err != nil { return nil, err } @@ -44,7 +42,7 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) { storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt") } - options = append(options, libpod.WithStorageConfig(*storageOpts)) + options = append(options, libpod.WithStorageConfig(storageOpts)) // TODO CLI flags for image config? // TODO CLI flag for signature policy? diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index f165c5f0f..2ce2e21bb 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -154,7 +154,7 @@ func playKubeYAMLCmd(c *cli.Context) error { if err != nil { return err } - ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx) + ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx, pod) if err != nil { return err } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 4f490bb88..bcdfdaee3 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -226,7 +226,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { Options: []string{"bind", "private"}, } if c.IsReadOnly() && dstPath != "/dev/shm" { - newMount.Options = append(newMount.Options, "ro") + newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev") } if !MountExists(g.Mounts(), dstPath) { g.AddMount(newMount) diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 87fce7e2e..632d60b55 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -341,10 +341,9 @@ func (c *CreateConfig) createExitCommand() []string { } // GetContainerCreateOptions takes a CreateConfig and returns a slice of CtrCreateOptions -func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCreateOption, error) { +func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *libpod.Pod) ([]libpod.CtrCreateOption, error) { var options []libpod.CtrCreateOption var portBindings []ocicni.PortMapping - var pod *libpod.Pod var err error if c.Interactive { @@ -358,12 +357,14 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib logrus.Debugf("appending name %s", c.Name) options = append(options, libpod.WithName(c.Name)) } - if c.Pod != "" { - logrus.Debugf("adding container to pod %s", c.Pod) - pod, err = runtime.LookupPod(c.Pod) - if err != nil { - return nil, errors.Wrapf(err, "unable to add container to pod %s", c.Pod) + if c.Pod != "" || pod != nil { + if pod == nil { + pod, err = runtime.LookupPod(c.Pod) + if err != nil { + return nil, errors.Wrapf(err, "unable to add container to pod %s", c.Pod) + } } + logrus.Debugf("adding container to pod %s", c.Pod) options = append(options, runtime.WithPod(pod)) } if len(c.PortBindings) > 0 { diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go index 63bc93686..d72eaeb18 100644 --- a/pkg/varlinkapi/containers_create.go +++ b/pkg/varlinkapi/containers_create.go @@ -41,7 +41,9 @@ func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.C return call.ReplyErrorOccurred(err.Error()) } - options, err := createConfig.GetContainerCreateOptions(i.Runtime) + // TODO fix when doing remote client and dealing with the ability to create a container + // within a non-existing pod (i.e. --pod new:foobar) + options, err := createConfig.GetContainerCreateOptions(i.Runtime, nil) if err != nil { return call.ReplyErrorOccurred(err.Error()) } diff --git a/test/test_podman_baseline.sh b/test/test_podman_baseline.sh index ca19058fd..8a878b4e7 100755 --- a/test/test_podman_baseline.sh +++ b/test/test_podman_baseline.sh @@ -60,7 +60,7 @@ podman ps --all ######## # Run ls in redis container, this should work ######## -ctrid=$(podman pull registry.access.redhat.com/rhscl/redis-32-rhel7) +ctrid=$(podman pull docker.io/library/redis:4-alpine3.8) podman run $ctrid ls / ######## @@ -72,7 +72,7 @@ podman rmi --all ######## # Create Fedora based image ######## -image=$(podman pull fedora) +image=$(podman pull registry.fedoraproject.org/fedora:latest) echo $image ######## @@ -113,7 +113,7 @@ podman images ######## # Create Fedora based container ######## -image=$(podman pull fedora) +image=$(podman pull registry.fedoraproject.org/fedora:latest) echo $image podman run $image ls / @@ -207,7 +207,7 @@ mount -t xfs -o prjquota $device $TMPDIR ######## # Expected to succeed ######## -podman $PODMANBASE run --security-opt label=disable alpine sh -c 'touch file.txt && dd if=/dev/zero of=file.txt count=1048576 bs=1' +podman $PODMANBASE run --security-opt label=disable docker.io/library/alpine:latest sh -c 'touch file.txt && dd if=/dev/zero of=file.txt count=1048576 bs=1' rc=$? if [ $rc == 0 ]; then @@ -221,7 +221,7 @@ fi ######## if [ "$showerror" -ne 1 ]; then - podman $PODMANBASE run --security-opt label=disable alpine sh -c 'touch file.txt && dd if=/dev/zero of=file.txt count=1048577 bs=1' + podman $PODMANBASE run --security-opt label=disable docker.io/library/alpine:latest sh -c 'touch file.txt && dd if=/dev/zero of=file.txt count=1048577 bs=1' rc=$? if [ $rc != 0 ]; then @@ -283,7 +283,7 @@ chmod +x $FILE ######## FILE=./Dockerfile /bin/cat <<EOM >$FILE -FROM debian +FROM docker.io/library/debian:latest ADD ./runtest.sh /runtest.sh EOM chmod +x $FILE @@ -327,7 +327,7 @@ rm -f ./Dockerfile ######## FILE=./Dockerfile /bin/cat <<EOM >$FILE -FROM alpine +FROM docker.io/library/alpine:latest RUN touch /foo ONBUILD RUN touch /bar EOM @@ -363,7 +363,7 @@ rm ./Dockerfile* ######## if aa-enabled >/dev/null && getent passwd 1000 >/dev/null; then # Expected to succeed - sudo -u "#1000" podman run alpine echo hello + sudo -u "#1000" podman run docker.io/library/alpine:latest echo hello rc=$? echo -n "rootless with no AppArmor profile " if [ $rc == 0 ]; then @@ -373,7 +373,7 @@ if aa-enabled >/dev/null && getent passwd 1000 >/dev/null; then fi # Expected to succeed - sudo -u "#1000" podman run --security-opt apparmor=unconfined alpine echo hello + sudo -u "#1000" podman run --security-opt apparmor=unconfined docker.io/library/alpine:latest echo hello rc=$? echo -n "rootless with unconfined AppArmor profile " if [ $rc == 0 ]; then @@ -402,7 +402,7 @@ EOF apparmor_parser -Kr $aaFile #Expected to pass (as root) - podman run --security-opt apparmor=$aaProfile alpine echo hello + podman run --security-opt apparmor=$aaProfile docker.io/library/alpine:latest echo hello rc=$? echo -n "root with specified AppArmor profile: " if [ $rc == 0 ]; then @@ -412,7 +412,7 @@ EOF fi #Expected to fail (as rootless) - sudo -u "#1000" podman run --security-opt apparmor=$aaProfile alpine echo hello + sudo -u "#1000" podman run --security-opt apparmor=$aaProfile docker.io/library/alpine:latest echo hello rc=$? echo -n "rootless with specified AppArmor profile: " if [ $rc != 0 ]; then @@ -437,7 +437,7 @@ fi ######## FILE=./Dockerfile /bin/cat <<EOM >$FILE -FROM docker/whalesay:latest +FROM pharshal/whalesay:latest RUN apt-get -y update && apt-get install -y fortunes CMD /usr/games/fortune -a | cowsay EOM diff --git a/test/test_podman_pods.sh b/test/test_podman_pods.sh index 587f148cc..daa8acaee 100755 --- a/test/test_podman_pods.sh +++ b/test/test_podman_pods.sh @@ -60,8 +60,8 @@ podman ps --no-trunc | grep $ctrid ######## # Containers in a pod share network namespace ######## -podman run -dt --pod foobar quay.io/baude/alpine_nginx:latest -podman run -it --rm --pod foobar fedora-minimal:28 curl http://localhost +podman run -dt --pod foobar docker.io/library/nginx:latest +podman run -it --rm --pod foobar registry.fedoraproject.org/fedora-minimal:29 curl http://localhost ######## # There should be 3 containers running now @@ -91,7 +91,7 @@ podman pod stop foobar # Start a pod and its containers ######## podman pod start foobar -podman run -it --rm --pod foobar fedora-minimal:28 curl http://localhost +podman run -it --rm --pod foobar registry.fedoraproject.org/fedora-minimal:29 curl http://localhost ######## # Pause a pod and its containers @@ -103,7 +103,7 @@ podman pod pause foobar # Unpause a pod and its containers ######## podman pod unpause foobar -podman run -it --rm --pod foobar fedora-minimal:28 curl http://localhost +podman run -it --rm --pod foobar registry.fedoraproject.org/fedora-minimal:29 curl http://localhost ######## # Kill a pod and its containers diff --git a/troubleshooting.md b/troubleshooting.md index 561562193..ac3335da0 100644 --- a/troubleshooting.md +++ b/troubleshooting.md @@ -9,7 +9,7 @@ A large number of issues reported against Podman are often found to already be fixed in more current versions of the project. Before reporting an issue, please verify the -version you are running with `podman version` and compare it to the lastest release +version you are running with `podman version` and compare it to the latest release documented on the top of Podman's [README.md](README.md). If they differ, please update your version of PODMAN to the latest possible @@ -143,3 +143,21 @@ If you are using a useradd command within a Dockerfile with a large UID/GID, it #### Solution If the entry in the Dockerfile looked like: RUN useradd -u 99999000 -g users newuser then add the `--log-no-init` parameter to change it to: `RUN useradd --log-no-init -u 99999000 -g users newuser`. This option tells useradd to stop creating the lastlog file. + +### 7) Permission denied when running Podman commands + +When rootless podman attempts to execute a container on a non exec home directory a permission error will be raised. + +#### Symptom + +If you are running podman or buildah on a home directory that is mounted noexec, +then they will fail. With a message like: + +``` +podman run centos:7 +standard_init_linux.go:203: exec user process caused "permission denied" +``` + +#### Solution + +Since the administrator of the system setup your home directory to be noexec, you will not be allowed to execute containers from storage in your home directory. It is possible to work around this by manually specifying a container storage path that is not on a noexec mount. Simply copy the file /etc/containers/storage.conf to ~/.config/containers/ (creating the directory if necessary). Specify a graphroot directory which is not on a noexec mount point and to which you have read/write privileges. You will need to modify other fields to writable directories as well. |