summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2021-02-05 06:04:30 -0500
committerDaniel J Walsh <dwalsh@redhat.com>2021-02-16 14:18:53 -0500
commit5d1ec2960df41b15040534e6507932cc5cf83542 (patch)
tree71b529a7872a33e111339f2d37ab8a2bfbe1410f
parent7fb347a3d40afeb4c565c2066fbade7f003e3e50 (diff)
downloadpodman-5d1ec2960df41b15040534e6507932cc5cf83542.tar.gz
podman-5d1ec2960df41b15040534e6507932cc5cf83542.tar.bz2
podman-5d1ec2960df41b15040534e6507932cc5cf83542.zip
Do not reset storage when running inside of a container
Currently if the host shares container storage with a container running podman, the podman inside of the container resets the storage on the host. This can cause issues on the host, as well as causes the podman command running the container, to fail to unmount /dev/shm. podman run -ti --rm --privileged -v /var/lib/containers:/var/lib/containers quay.io/podman/stable podman run alpine echo hello * unlinkat /var/lib/containers/storage/overlay-containers/a7f3c9deb0656f8de1d107e7ddff2d3c3c279c11c1635f233a0bffb16051fb2c/userdata/shm: device or resource busy * unlinkat /var/lib/containers/storage/overlay-containers/a7f3c9deb0656f8de1d107e7ddff2d3c3c279c11c1635f233a0bffb16051fb2c/userdata/shm: device or resource busy Since podman is volume mounting in the graphroot, it will add a flag to /run/.containerenv to tell podman inside of container whether to reset storage or not. Since the inner podman is running inside of the container, no reason to assume this is a fresh reboot, so if "container" environment variable is set then skip reset of storage. Also added tests to make sure /run/.containerenv is runnig correctly. Fixes: https://github.com/containers/podman/issues/9191 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
-rw-r--r--libpod/container_internal_linux.go4
-rw-r--r--libpod/runtime.go37
-rw-r--r--test/e2e/run_test.go23
3 files changed, 59 insertions, 5 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 2360d0737..edbbefb55 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1627,7 +1627,7 @@ func (c *Container) makeBindMounts() error {
// Make .containerenv if it does not exist
if _, ok := c.state.BindMounts["/run/.containerenv"]; !ok {
- var containerenv string
+ containerenv := c.runtime.graphRootMountedFlag(c.config.Spec.Mounts)
isRootless := 0
if rootless.IsRootless() {
isRootless = 1
@@ -1642,7 +1642,7 @@ id=%q
image=%q
imageid=%q
rootless=%d
-`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless)
+%s`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless, containerenv)
}
containerenvPath, err := c.writeStringToRundir(".containerenv", containerenv)
if err != nil {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 42af2046d..c04d91b9d 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "bufio"
"context"
"fmt"
"os"
@@ -26,6 +27,7 @@ import (
"github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/docker/pkg/namesgenerator"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -622,9 +624,12 @@ func (r *Runtime) Shutdown(force bool) error {
func (r *Runtime) refresh(alivePath string) error {
logrus.Debugf("Podman detected system restart - performing state refresh")
- // First clear the state in the database
- if err := r.state.Refresh(); err != nil {
- return err
+ // Clear state of database if not running in container
+ if !graphRootMounted() {
+ // First clear the state in the database
+ if err := r.state.Refresh(); err != nil {
+ return err
+ }
}
// Next refresh the state of all containers to recreate dirs and
@@ -904,3 +909,29 @@ func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) {
func (r *Runtime) GetSecretsStorageDir() string {
return filepath.Join(r.store.GraphRoot(), "secrets")
}
+
+func graphRootMounted() bool {
+ f, err := os.OpenFile("/run/.containerenv", os.O_RDONLY, os.ModePerm)
+ if err != nil {
+ return false
+ }
+ defer f.Close()
+
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ if scanner.Text() == "graphRootMounted=1" {
+ return true
+ }
+ }
+ return false
+}
+
+func (r *Runtime) graphRootMountedFlag(mounts []spec.Mount) string {
+ root := r.store.GraphRoot()
+ for _, val := range mounts {
+ if strings.HasPrefix(root, val.Source) {
+ return "graphRootMounted=1"
+ }
+ }
+ return ""
+}
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 18db63c15..f333b8afd 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -47,6 +47,29 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
})
+ It("podman run check /run/.containerenv", func() {
+ session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(""))
+
+ session = podmanTest.Podman([]string{"run", "--privileged", "--name=test1", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("name=\"test1\""))
+ Expect(session.OutputToString()).To(ContainSubstring("image=\"" + ALPINE + "\""))
+
+ session = podmanTest.Podman([]string{"run", "-v", "/:/host", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1"))
+
+ session = podmanTest.Podman([]string{"run", "-v", "/:/host", "--privileged", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1"))
+ })
+
It("podman run a container based on a complex local image name", func() {
imageName := strings.TrimPrefix(nginx, "quay.io/")
session := podmanTest.Podman([]string{"run", imageName, "ls"})