Merge pull request #19101 from poettering/mount-util-fixes

Make recursive bind remounting handle failures gracefully
This commit is contained in:
Lennart Poettering
2021-03-31 10:37:49 +02:00
committed by GitHub
4 changed files with 253 additions and 182 deletions
+14 -16
View File
@@ -196,13 +196,15 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
if (statx(fd, filename, (FLAGS_SET(flags, AT_SYMLINK_FOLLOW) ? 0 : AT_SYMLINK_NOFOLLOW) |
(flags & AT_EMPTY_PATH) |
AT_NO_AUTOMOUNT, 0, &sx) < 0) {
AT_NO_AUTOMOUNT, STATX_TYPE, &sx) < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
return -errno;
/* If statx() is not available or forbidden, fall back to name_to_handle_at() below */
} else if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) /* yay! */
return FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
else if (FLAGS_SET(sx.stx_mask, STATX_TYPE) && S_ISLNK(sx.stx_mode))
return false; /* symlinks are never mount points */
r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags);
if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL))
@@ -231,16 +233,13 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
} else if (r < 0)
return r;
/* The parent can do name_to_handle_at() but the
* directory we are interested in can't? If so, it
* must be a mount point. */
/* The parent can do name_to_handle_at() but the directory we are interested in can't? If so, it must
* be a mount point. */
if (nosupp)
return 1;
/* If the file handle for the directory we are
* interested in and its parent are identical, we
* assume this is the root directory, which is a mount
* point. */
/* If the file handle for the directory we are interested in and its parent are identical, we assume
* this is the root directory, which is a mount point. */
if (h->handle_bytes == h_parent->handle_bytes &&
h->handle_type == h_parent->handle_type &&
@@ -263,23 +262,22 @@ fallback_fdinfo:
if (mount_id != mount_id_parent)
return 1;
/* Hmm, so, the mount ids are the same. This leaves one
* special case though for the root file system. For that,
* let's see if the parent directory has the same inode as we
* are interested in. Hence, let's also do fstat() checks now,
* too, but avoid the st_dev comparisons, since they aren't
* that useful on unionfs mounts. */
/* Hmm, so, the mount ids are the same. This leaves one special case though for the root file
* system. For that, let's see if the parent directory has the same inode as we are interested
* in. Hence, let's also do fstat() checks now, too, but avoid the st_dev comparisons, since they
* aren't that useful on unionfs mounts. */
check_st_dev = false;
fallback_fstat:
/* yay for fstatat() taking a different set of flags than the other
* _at() above */
/* yay for fstatat() taking a different set of flags than the other _at() above */
if (flags & AT_SYMLINK_FOLLOW)
flags &= ~AT_SYMLINK_FOLLOW;
else
flags |= AT_SYMLINK_NOFOLLOW;
if (fstatat(fd, filename, &a, flags) < 0)
return -errno;
if (S_ISLNK(a.st_mode)) /* Symlinks are never mount points */
return false;
if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
return -errno;