Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
runtime: mount shared mountpoint readonly
Browse files Browse the repository at this point in the history
bindmount remount events are not propagated through mount subtrees,
so we have to remount the shared dir mountpoint directly.

E.g.,
```
mkdir -p source dest foo source/foo

mount -o bind --make-shared source dest

mount -o bind foo source/foo
echo bind mount rw
mount | grep foo
echo remount ro
mount -o remount,bind,ro source/foo
mount | grep foo
```
would result in:
```
bind mount rw
/dev/xvda1 on /home/ubuntu/source/foo type ext4 (rw,relatime,discard,data=ordered)
/dev/xvda1 on /home/ubuntu/dest/foo type ext4 (rw,relatime,discard,data=ordered)
remount ro
/dev/xvda1 on /home/ubuntu/source/foo type ext4 (ro,relatime,discard,data=ordered)
/dev/xvda1 on /home/ubuntu/dest/foo type ext4 (rw,relatime,discard,data=ordered)
```

The reason is that bind mount creats new mount structs and attaches them to different mount subtrees.
However, MS_REMOUNT only looks for existing mount structs to modify and does not try to propagate the
change to mount structs in other subtrees.

Fixes: #3041
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
  • Loading branch information
bergwolf authored and egernst committed Nov 5, 2020
1 parent 509eb6f commit 7739905
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 6 deletions.
15 changes: 11 additions & 4 deletions virtcontainers/container.go
Expand Up @@ -446,7 +446,7 @@ func (c *Container) setContainerState(state types.StateString) error {
return nil
}

func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir string) (string, bool, error) {
func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, hostMountDir, guestSharedDir string) (string, bool, error) {
randBytes, err := utils.GenerateRandomBytes(8)
if err != nil {
return "", false, err
Expand Down Expand Up @@ -480,12 +480,19 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s
}
} else {
// These mounts are created in the shared dir
mountDest := filepath.Join(hostSharedDir, filename)
mountDest := filepath.Join(hostMountDir, filename)
if err := bindMount(c.ctx, m.Source, mountDest, m.ReadOnly, "private"); err != nil {
return "", false, err
}
// Save HostPath mount value into the mount list of the container.
c.mounts[idx].HostPath = mountDest
// bindmount remount event is not propagated to mount subtrees, so we have to remount the shared dir mountpoint directly.
if m.ReadOnly {
mountDest = filepath.Join(hostSharedDir, filename)
if err := remountRo(c.ctx, mountDest); err != nil {
return "", false, err
}
}
}

return guestDest, false, nil
Expand All @@ -496,7 +503,7 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s
// It also updates the container mount list with the HostPath info, and store
// container mounts to the storage. This way, we will have the HostPath info
// available when we will need to unmount those mounts.
func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (sharedDirMounts map[string]Mount, ignoredMounts map[string]Mount, err error) {
func (c *Container) mountSharedDirMounts(hostSharedDir, hostMountDir, guestSharedDir string) (sharedDirMounts map[string]Mount, ignoredMounts map[string]Mount, err error) {
sharedDirMounts = make(map[string]Mount)
ignoredMounts = make(map[string]Mount)
var devicesToDetach []string
Expand Down Expand Up @@ -546,7 +553,7 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (

var ignore bool
var guestDest string
guestDest, ignore, err = c.shareFiles(m, idx, hostSharedDir, guestSharedDir)
guestDest, ignore, err = c.shareFiles(m, idx, hostSharedDir, hostMountDir, guestSharedDir)
if err != nil {
return nil, nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion virtcontainers/kata_agent.go
Expand Up @@ -1419,7 +1419,7 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
}

// Handle container mounts
newMounts, ignoredMounts, err := c.mountSharedDirMounts(getMountPath(sandbox.id), kataGuestSharedDir())
newMounts, ignoredMounts, err := c.mountSharedDirMounts(getSharePath(sandbox.id), getMountPath(sandbox.id), kataGuestSharedDir())
if err != nil {
return nil, err
}
Expand Down
5 changes: 5 additions & 0 deletions virtcontainers/mount.go
Expand Up @@ -273,6 +273,11 @@ func remount(ctx context.Context, mountflags uintptr, src string) error {
return nil
}

// remount a mount point as readonly
func remountRo(ctx context.Context, src string) error {
return remount(ctx, syscall.MS_BIND|syscall.MS_RDONLY, src)
}

// bindMountContainerRootfs bind mounts a container rootfs into a 9pfs shared
// directory between the guest and the host.
func bindMountContainerRootfs(ctx context.Context, shareDir, cid, cRootFs string, readonly bool) error {
Expand Down
2 changes: 1 addition & 1 deletion virtcontainers/sandbox_test.go
Expand Up @@ -1177,7 +1177,7 @@ func TestPreAddDevice(t *testing.T) {
},
}

mounts, ignoreMounts, err := container.mountSharedDirMounts("", "")
mounts, ignoreMounts, err := container.mountSharedDirMounts("", "", "")
assert.Nil(t, err)
assert.Equal(t, len(mounts), 0,
"mounts should contain nothing because it only contains a block device")
Expand Down

0 comments on commit 7739905

Please sign in to comment.