mirror of
https://github.com/containers/podman.git
synced 2025-06-21 01:19:15 +08:00
Fix problem copying files when container is in host pid namespace
When attempting to copy files into and out of running containers within the host pidnamespace, the code was attempting to join the host pidns again, and getting an error. This was causing the podman cp command to fail. Since we are already in the host pid namespace, we should not be attempting to join. This PR adds a check to see if the container is in NOT host pid namespace, and only then attempts to join. Fixes: https://github.com/containers/podman/issues/9985 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -237,21 +237,32 @@ func (c *Container) joinMountAndExec(ctx context.Context, f func() error) error
|
|||||||
}
|
}
|
||||||
defer mountFD.Close()
|
defer mountFD.Close()
|
||||||
|
|
||||||
pidFD, err := getFD(PIDNS)
|
inHostPidNS, err := c.inHostPidNS()
|
||||||
|
if err != nil {
|
||||||
|
errChan <- errors.Wrap(err, "checking inHostPidNS")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var pidFD *os.File
|
||||||
|
if !inHostPidNS {
|
||||||
|
pidFD, err = getFD(PIDNS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer pidFD.Close()
|
defer pidFD.Close()
|
||||||
|
}
|
||||||
|
|
||||||
if err := unix.Unshare(unix.CLONE_NEWNS); err != nil {
|
if err := unix.Unshare(unix.CLONE_NEWNS); err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pidFD != nil {
|
||||||
if err := unix.Setns(int(pidFD.Fd()), unix.CLONE_NEWPID); err != nil {
|
if err := unix.Setns(int(pidFD.Fd()), unix.CLONE_NEWPID); err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err := unix.Setns(int(mountFD.Fd()), unix.CLONE_NEWNS); err != nil {
|
if err := unix.Setns(int(mountFD.Fd()), unix.CLONE_NEWNS); err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
|
@ -892,3 +892,26 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
|
|||||||
|
|
||||||
return hostConfig, nil
|
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
|
||||||
|
}
|
||||||
|
@ -91,6 +91,50 @@ var _ = Describe("Podman cp", func() {
|
|||||||
Expect(roundtripContent).To(Equal(originalContent))
|
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
|
// 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
|
// make sure that the link and the resolved path are accessible and
|
||||||
// give the right content.
|
// give the right content.
|
||||||
|
@ -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" {
|
@test "podman cp file from container to host" {
|
||||||
srcdir=$PODMAN_TMPDIR/cp-test-file-ctr-to-host
|
srcdir=$PODMAN_TMPDIR/cp-test-file-ctr-to-host
|
||||||
mkdir -p $srcdir
|
mkdir -p $srcdir
|
||||||
|
Reference in New Issue
Block a user