Browse code

Automatically set `may_detach_mounts=1` on startup

This is kernel config available in RHEL7.4 based kernels that enables
mountpoint removal where the mountpoint exists in other namespaces.
In particular this is important for making this pattern work:

```
umount -l /some/path
rm -r /some/path
```

Where `/some/path` exists in another mount namespace.
Setting this value will prevent `device or resource busy` errors when
attempting to the removal of `/some/path` in the example.

This setting is the default, and non-configurable, on upstream kernels
since 3.15.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2017/09/18 22:26:34
Showing 1 changed files
... ...
@@ -1297,7 +1297,39 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
1297 1297
 // setupDaemonProcess sets various settings for the daemon's process
1298 1298
 func setupDaemonProcess(config *config.Config) error {
1299 1299
 	// setup the daemons oom_score_adj
1300
-	return setupOOMScoreAdj(config.OOMScoreAdjust)
1300
+	if err := setupOOMScoreAdj(config.OOMScoreAdjust); err != nil {
1301
+		return err
1302
+	}
1303
+	return setMayDetachMounts()
1304
+}
1305
+
1306
+// This is used to allow removal of mountpoints that may be mounted in other
1307
+// namespaces on RHEL based kernels starting from RHEL 7.4.
1308
+// Without this setting, removals on these RHEL based kernels may fail with
1309
+// "device or resource busy".
1310
+// This setting is not available in upstream kernels as it is not configurable,
1311
+// but has been in the upstream kernels since 3.15.
1312
+func setMayDetachMounts() error {
1313
+	f, err := os.OpenFile("/proc/sys/fs/may_detach_mounts", os.O_WRONLY, 0)
1314
+	if err != nil {
1315
+		if os.IsNotExist(err) {
1316
+			return nil
1317
+		}
1318
+		return errors.Wrap(err, "error opening may_detach_mounts kernel config file")
1319
+	}
1320
+	defer f.Close()
1321
+
1322
+	_, err = f.WriteString("1")
1323
+	if os.IsPermission(err) {
1324
+		// Setting may_detach_mounts does not work in an
1325
+		// unprivileged container. Ignore the error, but log
1326
+		// it if we appear not to be in that situation.
1327
+		if !rsystem.RunningInUserNS() {
1328
+			logrus.Debugf("Permission denied writing %q to /proc/sys/fs/may_detach_mounts", "1")
1329
+		}
1330
+		return nil
1331
+	}
1332
+	return err
1301 1333
 }
1302 1334
 
1303 1335
 func setupOOMScoreAdj(score int) error {