mirror of
https://github.com/containers/podman.git
synced 2025-07-02 00:30:00 +08:00
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>
This commit is contained in:
@ -5,11 +5,8 @@ package libpod
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
buildahCopiah "github.com/containers/buildah/copier"
|
||||
@ -21,7 +18,6 @@ import (
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir bool, rename map[string]string, reader io.Reader) (func() error, error) {
|
||||
@ -56,15 +52,10 @@ func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir boo
|
||||
}
|
||||
}
|
||||
|
||||
if c.state.State == define.ContainerStateRunning {
|
||||
resolvedRoot = "/"
|
||||
resolvedPath = c.pathAbs(path)
|
||||
} else {
|
||||
resolvedRoot, resolvedPath, err = c.resolvePath(mountPoint, path)
|
||||
if err != nil {
|
||||
unmount()
|
||||
return nil, err
|
||||
}
|
||||
resolvedRoot, resolvedPath, err = c.resolveCopyTarget(mountPoint, path)
|
||||
if err != nil {
|
||||
unmount()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var idPair *idtools.IDPair
|
||||
@ -220,71 +211,3 @@ func idtoolsToRuntimeSpec(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxI
|
||||
}
|
||||
return convertedIDMap
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
88
libpod/container_copy_linux.go
Normal file
88
libpod/container_copy_linux.go
Normal file
@ -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)
|
||||
}
|
Reference in New Issue
Block a user