Pārlūkot izejas kodu

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.

Signed-off-by: Aleksa Sarai <asarai@suse.de>
Aleksa Sarai 8 gadi atpakaļ
vecāks
revīzija
92e45b81e0

+ 12 - 0
daemon/graphdriver/devmapper/deviceset.go

@@ -2416,6 +2416,18 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error {
 	}
 	}
 	logrus.Debug("devmapper: Unmount done")
 	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)
 	return devices.deactivateDevice(info)
 }
 }
 
 

+ 3 - 1
daemon/graphdriver/devmapper/driver.go

@@ -228,10 +228,12 @@ func (d *Driver) Put(id string) error {
 	if count := d.ctr.Decrement(mp); count > 0 {
 	if count := d.ctr.Decrement(mp); count > 0 {
 		return nil
 		return nil
 	}
 	}
+
 	err := d.DeviceSet.UnmountDevice(id, mp)
 	err := d.DeviceSet.UnmountDevice(id, mp)
 	if err != nil {
 	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
 	return err
 }
 }