Fixes to handle /dev/shm correctly.

We had two problems with /dev/shm, first, you mount the
container read/only then /dev/shm was mounted read/only.
This is a bug a tmpfs directory should be read/write within
a read-only container.

The second problem is we were ignoring users mounted /dev/shm
from the host.

If user specified

podman run -d -v /dev/shm:/dev/shm ...

We were dropping this mount and still using the internal mount.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh 2018-12-24 06:55:24 -05:00
parent bbfe7341b7
commit df99522c67
No known key found for this signature in database
GPG Key ID: A2DF901DABE2C028
5 changed files with 13 additions and 6 deletions

View File

@ -851,7 +851,7 @@ func (c *Container) mountStorage() (string, error) {
return "", errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir) return "", errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir)
} }
if !mounted { if !mounted && !MountExists(c.config.Spec.Mounts, "/dev/shm") {
shmOptions := fmt.Sprintf("mode=1777,size=%d", c.config.ShmSize) shmOptions := fmt.Sprintf("mode=1777,size=%d", c.config.ShmSize)
if err := c.mountSHM(shmOptions); err != nil { if err := c.mountSHM(shmOptions); err != nil {
return "", err return "", err

View File

@ -210,9 +210,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
g.SetProcessSelinuxLabel(c.ProcessLabel()) g.SetProcessSelinuxLabel(c.ProcessLabel())
g.SetLinuxMountLabel(c.MountLabel()) g.SetLinuxMountLabel(c.MountLabel())
// Remove the default /dev/shm mount to ensure we overwrite it
g.RemoveMount("/dev/shm")
// Add bind mounts to container // Add bind mounts to container
for dstPath, srcPath := range c.state.BindMounts { for dstPath, srcPath := range c.state.BindMounts {
newMount := spec.Mount{ newMount := spec.Mount{
@ -221,7 +218,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
Destination: dstPath, Destination: dstPath,
Options: []string{"bind", "private"}, Options: []string{"bind", "private"},
} }
if c.IsReadOnly() { if c.IsReadOnly() && dstPath != "/dev/shm" {
newMount.Options = append(newMount.Options, "ro") newMount.Options = append(newMount.Options, "ro")
} }
if !MountExists(g.Mounts(), dstPath) { if !MountExists(g.Mounts(), dstPath) {

View File

@ -180,7 +180,8 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
if ctr.config.LogPath == "" { if ctr.config.LogPath == "" {
ctr.config.LogPath = filepath.Join(ctr.config.StaticDir, "ctr.log") ctr.config.LogPath = filepath.Join(ctr.config.StaticDir, "ctr.log")
} }
if ctr.config.ShmDir == "" {
if !MountExists(ctr.config.Spec.Mounts, "/dev/shm") && ctr.config.ShmDir == "" {
if ctr.state.UserNSRoot == "" { if ctr.state.UserNSRoot == "" {
ctr.config.ShmDir = filepath.Join(ctr.bundlePath(), "shm") ctr.config.ShmDir = filepath.Join(ctr.bundlePath(), "shm")
} else { } else {

View File

@ -52,6 +52,8 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Remove the default /dev/shm mount to ensure we overwrite it
g.RemoveMount("/dev/shm")
g.HostSpecific = true g.HostSpecific = true
addCgroup := true addCgroup := true
canMountSys := true canMountSys := true

View File

@ -669,4 +669,11 @@ USER mail`
numContainers := podmanTest.NumberOfContainers() numContainers := podmanTest.NumberOfContainers()
Expect(numContainers).To(Equal(1)) Expect(numContainers).To(Equal(1))
}) })
It("podman run readonly container should NOT mount /dev/shm read/only", func() {
session := podmanTest.Podman([]string{"run", "--read-only", ALPINE, "mount"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Not(ContainSubstring("/dev/shm type tmpfs (ro,")))
})
}) })