From be9eaee9e25e6b389fcfacd8829bc1235269527b Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Sun, 20 Aug 2017 13:50:52 +1000 Subject: [PATCH] devicemapper: remove container rootfs mountPath after umount libdm currently has a fairly substantial DoS bug that makes certain operations fail on a libdm device if the device has active references through mountpoints. This is a significant problem with the advent of mount namespaces and MS_PRIVATE, and can cause certain --volume mounts to cause libdm to no longer be able to remove containers: % docker run -d --name testA busybox top % docker run -d --name testB -v /var/lib/docker:/docker busybox top % docker rm -f testA [fails on libdm with dm_task_run errors.] This also solves the problem of unprivileged users being able to DoS docker by using unprivileged mount namespaces to preseve mounts that Docker has dropped. SUSE-Bug: https://bugzilla.suse.com/show_bug.cgi?id=1045628 SUSE-Backport: https://github.com/moby/moby/pull/34573 Signed-off-by: Aleksa Sarai --- daemon/graphdriver/devmapper/deviceset.go | 12 ++++++++++++ daemon/graphdriver/devmapper/driver.go | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index ba845d4d01d4..fe8103683b9b 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -2402,6 +2402,18 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { } logrus.Debug("devmapper: Unmount done") + // Remove the mountpoint here. Removing the mountpoint (in newer kernels) + // will cause all other instances of this mount in other mount namespaces + // to be killed (this is an anti-DoS measure that is necessary for things + // like devicemapper). This is necessary to avoid cases where a libdm mount + // that is present in another namespace will cause subsequent RemoveDevice + // operations to fail. We ignore any errors here because this may fail on + // older kernels which don't have + // torvalds/linux@8ed936b5671bfb33d89bc60bdcc7cf0470ba52fe applied. + if err := os.Remove(mountPath); err != nil { + logrus.Debugf("devmapper: error doing a remove on unmounted device %s: %v", mountPath, err) + } + return devices.deactivateDevice(info) } diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 91de5cd12a0f..69a3b3184933 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -227,10 +227,12 @@ func (d *Driver) Put(id string) error { if count := d.ctr.Decrement(mp); count > 0 { return nil } + err := d.DeviceSet.UnmountDevice(id, mp) if err != nil { - logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err) + logrus.Errorf("devmapper: Error unmounting device %s: %v", id, err) } + return err } -- 2.14.1