aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorDoug Rabson <dfr@rabson.org>2022-08-27 14:19:17 +0100
committerDoug Rabson <dfr@rabson.org>2022-09-05 10:17:49 +0100
commit232eea5a00f542081e0bade13b21b8b44b0ad906 (patch)
tree184513cebe37dd7e4e3d19f195963cab02af4605 /libpod
parenta5ee3cb79065907548e95fef5709f08f51041b69 (diff)
downloadpodman-232eea5a00f542081e0bade13b21b8b44b0ad906.tar.gz
podman-232eea5a00f542081e0bade13b21b8b44b0ad906.tar.bz2
podman-232eea5a00f542081e0bade13b21b8b44b0ad906.zip
libpod: Move isWorkDirSymlink, resolveWorkDir to container_internal_common.go
[NO NEW TESTS NEEDED] Signed-off-by: Doug Rabson <dfr@rabson.org>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_internal_common.go113
-rw-r--r--libpod/container_internal_freebsd.go113
-rw-r--r--libpod/container_internal_linux.go113
3 files changed, 113 insertions, 226 deletions
diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go
index 2b11ff5b6..476ae1989 100644
--- a/libpod/container_internal_common.go
+++ b/libpod/container_internal_common.go
@@ -14,6 +14,7 @@ import (
"time"
cdi "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
+ "github.com/containers/buildah/pkg/chrootuser"
"github.com/containers/buildah/pkg/overlay"
butil "github.com/containers/buildah/util"
"github.com/containers/common/pkg/apparmor"
@@ -480,3 +481,115 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return g.Config, nil
}
+
+// isWorkDirSymlink returns true if resolved workdir is symlink or a chain of symlinks,
+// and final resolved target is present either on volume, mount or inside of container
+// otherwise it returns false. Following function is meant for internal use only and
+// can change at any point of time.
+func (c *Container) isWorkDirSymlink(resolvedPath string) bool {
+ // We cannot create workdir since explicit --workdir is
+ // set in config but workdir could also be a symlink.
+ // If it's a symlink, check if the resolved target is present in the container.
+ // If so, that's a valid use case: return nil.
+
+ maxSymLinks := 0
+ for {
+ // Linux only supports a chain of 40 links.
+ // Reference: https://github.com/torvalds/linux/blob/master/include/linux/namei.h#L13
+ if maxSymLinks > 40 {
+ break
+ }
+ resolvedSymlink, err := os.Readlink(resolvedPath)
+ if err != nil {
+ // End sym-link resolution loop.
+ break
+ }
+ if resolvedSymlink != "" {
+ _, resolvedSymlinkWorkdir, err := c.resolvePath(c.state.Mountpoint, resolvedSymlink)
+ if isPathOnVolume(c, resolvedSymlinkWorkdir) || isPathOnBindMount(c, resolvedSymlinkWorkdir) {
+ // Resolved symlink exists on external volume or mount
+ return true
+ }
+ if err != nil {
+ // Could not resolve path so end sym-link resolution loop.
+ break
+ }
+ if resolvedSymlinkWorkdir != "" {
+ resolvedPath = resolvedSymlinkWorkdir
+ _, err := os.Stat(resolvedSymlinkWorkdir)
+ if err == nil {
+ // Symlink resolved successfully and resolved path exists on container,
+ // this is a valid use-case so return nil.
+ logrus.Debugf("Workdir is a symlink with target to %q and resolved symlink exists on container", resolvedSymlink)
+ return true
+ }
+ }
+ }
+ maxSymLinks++
+ }
+ return false
+}
+
+// resolveWorkDir resolves the container's workdir and, depending on the
+// configuration, will create it, or error out if it does not exist.
+// Note that the container must be mounted before.
+func (c *Container) resolveWorkDir() error {
+ workdir := c.WorkingDir()
+
+ // If the specified workdir is a subdir of a volume or mount,
+ // we don't need to do anything. The runtime is taking care of
+ // that.
+ if isPathOnVolume(c, workdir) || isPathOnBindMount(c, workdir) {
+ logrus.Debugf("Workdir %q resolved to a volume or mount", workdir)
+ return nil
+ }
+
+ _, resolvedWorkdir, err := c.resolvePath(c.state.Mountpoint, workdir)
+ if err != nil {
+ return err
+ }
+ logrus.Debugf("Workdir %q resolved to host path %q", workdir, resolvedWorkdir)
+
+ st, err := os.Stat(resolvedWorkdir)
+ if err == nil {
+ if !st.IsDir() {
+ return fmt.Errorf("workdir %q exists on container %s, but is not a directory", workdir, c.ID())
+ }
+ return nil
+ }
+ if !c.config.CreateWorkingDir {
+ // No need to create it (e.g., `--workdir=/foo`), so let's make sure
+ // the path exists on the container.
+ if err != nil {
+ if os.IsNotExist(err) {
+ // If resolved Workdir path gets marked as a valid symlink,
+ // return nil cause this is valid use-case.
+ if c.isWorkDirSymlink(resolvedWorkdir) {
+ return nil
+ }
+ return fmt.Errorf("workdir %q does not exist on container %s", workdir, c.ID())
+ }
+ // This might be a serious error (e.g., permission), so
+ // we need to return the full error.
+ return fmt.Errorf("error detecting workdir %q on container %s: %w", workdir, c.ID(), err)
+ }
+ return nil
+ }
+ if err := os.MkdirAll(resolvedWorkdir, 0755); err != nil {
+ if os.IsExist(err) {
+ return nil
+ }
+ return fmt.Errorf("error creating container %s workdir: %w", c.ID(), err)
+ }
+
+ // Ensure container entrypoint is created (if required).
+ uid, gid, _, err := chrootuser.GetUser(c.state.Mountpoint, c.User())
+ if err != nil {
+ return fmt.Errorf("error looking up %s inside of the container %s: %w", c.User(), c.ID(), err)
+ }
+ if err := os.Chown(resolvedWorkdir, int(uid), int(gid)); err != nil {
+ return fmt.Errorf("error chowning container %s workdir to container root: %w", c.ID(), err)
+ }
+
+ return nil
+}
diff --git a/libpod/container_internal_freebsd.go b/libpod/container_internal_freebsd.go
index c180528cb..f460ca49a 100644
--- a/libpod/container_internal_freebsd.go
+++ b/libpod/container_internal_freebsd.go
@@ -21,7 +21,6 @@ import (
metadata "github.com/checkpoint-restore/checkpointctl/lib"
"github.com/checkpoint-restore/go-criu/v5/stats"
- "github.com/containers/buildah/pkg/chrootuser"
"github.com/containers/buildah/pkg/overlay"
"github.com/containers/common/libnetwork/etchosts"
"github.com/containers/common/libnetwork/resolvconf"
@@ -150,118 +149,6 @@ func (c *Container) prepare() error {
return nil
}
-// isWorkDirSymlink returns true if resolved workdir is symlink or a chain of symlinks,
-// and final resolved target is present either on volume, mount or inside of container
-// otherwise it returns false. Following function is meant for internal use only and
-// can change at any point of time.
-func (c *Container) isWorkDirSymlink(resolvedPath string) bool {
- // We cannot create workdir since explicit --workdir is
- // set in config but workdir could also be a symlink.
- // If it's a symlink, check if the resolved target is present in the container.
- // If so, that's a valid use case: return nil.
-
- maxSymLinks := 0
- for {
- // Linux only supports a chain of 40 links.
- // Reference: https://github.com/torvalds/linux/blob/master/include/linux/namei.h#L13
- if maxSymLinks > 40 {
- break
- }
- resolvedSymlink, err := os.Readlink(resolvedPath)
- if err != nil {
- // End sym-link resolution loop.
- break
- }
- if resolvedSymlink != "" {
- _, resolvedSymlinkWorkdir, err := c.resolvePath(c.state.Mountpoint, resolvedSymlink)
- if isPathOnVolume(c, resolvedSymlinkWorkdir) || isPathOnBindMount(c, resolvedSymlinkWorkdir) {
- // Resolved symlink exists on external volume or mount
- return true
- }
- if err != nil {
- // Could not resolve path so end sym-link resolution loop.
- break
- }
- if resolvedSymlinkWorkdir != "" {
- resolvedPath = resolvedSymlinkWorkdir
- _, err := os.Stat(resolvedSymlinkWorkdir)
- if err == nil {
- // Symlink resolved successfully and resolved path exists on container,
- // this is a valid use-case so return nil.
- logrus.Debugf("Workdir is a symlink with target to %q and resolved symlink exists on container", resolvedSymlink)
- return true
- }
- }
- }
- maxSymLinks++
- }
- return false
-}
-
-// resolveWorkDir resolves the container's workdir and, depending on the
-// configuration, will create it, or error out if it does not exist.
-// Note that the container must be mounted before.
-func (c *Container) resolveWorkDir() error {
- workdir := c.WorkingDir()
-
- // If the specified workdir is a subdir of a volume or mount,
- // we don't need to do anything. The runtime is taking care of
- // that.
- if isPathOnVolume(c, workdir) || isPathOnBindMount(c, workdir) {
- logrus.Debugf("Workdir %q resolved to a volume or mount", workdir)
- return nil
- }
-
- _, resolvedWorkdir, err := c.resolvePath(c.state.Mountpoint, workdir)
- if err != nil {
- return err
- }
- logrus.Debugf("Workdir %q resolved to host path %q", workdir, resolvedWorkdir)
-
- st, err := os.Stat(resolvedWorkdir)
- if err == nil {
- if !st.IsDir() {
- return fmt.Errorf("workdir %q exists on container %s, but is not a directory", workdir, c.ID())
- }
- return nil
- }
- if !c.config.CreateWorkingDir {
- // No need to create it (e.g., `--workdir=/foo`), so let's make sure
- // the path exists on the container.
- if err != nil {
- if os.IsNotExist(err) {
- // If resolved Workdir path gets marked as a valid symlink,
- // return nil cause this is valid use-case.
- if c.isWorkDirSymlink(resolvedWorkdir) {
- return nil
- }
- return fmt.Errorf("workdir %q does not exist on container %s", workdir, c.ID())
- }
- // This might be a serious error (e.g., permission), so
- // we need to return the full error.
- return fmt.Errorf("error detecting workdir %q on container %s: %w", workdir, c.ID(), err)
- }
- return nil
- }
- if err := os.MkdirAll(resolvedWorkdir, 0755); err != nil {
- if os.IsExist(err) {
- return nil
- }
- return fmt.Errorf("error creating container %s workdir: %w", c.ID(), err)
- }
-
- // Ensure container entrypoint is created (if required).
- uid, gid, _, err := chrootuser.GetUser(c.state.Mountpoint, c.User())
- if err != nil {
- return fmt.Errorf("error looking up %s inside of the container %s: %w", c.User(), c.ID(), err)
- }
- if err := os.Chown(resolvedWorkdir, int(uid), int(gid)); err != nil {
- return fmt.Errorf("error chowning container %s workdir to container root: %w", c.ID(), err)
- }
-
- return nil
-}
-
// cleanupNetwork unmounts and cleans up the container's network
func (c *Container) cleanupNetwork() error {
if c.config.NetNsCtr != "" {
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index bd50ceb45..16a576947 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -23,7 +23,6 @@ import (
"github.com/checkpoint-restore/go-criu/v5/stats"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/buildah"
- "github.com/containers/buildah/pkg/chrootuser"
"github.com/containers/buildah/pkg/overlay"
"github.com/containers/common/libnetwork/etchosts"
"github.com/containers/common/libnetwork/resolvconf"
@@ -175,118 +174,6 @@ func (c *Container) prepare() error {
return nil
}
-// isWorkDirSymlink returns true if resolved workdir is symlink or a chain of symlinks,
-// and final resolved target is present either on volume, mount or inside of container
-// otherwise it returns false. Following function is meant for internal use only and
-// can change at any point of time.
-func (c *Container) isWorkDirSymlink(resolvedPath string) bool {
- // We cannot create workdir since explicit --workdir is
- // set in config but workdir could also be a symlink.
- // If it's a symlink, check if the resolved target is present in the container.
- // If so, that's a valid use case: return nil.
-
- maxSymLinks := 0
- for {
- // Linux only supports a chain of 40 links.
- // Reference: https://github.com/torvalds/linux/blob/master/include/linux/namei.h#L13
- if maxSymLinks > 40 {
- break
- }
- resolvedSymlink, err := os.Readlink(resolvedPath)
- if err != nil {
- // End sym-link resolution loop.
- break
- }
- if resolvedSymlink != "" {
- _, resolvedSymlinkWorkdir, err := c.resolvePath(c.state.Mountpoint, resolvedSymlink)
- if isPathOnVolume(c, resolvedSymlinkWorkdir) || isPathOnBindMount(c, resolvedSymlinkWorkdir) {
- // Resolved symlink exists on external volume or mount
- return true
- }
- if err != nil {
- // Could not resolve path so end sym-link resolution loop.
- break
- }
- if resolvedSymlinkWorkdir != "" {
- resolvedPath = resolvedSymlinkWorkdir
- _, err := os.Stat(resolvedSymlinkWorkdir)
- if err == nil {
- // Symlink resolved successfully and resolved path exists on container,
- // this is a valid use-case so return nil.
- logrus.Debugf("Workdir is a symlink with target to %q and resolved symlink exists on container", resolvedSymlink)
- return true
- }
- }
- }
- maxSymLinks++
- }
- return false
-}
-
-// resolveWorkDir resolves the container's workdir and, depending on the
-// configuration, will create it, or error out if it does not exist.
-// Note that the container must be mounted before.
-func (c *Container) resolveWorkDir() error {
- workdir := c.WorkingDir()
-
- // If the specified workdir is a subdir of a volume or mount,
- // we don't need to do anything. The runtime is taking care of
- // that.
- if isPathOnVolume(c, workdir) || isPathOnBindMount(c, workdir) {
- logrus.Debugf("Workdir %q resolved to a volume or mount", workdir)
- return nil
- }
-
- _, resolvedWorkdir, err := c.resolvePath(c.state.Mountpoint, workdir)
- if err != nil {
- return err
- }
- logrus.Debugf("Workdir %q resolved to host path %q", workdir, resolvedWorkdir)
-
- st, err := os.Stat(resolvedWorkdir)
- if err == nil {
- if !st.IsDir() {
- return fmt.Errorf("workdir %q exists on container %s, but is not a directory", workdir, c.ID())
- }
- return nil
- }
- if !c.config.CreateWorkingDir {
- // No need to create it (e.g., `--workdir=/foo`), so let's make sure
- // the path exists on the container.
- if err != nil {
- if os.IsNotExist(err) {
- // If resolved Workdir path gets marked as a valid symlink,
- // return nil cause this is valid use-case.
- if c.isWorkDirSymlink(resolvedWorkdir) {
- return nil
- }
- return fmt.Errorf("workdir %q does not exist on container %s", workdir, c.ID())
- }
- // This might be a serious error (e.g., permission), so
- // we need to return the full error.
- return fmt.Errorf("error detecting workdir %q on container %s: %w", workdir, c.ID(), err)
- }
- return nil
- }
- if err := os.MkdirAll(resolvedWorkdir, 0755); err != nil {
- if os.IsExist(err) {
- return nil
- }
- return fmt.Errorf("error creating container %s workdir: %w", c.ID(), err)
- }
-
- // Ensure container entrypoint is created (if required).
- uid, gid, _, err := chrootuser.GetUser(c.state.Mountpoint, c.User())
- if err != nil {
- return fmt.Errorf("error looking up %s inside of the container %s: %w", c.User(), c.ID(), err)
- }
- if err := os.Chown(resolvedWorkdir, int(uid), int(gid)); err != nil {
- return fmt.Errorf("error chowning container %s workdir to container root: %w", c.ID(), err)
- }
-
- return nil
-}
-
// cleanupNetwork unmounts and cleans up the container's network
func (c *Container) cleanupNetwork() error {
if c.config.NetNsCtr != "" {