namespace: when setting up an inaccessible mount point, unmounting everything below

This has the benefit of not triggering any autofs mount points
unnecessarily.
This commit is contained in:
Lennart Poettering 2014-06-05 21:35:35 +02:00
parent c3544e8d2c
commit 6d313367d9
3 changed files with 76 additions and 0 deletions

View File

@ -284,6 +284,12 @@ static int apply_mount(
return mount_dev(m);
case INACCESSIBLE:
/* First, get rid of everything that is below if there
* is anything... Then, overmount it with an
* inaccessible directory. */
umount_recursive(m->path, 0);
what = "/run/systemd/inaccessible";
break;

View File

@ -54,6 +54,7 @@
#include <grp.h>
#include <sys/mman.h>
#include <sys/vfs.h>
#include <sys/mount.h>
#include <linux/magic.h>
#include <limits.h>
#include <langinfo.h>
@ -6502,3 +6503,70 @@ int update_reboot_param_file(const char *param) {
return r;
}
int umount_recursive(const char *prefix, int flags) {
bool again;
int n = 0, r;
/* Try to umount everything recursively below a
* directory. Also, take care of stacked mounts, and keep
* unmounting them until they are gone. */
do {
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
again = false;
r = 0;
proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
if (!proc_self_mountinfo)
return -errno;
for (;;) {
_cleanup_free_ char *path = NULL, *p = NULL;
int k;
k = fscanf(proc_self_mountinfo,
"%*s " /* (1) mount id */
"%*s " /* (2) parent id */
"%*s " /* (3) major:minor */
"%*s " /* (4) root */
"%ms " /* (5) mount point */
"%*s" /* (6) mount options */
"%*[^-]" /* (7) optional fields */
"- " /* (8) separator */
"%*s " /* (9) file system type */
"%*s" /* (10) mount source */
"%*s" /* (11) mount options 2 */
"%*[^\n]", /* some rubbish at the end */
&path);
if (k != 1) {
if (k == EOF)
break;
continue;
}
p = cunescape(path);
if (!p)
return -ENOMEM;
if (!path_startswith(p, prefix))
continue;
if (umount2(p, flags) < 0) {
r = -errno;
continue;
}
again = true;
n++;
break;
}
} while (again);
return r ? r : n;
}

View File

@ -942,3 +942,5 @@ union file_handle_union {
};
int update_reboot_param_file(const char *param);
int umount_recursive(const char *target, int flags);