diff options
author | Doug Rabson <dfr@rabson.org> | 2022-08-25 08:47:42 +0100 |
---|---|---|
committer | Doug Rabson <dfr@rabson.org> | 2022-09-20 08:36:23 +0100 |
commit | 88f82ceab2b14b0523a56cd8c6b3a9cec8a323e2 (patch) | |
tree | 7357697636b6b805a7e07ada9a8d5cf5bb0f39cc /libpod/container_copy_linux.go | |
parent | 75d6e7bae5abb73fb248a6c4766ab799a030cb93 (diff) | |
download | podman-88f82ceab2b14b0523a56cd8c6b3a9cec8a323e2.tar.gz podman-88f82ceab2b14b0523a56cd8c6b3a9cec8a323e2.tar.bz2 podman-88f82ceab2b14b0523a56cd8c6b3a9cec8a323e2.zip |
libpod: Move jointMountAndExec to container_copy_linux.go
This also moves the logic for resolving paths in running and stopped
containers tp container_copy_linux.go.
On FreeBSD, we can execute the function argument to joinMountAndExec
directly using host-relative paths since the host mount namespace
includes all the container mounts.
[NO NEW TESTS NEEDED]
Signed-off-by: Doug Rabson <dfr@rabson.org>
Diffstat (limited to 'libpod/container_copy_linux.go')
-rw-r--r-- | libpod/container_copy_linux.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go new file mode 100644 index 000000000..3b029f08f --- /dev/null +++ b/libpod/container_copy_linux.go @@ -0,0 +1,88 @@ +package libpod + +import ( + "fmt" + "os" + "runtime" + + "github.com/containers/podman/v4/libpod/define" + "golang.org/x/sys/unix" +) + +// joinMountAndExec executes the specified function `f` inside the container's +// mount and PID namespace. That allows for having the exact view on the +// container's file system. +// +// Note, if the container is not running `f()` will be executed as is. +func (c *Container) joinMountAndExec(f func() error) error { + if c.state.State != define.ContainerStateRunning { + return f() + } + + // Container's running, so we need to execute `f()` inside its mount NS. + errChan := make(chan error) + go func() { + runtime.LockOSThread() + + // Join the mount and PID NS of the container. + getFD := func(ns LinuxNS) (*os.File, error) { + nsPath, err := c.namespacePath(ns) + if err != nil { + return nil, err + } + return os.Open(nsPath) + } + + mountFD, err := getFD(MountNS) + if err != nil { + errChan <- err + return + } + defer mountFD.Close() + + inHostPidNS, err := c.inHostPidNS() + if err != nil { + errChan <- fmt.Errorf("checking inHostPidNS: %w", err) + return + } + var pidFD *os.File + if !inHostPidNS { + pidFD, err = getFD(PIDNS) + if err != nil { + errChan <- err + return + } + defer pidFD.Close() + } + + 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 + } + + // Last but not least, execute the workload. + errChan <- f() + }() + return <-errChan +} + +func (c *Container) resolveCopyTarget(mountPoint string, containerPath string) (string, string, error) { + // If the container is running, we will execute the copy + // inside the container's mount namespace so we return a path + // relative to the container's root. + if c.state.State == define.ContainerStateRunning { + return "/", c.pathAbs(containerPath), nil + } + return c.resolvePath(mountPoint, containerPath) +} |