Skip to content

Commit

Permalink
Merge pull request #10327 from rhatdan/copy
Browse files Browse the repository at this point in the history
Fix problem copying files when container is in host pid namespace
  • Loading branch information
openshift-merge-robot authored May 19, 2021
2 parents 18efc5a + bc0e12a commit 4683225
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 7 deletions.
25 changes: 18 additions & 7 deletions libpod/container_copy_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,21 +237,32 @@ func (c *Container) joinMountAndExec(ctx context.Context, f func() error) error
}
defer mountFD.Close()

pidFD, err := getFD(PIDNS)
inHostPidNS, err := c.inHostPidNS()
if err != nil {
errChan <- err
errChan <- errors.Wrap(err, "checking inHostPidNS")
return
}
defer pidFD.Close()
if err := unix.Unshare(unix.CLONE_NEWNS); err != nil {
errChan <- err
return
var pidFD *os.File
if !inHostPidNS {
pidFD, err = getFD(PIDNS)
if err != nil {
errChan <- err
return
}
defer pidFD.Close()
}
if err := unix.Setns(int(pidFD.Fd()), unix.CLONE_NEWPID); err != nil {

if err := unix.Unshare(unix.CLONE_NEWNS); err != nil {
errChan <- err
return
}

if pidFD != nil {
if err := unix.Setns(int(pidFD.Fd()), unix.CLONE_NEWPID); err != nil {
errChan <- err
return
}
}
if err := unix.Setns(int(mountFD.Fd()), unix.CLONE_NEWNS); err != nil {
errChan <- err
return
Expand Down
23 changes: 23 additions & 0 deletions libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -892,3 +892,26 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named

return hostConfig, nil
}

// Return true if the container is running in the host's PID NS.
func (c *Container) inHostPidNS() (bool, error) {
if c.config.PIDNsCtr != "" {
return false, nil
}
ctrSpec, err := c.specFromState()
if err != nil {
return false, err
}
if ctrSpec.Linux != nil {
// Locate the spec's PID namespace.
// If there is none, it's pid=host.
// If there is one and it has a path, it's "ns:".
// If there is no path, it's default - the empty string.
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == spec.PIDNamespace {
return false, nil
}
}
}
return true, nil
}
44 changes: 44 additions & 0 deletions test/e2e/cp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,50 @@ var _ = Describe("Podman cp", func() {
Expect(roundtripContent).To(Equal(originalContent))
})

// Copy a file to the container, then back to the host in --pid=host
It("podman cp --pid=host file", func() {
SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1")
srcFile, err := ioutil.TempFile("", "")
Expect(err).To(BeNil())
defer srcFile.Close()
defer os.Remove(srcFile.Name())

originalContent := []byte("podman cp file test")
err = ioutil.WriteFile(srcFile.Name(), originalContent, 0644)
Expect(err).To(BeNil())

// Create a container. NOTE that container mustn't be running for copying.
session := podmanTest.Podman([]string{"create", "--pid=host", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
name := session.OutputToString()

session = podmanTest.Podman([]string{"start", name})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

// The file will now be created (and written to).
session = podmanTest.Podman([]string{"cp", srcFile.Name(), name + ":foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

// Copy FROM the container.

destFile, err := ioutil.TempFile("", "")
Expect(err).To(BeNil())
defer destFile.Close()
defer os.Remove(destFile.Name())

session = podmanTest.Podman([]string{"cp", name + ":foo", destFile.Name()})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

// Now make sure the content matches.
roundtripContent, err := ioutil.ReadFile(destFile.Name())
Expect(err).To(BeNil())
Expect(roundtripContent).To(Equal(originalContent))
})

// Create a symlink in the container, use it as a copy destination and
// make sure that the link and the resolved path are accessible and
// give the right content.
Expand Down
16 changes: 16 additions & 0 deletions test/system/065-cp.bats
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,22 @@ load helpers
}


@test "podman cp file from/to host while --pid=host" {
if is_rootless && ! is_cgroupsv2; then
skip "'podman cp --pid=host' (rootless) only works with cgroups v2"
fi

srcdir=$PODMAN_TMPDIR/cp-pid-equals-host
mkdir -p $srcdir
touch $srcdir/hostfile

run_podman run --pid=host -d --name cpcontainer $IMAGE sleep infinity
run_podman cp $srcdir/hostfile cpcontainer:/tmp/hostfile
run_podman cp cpcontainer:/tmp/hostfile $srcdir/hostfile1
run_podman kill cpcontainer
run_podman rm -f cpcontainer
}

@test "podman cp file from container to host" {
srcdir=$PODMAN_TMPDIR/cp-test-file-ctr-to-host
mkdir -p $srcdir
Expand Down

0 comments on commit 4683225

Please sign in to comment.