int collect_mount_info(pid_t pid) { pr_info("Collecting mountinfo\n"); mntinfo = parse_mountinfo(pid); if (!mntinfo) { pr_err("Parsing mountinfo %d failed\n", getpid()); return -1; } return 0; }
/** * Read /proc/self/mountinfo and check if /run/snapd/ns is a private bind mount. * * We do this because /run/snapd/ns cannot be shared with any other peers as per: * https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt **/ static bool sc_is_ns_group_dir_private() { struct mountinfo *info __attribute__ ((cleanup(cleanup_mountinfo))) = NULL; info = parse_mountinfo(NULL); if (info == NULL) { die("cannot parse /proc/self/mountinfo"); } struct mountinfo_entry *entry = first_mountinfo_entry(info); while (entry != NULL) { const char *mount_dir = mountinfo_entry_mount_dir(entry); const char *optional_fields = mountinfo_entry_optional_fields(entry); if (strcmp(mount_dir, sc_ns_dir) == 0 && strcmp(optional_fields, "") == 0) { // If /run/snapd/ns has no optional fields, we know it is mounted // private and there is nothing else to do. return true; } entry = next_mountinfo_entry(entry); } return false; }
int bind_mount (int proc_fd, const char *src, const char *dest, bind_option_t options) { bool readonly = (options & BIND_READONLY) != 0; bool devices = (options & BIND_DEVICES) != 0; bool recursive = (options & BIND_RECURSIVE) != 0; unsigned long current_flags, new_flags; cleanup_mount_tab MountTab mount_tab = NULL; cleanup_free char *resolved_dest = NULL; int i; if (src) { if (mount (src, dest, NULL, MS_BIND | (recursive ? MS_REC : 0), NULL) != 0) return 1; } /* The mount operation will resolve any symlinks in the destination path, so to find it in the mount table we need to do that too. */ resolved_dest = realpath (dest, NULL); if (resolved_dest == NULL) return 2; mount_tab = parse_mountinfo (proc_fd, resolved_dest); if (mount_tab[0].mountpoint == NULL) { errno = EINVAL; return 2; /* No mountpoint at dest */ } assert (path_equal (mount_tab[0].mountpoint, resolved_dest)); current_flags = mount_tab[0].options; new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0); if (new_flags != current_flags && mount ("none", resolved_dest, NULL, MS_BIND | MS_REMOUNT | new_flags, NULL) != 0) return 3; /* We need to work around the fact that a bind mount does not apply the flags, so we need to manually * apply the flags to all submounts in the recursive case. * Note: This does not apply the flags to mounts which are later propagated into this namespace. */ if (recursive) { for (i = 1; mount_tab[i].mountpoint != NULL; i++) { current_flags = mount_tab[i].options; new_flags = current_flags | (devices ? 0 : MS_NODEV) | MS_NOSUID | (readonly ? MS_RDONLY : 0); if (new_flags != current_flags && mount ("none", mount_tab[i].mountpoint, NULL, MS_BIND | MS_REMOUNT | new_flags, NULL) != 0) { /* If we can't read the mountpoint we can't remount it, but that should be safe to ignore because its not something the user can access. */ if (errno != EACCES) return 5; } } } return 0; }