1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-19 22:50:17 +03:00

mount-tool: modernize umount and make sure it works for bind mounted files

So far, "systemd-umount" executed on a bind mounted file would assume it
is supposed to unmount a loopback mounted file system. Let's address
that by instead checking if the file is a mount.
This commit is contained in:
Lennart Poettering 2025-02-07 13:43:30 +01:00
parent 66b5e7dfaa
commit 61178346e6

View File

@ -1044,7 +1044,11 @@ static int action_umount(
int argc,
char **argv) {
int r, r2 = 0;
int r, ret = 0;
assert(bus);
assert(argv);
assert(argc > optind);
if (arg_transport != BUS_TRANSPORT_LOCAL) {
for (int i = optind; i < argc; i++) {
@ -1054,46 +1058,52 @@ static int action_umount(
if (r < 0)
return r;
r = stop_mounts(bus, p);
if (r < 0)
r2 = r;
RET_GATHER(ret, stop_mounts(bus, p));
}
return r2;
return ret;
}
for (int i = optind; i < argc; i++) {
_cleanup_free_ char *u = NULL, *p = NULL;
struct stat st;
u = fstab_node_to_udev_node(argv[i]);
if (!u)
return log_oom();
r = chase(u, NULL, 0, &p, NULL);
_cleanup_close_ int fd = -EBADF;
r = chase(u, /* root= */ NULL, 0, &p, &fd);
if (r < 0) {
r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]);
RET_GATHER(ret, log_error_errno(r, "Failed to make path %s absolute: %m", u));
continue;
}
if (stat(p, &st) < 0)
struct stat st;
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Can't stat %s (from %s): %m", p, argv[i]);
if (S_ISBLK(st.st_mode))
r = umount_by_device_node(bus, p);
else if (S_ISREG(st.st_mode))
r = umount_loop(bus, p);
else if (S_ISDIR(st.st_mode))
r = stop_mounts(bus, p);
r = is_mount_point_at(fd, /* filename= */ NULL, /* flags= */ 0);
fd = safe_close(fd); /* before continuing make sure the dir is not keeping anything busy */
if (r > 0)
RET_GATHER(ret, stop_mounts(bus, p));
else {
log_error("Invalid file type: %s (from %s)", p, argv[i]);
r = -EINVAL;
}
/* This can realistically fail on pre-5.8 kernels that do not tell us via statx() if
* something is a mount point, hence handle this gracefully, and go by type as we did
* in pre-v258 times. */
if (r < 0)
log_warning_errno(r, "Failed to determine if '%s' is a mount point, ignoring: %m", u);
if (r < 0)
r2 = r;
if (S_ISBLK(st.st_mode))
RET_GATHER(ret, umount_by_device_node(bus, p));
else if (S_ISREG(st.st_mode))
RET_GATHER(ret, umount_loop(bus, p));
else if (S_ISDIR(st.st_mode))
RET_GATHER(ret, stop_mounts(bus, p));
else
RET_GATHER(ret, log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid file type: %s (from %s)", p, argv[i]));
}
}
return r2;
return ret;
}
static int acquire_mount_type(sd_device *d) {