summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-07-31 17:08:06 -0400
committerMatthew Heon <matthew.heon@pm.me>2020-08-20 12:16:53 -0400
commitd4c3365454d903077ece3c1a31367f639ee24900 (patch)
tree6d81363c00becc04d10b5d864c03e26948d1f9f7
parent66fcafa4d45a26b59ad3662419cd3c778e23c39c (diff)
downloadpodman-d4c3365454d903077ece3c1a31367f639ee24900.tar.gz
podman-d4c3365454d903077ece3c1a31367f639ee24900.tar.bz2
podman-d4c3365454d903077ece3c1a31367f639ee24900.zip
Ensure WORKDIR from images is created
A recent crun change stopped the creation of the container's working directory if it does not exist. This is arguably correct for user-specified directories, to protect against typos; it is definitely not correct for image WORKDIR, where the image author definitely intended for the directory to be used. This makes Podman create the working directory and chown it to container root, if it does not already exist, and only if it was specified by an image, not the user. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
-rw-r--r--libpod/container.go4
-rw-r--r--libpod/container_internal_linux.go27
-rw-r--r--libpod/options.go13
-rw-r--r--pkg/specgen/generate/container_create.go11
-rw-r--r--test/e2e/run_test.go10
5 files changed, 64 insertions, 1 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 9ad938a5c..644647bc9 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -261,6 +261,10 @@ type ContainerConfig struct {
Mounts []string `json:"mounts,omitempty"`
// NamedVolumes lists the named volumes to mount into the container.
NamedVolumes []*ContainerNamedVolume `json:"namedVolumes,omitempty"`
+ // CreateWorkingDir indicates that Libpod should create the container's
+ // working directory if it does not exist. Some OCI runtimes do this by
+ // default, but others do not.
+ CreateWorkingDir bool `json:"createWorkingDir,omitempty"`
// Security Config
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index b9e4f9a93..0d9a1c824 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -157,7 +157,32 @@ func (c *Container) prepare() error {
}
// Save changes to container state
- return c.save()
+ if err := c.save(); err != nil {
+ return err
+ }
+
+ // Ensure container entrypoint is created (if required)
+ if c.config.CreateWorkingDir {
+ workdir, err := securejoin.SecureJoin(c.state.Mountpoint, c.WorkingDir())
+ if err != nil {
+ return errors.Wrapf(err, "error creating path to container %s working dir", c.ID())
+ }
+ rootUID := c.RootUID()
+ rootGID := c.RootGID()
+
+ if err := os.MkdirAll(workdir, 0755); err != nil {
+ if os.IsExist(err) {
+ return nil
+ }
+ return errors.Wrapf(err, "error creating container %s working dir", c.ID())
+ }
+
+ if err := os.Chown(workdir, rootUID, rootGID); err != nil {
+ return errors.Wrapf(err, "error chowning container %s working directory to container root", c.ID())
+ }
+ }
+
+ return nil
}
// cleanupNetwork unmounts and cleans up the container's network
diff --git a/libpod/options.go b/libpod/options.go
index 560b406e2..a4e4b99e9 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1395,6 +1395,19 @@ func WithCreateCommand(cmd []string) CtrCreateOption {
}
}
+// WithCreateWorkingDir tells Podman to create the container's working directory
+// if it does not exist.
+func WithCreateWorkingDir() CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+
+ ctr.config.CreateWorkingDir = true
+ return nil
+ }
+}
+
// Volume Creation Options
// WithVolumeName sets the name of the volume.
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index b31bc91e0..42be5e812 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -215,6 +215,17 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
if s.Entrypoint != nil {
options = append(options, libpod.WithEntrypoint(s.Entrypoint))
}
+ // If the user did not set an workdir but the image did, ensure it is
+ // created.
+ if s.WorkDir == "" && img != nil {
+ newWD, err := img.WorkingDir(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if newWD != "" {
+ options = append(options, libpod.WithCreateWorkingDir())
+ }
+ }
if s.StopSignal != nil {
options = append(options, libpod.WithStopSignal(*s.StopSignal))
}
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 13f0db550..ef275b32e 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -1060,4 +1060,14 @@ USER mail`
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring(limit))
})
+
+ It("podman run makes entrypoint from image", func() {
+ dockerfile := `FROM busybox
+WORKDIR /madethis`
+ podmanTest.BuildImage(dockerfile, "test", "false")
+ session := podmanTest.Podman([]string{"run", "--rm", "test", "pwd"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/madethis"))
+ })
})