diff options
-rw-r--r-- | cmd/podman/common/create_opts.go | 2 | ||||
-rw-r--r-- | cmd/podman/common/specgen.go | 64 | ||||
-rw-r--r-- | cmd/podman/containers/create.go | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 4 | ||||
-rw-r--r-- | test/e2e/run_ns_test.go | 31 | ||||
-rw-r--r-- | test/system/070-build.bats | 74 | ||||
-rwxr-xr-x | test/system/helpers.t | 2 |
7 files changed, 143 insertions, 36 deletions
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index 3802c37b0..f9e4d7ca5 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -10,7 +10,7 @@ type ContainerCLIOpts struct { BlkIOWeightDevice []string CapAdd []string CapDrop []string - CGroupsNS string + CgroupNS string CGroupsMode string CGroupParent string CIDFile string diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 07c88efea..0b6897d3a 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -186,6 +186,46 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts) (*specs.Linu return memory, nil } +func setNamespaces(s *specgen.SpecGenerator, c *ContainerCLIOpts) error { + var err error + + if c.PID != "" { + s.PidNS, err = specgen.ParseNamespace(c.PID) + if err != nil { + return err + } + } + if c.IPC != "" { + s.IpcNS, err = specgen.ParseNamespace(c.IPC) + if err != nil { + return err + } + } + if c.UTS != "" { + s.UtsNS, err = specgen.ParseNamespace(c.UTS) + if err != nil { + return err + } + } + if c.CgroupNS != "" { + s.CgroupNS, err = specgen.ParseNamespace(c.CgroupNS) + if err != nil { + return err + } + } + // userns must be treated differently + if c.UserNS != "" { + s.UserNS, err = specgen.ParseUserNamespace(c.UserNS) + if err != nil { + return err + } + } + if c.Net != nil { + s.NetNS = c.Net.Network + } + return nil +} + func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) error { var ( err error @@ -252,28 +292,8 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } s.Expose = expose - for k, v := range map[string]*specgen.Namespace{ - c.IPC: &s.IpcNS, - c.PID: &s.PidNS, - c.UTS: &s.UtsNS, - c.CGroupsNS: &s.CgroupNS, - } { - if k != "" { - *v, err = specgen.ParseNamespace(k) - if err != nil { - return err - } - } - } - // userns must be treated differently - if c.UserNS != "" { - s.UserNS, err = specgen.ParseUserNamespace(c.UserNS) - if err != nil { - return err - } - } - if c.Net != nil { - s.NetNS = c.Net.Network + if err := setNamespaces(s, c); err != nil { + return err } if sig := c.StopSignal; len(sig) > 0 { diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index dcbc52b56..dd77dc9d7 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -195,7 +195,7 @@ func createInit(c *cobra.Command) error { cliVals.IPC = c.Flag("ipc").Value.String() cliVals.UTS = c.Flag("uts").Value.String() cliVals.PID = c.Flag("pid").Value.String() - cliVals.CGroupsNS = c.Flag("cgroupns").Value.String() + cliVals.CgroupNS = c.Flag("cgroupns").Value.String() if c.Flag("entrypoint").Changed { val := c.Flag("entrypoint").Value.String() cliVals.Entrypoint = &val diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index b959b947f..4fdb7f81b 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -1411,9 +1411,9 @@ required for VPN, without it containers need to be run with the **--network=host Environment variables within containers can be set using multiple different options, in the following order of precedence (later entries override earlier entries): -- **--env-host**: Host environment of the process executing Podman is added. -- **--http-proxy**: By default, several environment variables will be passed in from the host, such as **http_proxy** and **no_proxy**. See **--http-proxy** for details. - Container image: Any environment variables specified in the container image. +- **--http-proxy**: By default, several environment variables will be passed in from the host, such as **http_proxy** and **no_proxy**. See **--http-proxy** for details. +- **--env-host**: Host environment of the process executing Podman is added. - **--env-file**: Any environment variables specified via env-files. If multiple files specified, then they override each other in order of entry. - **--env**: Any environment variables specified will override previous settings. diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go index 2b6da2888..5242e04d2 100644 --- a/test/e2e/run_ns_test.go +++ b/test/e2e/run_ns_test.go @@ -2,6 +2,7 @@ package integration import ( "os" + "os/exec" "strings" . "github.com/containers/podman/v2/test/utils" @@ -102,4 +103,34 @@ var _ = Describe("Podman run ns", func() { session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) }) + + It("podman run --ipc=host --pid=host", func() { + cmd := exec.Command("ls", "-l", "/proc/self/ns/pid") + res, err := cmd.Output() + Expect(err).To(BeNil()) + fields := strings.Split(string(res), " ") + hostPidNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + + cmd = exec.Command("ls", "-l", "/proc/self/ns/ipc") + res, err = cmd.Output() + Expect(err).To(BeNil()) + fields = strings.Split(string(res), " ") + hostIpcNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + + session := podmanTest.Podman([]string{"run", "--ipc=host", "--pid=host", ALPINE, "ls", "-l", "/proc/self/ns/pid"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + fields = strings.Split(session.OutputToString(), " ") + ctrPidNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + + session = podmanTest.Podman([]string{"run", "--ipc=host", "--pid=host", ALPINE, "ls", "-l", "/proc/self/ns/ipc"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + fields = strings.Split(session.OutputToString(), " ") + ctrIpcNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + + Expect(hostPidNS).To(Equal(ctrPidNS)) + Expect(hostIpcNS).To(Equal(ctrIpcNS)) + }) + }) diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 84d3adec1..accdc9315 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -109,6 +109,7 @@ EOF s_env1=$(random_string 20) s_env2=$(random_string 25) s_env3=$(random_string 30) + s_env4=$(random_string 40) # Label name: make sure it begins with a letter! jq barfs if you # try to ask it for '.foo.<N>xyz', i.e. any string beginning with digit @@ -118,11 +119,17 @@ EOF # Command to run on container startup with no args cat >$tmpdir/mycmd <<EOF #!/bin/sh +PATH=/usr/bin:/bin pwd echo "\$1" -echo "\$MYENV1" -echo "\$MYENV2" -echo "\$MYENV3" +printenv | grep MYENV | sort | sed -e 's/^MYENV.=//' +EOF + + # For overridding with --env-file + cat >$PODMAN_TMPDIR/env-file <<EOF +MYENV3=$s_env3 +http_proxy=http-proxy-in-env-file +https_proxy=https-proxy-in-env-file EOF cat >$tmpdir/Containerfile <<EOF @@ -130,11 +137,25 @@ FROM $IMAGE LABEL $label_name=$label_value RUN mkdir $workdir WORKDIR $workdir + +# Test for #7094 - chowning of invalid symlinks +RUN mkdir -p /a/b/c +RUN ln -s /no/such/nonesuch /a/b/c/badsymlink +RUN ln -s /bin/mydefaultcmd /a/b/c/goodsymlink +RUN touch /a/b/c/myfile +RUN chown -h 1:2 /a/b/c/badsymlink /a/b/c/goodsymlink /a/b/c/myfile +VOLUME /a/b/c + +# Test for environment passing and override ENV MYENV1=$s_env1 -ENV MYENV2 $s_env2 -ENV MYENV3 this-should-be-overridden +ENV MYENV2 this-should-be-overridden-by-env-host +ENV MYENV3 this-should-be-overridden-by-env-file +ENV MYENV4 this-should-be-overridden-by-cmdline +ENV http_proxy http-proxy-in-image +ENV ftp_proxy ftp-proxy-in-image ADD mycmd /bin/mydefaultcmd RUN chmod 755 /bin/mydefaultcmd +RUN chown 2:3 /bin/mydefaultcmd CMD ["/bin/mydefaultcmd","$s_echo"] EOF @@ -143,12 +164,28 @@ EOF run_podman build -t build_test -f build-test/Containerfile build-test # Run without args - should run the above script. Verify its output. - run_podman run --rm -e MYENV3="$s_env3" build_test + export MYENV2="$s_env2" + export MYENV3="env-file-should-override-env-host!" + run_podman run --rm \ + --env-file=$PODMAN_TMPDIR/env-file \ + --env-host \ + -e MYENV4="$s_env4" \ + build_test is "${lines[0]}" "$workdir" "container default command: pwd" is "${lines[1]}" "$s_echo" "container default command: output from echo" is "${lines[2]}" "$s_env1" "container default command: env1" is "${lines[3]}" "$s_env2" "container default command: env2" - is "${lines[4]}" "$s_env3" "container default command: env3 (from cmdline)" + is "${lines[4]}" "$s_env3" "container default command: env3 (from envfile)" + is "${lines[5]}" "$s_env4" "container default command: env4 (from cmdline)" + + # Proxies - environment should override container, but not env-file + http_proxy=http-proxy-from-env ftp_proxy=ftp-proxy-from-env \ + run_podman run --rm --env-file=$PODMAN_TMPDIR/env-file \ + build_test \ + printenv http_proxy https_proxy ftp_proxy + is "${lines[0]}" "http-proxy-in-env-file" "env-file overrides env" + is "${lines[1]}" "https-proxy-in-env-file" "env-file sets proxy var" + is "${lines[2]}" "ftp-proxy-from-env" "ftp-proxy is passed through" # test that workdir is set for command-line commands also run_podman run --rm build_test pwd @@ -159,8 +196,9 @@ EOF run_podman image inspect build_test tests=" Env[1] | MYENV1=$s_env1 -Env[2] | MYENV2=$s_env2 -Env[3] | MYENV3=this-should-be-overridden +Env[2] | MYENV2=this-should-be-overridden-by-env-host +Env[3] | MYENV3=this-should-be-overridden-by-env-file +Env[4] | MYENV4=this-should-be-overridden-by-cmdline Cmd[0] | /bin/mydefaultcmd Cmd[1] | $s_echo WorkingDir | $workdir @@ -173,6 +211,24 @@ Labels.$label_name | $label_value is "$actual" "$expect" "jq .Config.$field" done + # Bad symlink in volume. Prior to #7094, well, we wouldn't actually + # get here because any 'podman run' on a volume that had symlinks, + # be they dangling or valid, would barf with + # Error: chown <mountpath>/_data/symlink: ENOENT + run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/badsymlink + is "$output" "0:0:'/a/b/c/badsymlink' -> '/no/such/nonesuch'" \ + "bad symlink to nonexistent file is chowned and preserved" + + run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/goodsymlink + is "$output" "0:0:'/a/b/c/goodsymlink' -> '/bin/mydefaultcmd'" \ + "good symlink to existing file is chowned and preserved" + + run_podman run --rm build_test stat -c'%u:%g' /bin/mydefaultcmd + is "$output" "2:3" "target of symlink is not chowned" + + run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/myfile + is "$output" "0:0:/a/b/c/myfile" "file in volume is chowned to root" + # Clean up run_podman rmi -f build_test } diff --git a/test/system/helpers.t b/test/system/helpers.t index a022f11c4..bee09505c 100755 --- a/test/system/helpers.t +++ b/test/system/helpers.t @@ -6,7 +6,7 @@ # anything if we have to mess with them. # -source $(dirname $0)/helpers.bash +source "$(dirname $0)"/helpers.bash die() { echo "$(basename $0): $*" >&2 |