Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #3
0
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;
}