]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shutdown/umount.c
Merge pull request #12252 from keszybz/libmount-dont-unescape
[thirdparty/systemd.git] / src / shutdown / umount.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright © 2010 ProFUSION embedded systems
4 ***/
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <linux/loop.h>
9 #include <string.h>
10 #include <sys/mount.h>
11 #include <sys/swap.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15
16 #include "sd-device.h"
17
18 #include "alloc-util.h"
19 #include "blockdev-util.h"
20 #include "def.h"
21 #include "device-util.h"
22 #include "escape.h"
23 #include "fd-util.h"
24 #include "fstab-util.h"
25 #include "libmount-util.h"
26 #include "linux-3.13/dm-ioctl.h"
27 #include "mount-setup.h"
28 #include "mount-util.h"
29 #include "mountpoint-util.h"
30 #include "path-util.h"
31 #include "process-util.h"
32 #include "signal-util.h"
33 #include "string-util.h"
34 #include "strv.h"
35 #include "umount.h"
36 #include "util.h"
37 #include "virt.h"
38
39 static void mount_point_free(MountPoint **head, MountPoint *m) {
40 assert(head);
41 assert(m);
42
43 LIST_REMOVE(mount_point, *head, m);
44
45 free(m->path);
46 free(m->remount_options);
47 free(m);
48 }
49
50 void mount_points_list_free(MountPoint **head) {
51 assert(head);
52
53 while (*head)
54 mount_point_free(head, *head);
55 }
56
57 int mount_points_list_get(const char *mountinfo, MountPoint **head) {
58 _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
59 _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
60 int r;
61
62 assert(head);
63
64 t = mnt_new_table();
65 i = mnt_new_iter(MNT_ITER_FORWARD);
66 if (!t || !i)
67 return log_oom();
68
69 r = mnt_table_parse_mtab(t, mountinfo);
70 if (r < 0)
71 return log_error_errno(r, "Failed to parse %s: %m", mountinfo);
72
73 for (;;) {
74 struct libmnt_fs *fs;
75 const char *path, *fstype;
76 _cleanup_free_ char *options = NULL;
77 unsigned long remount_flags = 0u;
78 _cleanup_free_ char *remount_options = NULL;
79 bool try_remount_ro;
80 _cleanup_free_ MountPoint *m = NULL;
81
82 r = mnt_table_next_fs(t, i, &fs);
83 if (r == 1)
84 break;
85 if (r < 0)
86 return log_error_errno(r, "Failed to get next entry from %s: %m", mountinfo);
87
88 path = mnt_fs_get_target(fs);
89 if (!path)
90 continue;
91
92 fstype = mnt_fs_get_fstype(fs);
93
94 /* Combine the generic VFS options with the FS-specific
95 * options. Duplicates are not a problem here, because the only
96 * options that should come up twice are typically ro/rw, which
97 * are turned into MS_RDONLY or the inversion of it.
98 *
99 * Even if there are duplicates later in mount_option_mangle()
100 * they shouldn't hurt anyways as they override each other.
101 */
102 if (!strextend_with_separator(&options, ",",
103 mnt_fs_get_vfs_options(fs),
104 NULL))
105 return log_oom();
106 if (!strextend_with_separator(&options, ",",
107 mnt_fs_get_fs_options(fs),
108 NULL))
109 return log_oom();
110
111 /* Ignore mount points we can't unmount because they
112 * are API or because we are keeping them open (like
113 * /dev/console). Also, ignore all mounts below API
114 * file systems, since they are likely virtual too,
115 * and hence not worth spending time on. Also, in
116 * unprivileged containers we might lack the rights to
117 * unmount these things, hence don't bother. */
118 if (mount_point_is_api(path) ||
119 mount_point_ignore(path) ||
120 PATH_STARTSWITH_SET(path, "/dev", "/sys", "/proc"))
121 continue;
122
123 /* If we are in a container, don't attempt to
124 * read-only mount anything as that brings no real
125 * benefits, but might confuse the host, as we remount
126 * the superblock here, not the bind mount.
127 *
128 * If the filesystem is a network fs, also skip the
129 * remount. It brings no value (we cannot leave
130 * a "dirty fs") and could hang if the network is down.
131 * Note that umount2() is more careful and will not
132 * hang because of the network being down. */
133 try_remount_ro = detect_container() <= 0 &&
134 !fstype_is_network(fstype) &&
135 !fstype_is_api_vfs(fstype) &&
136 !fstype_is_ro(fstype) &&
137 !fstab_test_yes_no_option(options, "ro\0rw\0");
138
139 if (try_remount_ro) {
140 /* mount(2) states that mount flags and options need to be exactly the same
141 * as they were when the filesystem was mounted, except for the desired
142 * changes. So we reconstruct both here and adjust them for the later
143 * remount call too. */
144
145 r = mnt_fs_get_propagation(fs, &remount_flags);
146 if (r < 0) {
147 log_warning_errno(r, "mnt_fs_get_propagation() failed for %s, ignoring: %m", path);
148 continue;
149 }
150
151 r = mount_option_mangle(options, remount_flags, &remount_flags, &remount_options);
152 if (r < 0) {
153 log_warning_errno(r, "mount_option_mangle failed for %s, ignoring: %m", path);
154 continue;
155 }
156
157 /* MS_BIND is special. If it is provided it will only make the mount-point
158 * read-only. If left out, the super block itself is remounted, which we want. */
159 remount_flags = (remount_flags|MS_REMOUNT|MS_RDONLY) & ~MS_BIND;
160 }
161
162 m = new0(MountPoint, 1);
163 if (!m)
164 return log_oom();
165
166 m->path = strdup(path);
167 if (!m->path)
168 return log_oom();
169
170 m->remount_options = TAKE_PTR(remount_options);
171 m->remount_flags = remount_flags;
172 m->try_remount_ro = try_remount_ro;
173
174 LIST_PREPEND(mount_point, *head, TAKE_PTR(m));
175 }
176
177 return 0;
178 }
179
180 int swap_list_get(const char *swaps, MountPoint **head) {
181 _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
182 _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
183 int r;
184
185 assert(head);
186
187 t = mnt_new_table();
188 i = mnt_new_iter(MNT_ITER_FORWARD);
189 if (!t || !i)
190 return log_oom();
191
192 r = mnt_table_parse_swaps(t, swaps);
193 if (r < 0)
194 return log_error_errno(r, "Failed to parse %s: %m", swaps);
195
196 for (;;) {
197 struct libmnt_fs *fs;
198 _cleanup_free_ MountPoint *swap = NULL;
199 const char *source;
200
201 r = mnt_table_next_fs(t, i, &fs);
202 if (r == 1)
203 break;
204 if (r < 0)
205 return log_error_errno(r, "Failed to get next entry from %s: %m", swaps);
206
207 source = mnt_fs_get_source(fs);
208 if (!source)
209 continue;
210
211 swap = new0(MountPoint, 1);
212 if (!swap)
213 return -ENOMEM;
214
215 swap->path = strdup(source);
216 if (!swap->path)
217 return -ENOMEM;
218
219 LIST_PREPEND(mount_point, *head, TAKE_PTR(swap));
220 }
221
222 return 0;
223 }
224
225 static int loopback_list_get(MountPoint **head) {
226 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
227 sd_device *d;
228 int r;
229
230 assert(head);
231
232 r = sd_device_enumerator_new(&e);
233 if (r < 0)
234 return r;
235
236 r = sd_device_enumerator_allow_uninitialized(e);
237 if (r < 0)
238 return r;
239
240 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
241 if (r < 0)
242 return r;
243
244 r = sd_device_enumerator_add_match_sysname(e, "loop*");
245 if (r < 0)
246 return r;
247
248 r = sd_device_enumerator_add_match_sysattr(e, "loop/backing_file", NULL, true);
249 if (r < 0)
250 return r;
251
252 FOREACH_DEVICE(e, d) {
253 _cleanup_free_ char *p = NULL;
254 const char *dn;
255 MountPoint *lb;
256
257 if (sd_device_get_devname(d, &dn) < 0)
258 continue;
259
260 p = strdup(dn);
261 if (!p)
262 return -ENOMEM;
263
264 lb = new(MountPoint, 1);
265 if (!lb)
266 return -ENOMEM;
267
268 *lb = (MountPoint) {
269 .path = TAKE_PTR(p),
270 };
271
272 LIST_PREPEND(mount_point, *head, lb);
273 }
274
275 return 0;
276 }
277
278 static int dm_list_get(MountPoint **head) {
279 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
280 sd_device *d;
281 int r;
282
283 assert(head);
284
285 r = sd_device_enumerator_new(&e);
286 if (r < 0)
287 return r;
288
289 r = sd_device_enumerator_allow_uninitialized(e);
290 if (r < 0)
291 return r;
292
293 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
294 if (r < 0)
295 return r;
296
297 r = sd_device_enumerator_add_match_sysname(e, "dm-*");
298 if (r < 0)
299 return r;
300
301 FOREACH_DEVICE(e, d) {
302 _cleanup_free_ char *p = NULL;
303 const char *dn;
304 MountPoint *m;
305 dev_t devnum;
306
307 if (sd_device_get_devnum(d, &devnum) < 0 ||
308 sd_device_get_devname(d, &dn) < 0)
309 continue;
310
311 p = strdup(dn);
312 if (!p)
313 return -ENOMEM;
314
315 m = new(MountPoint, 1);
316 if (!m)
317 return -ENOMEM;
318
319 *m = (MountPoint) {
320 .path = TAKE_PTR(p),
321 .devnum = devnum,
322 };
323
324 LIST_PREPEND(mount_point, *head, m);
325 }
326
327 return 0;
328 }
329
330 static int delete_loopback(const char *device) {
331 _cleanup_close_ int fd = -1;
332 int r;
333
334 assert(device);
335
336 fd = open(device, O_RDONLY|O_CLOEXEC);
337 if (fd < 0)
338 return errno == ENOENT ? 0 : -errno;
339
340 r = ioctl(fd, LOOP_CLR_FD, 0);
341 if (r >= 0)
342 return 1;
343
344 /* ENXIO: not bound, so no error */
345 if (errno == ENXIO)
346 return 0;
347
348 return -errno;
349 }
350
351 static int delete_dm(dev_t devnum) {
352
353 struct dm_ioctl dm = {
354 .version = {
355 DM_VERSION_MAJOR,
356 DM_VERSION_MINOR,
357 DM_VERSION_PATCHLEVEL
358 },
359 .data_size = sizeof(dm),
360 .dev = devnum,
361 };
362
363 _cleanup_close_ int fd = -1;
364
365 assert(major(devnum) != 0);
366
367 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
368 if (fd < 0)
369 return -errno;
370
371 if (ioctl(fd, DM_DEV_REMOVE, &dm) < 0)
372 return -errno;
373
374 return 0;
375 }
376
377 static bool nonunmountable_path(const char *path) {
378 return path_equal(path, "/")
379 #if ! HAVE_SPLIT_USR
380 || path_equal(path, "/usr")
381 #endif
382 || path_startswith(path, "/run/initramfs");
383 }
384
385 static int remount_with_timeout(MountPoint *m, int umount_log_level) {
386 pid_t pid;
387 int r;
388
389 BLOCK_SIGNALS(SIGCHLD);
390
391 assert(m);
392
393 /* Due to the possiblity of a remount operation hanging, we
394 * fork a child process and set a timeout. If the timeout
395 * lapses, the assumption is that that particular remount
396 * failed. */
397 r = safe_fork("(sd-remount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
398 if (r < 0)
399 return r;
400 if (r == 0) {
401 log_info("Remounting '%s' read-only in with options '%s'.", m->path, m->remount_options);
402
403 /* Start the mount operation here in the child */
404 r = mount(NULL, m->path, NULL, m->remount_flags, m->remount_options);
405 if (r < 0)
406 log_full_errno(umount_log_level, errno, "Failed to remount '%s' read-only: %m", m->path);
407
408 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
409 }
410
411 r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC);
412 if (r == -ETIMEDOUT) {
413 log_error_errno(r, "Remounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid);
414 (void) kill(pid, SIGKILL);
415 } else if (r == -EPROTO)
416 log_debug_errno(r, "Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid);
417 else if (r < 0)
418 log_error_errno(r, "Remounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid);
419
420 return r;
421 }
422
423 static int umount_with_timeout(MountPoint *m, int umount_log_level) {
424 pid_t pid;
425 int r;
426
427 BLOCK_SIGNALS(SIGCHLD);
428
429 assert(m);
430
431 /* Due to the possiblity of a umount operation hanging, we
432 * fork a child process and set a timeout. If the timeout
433 * lapses, the assumption is that that particular umount
434 * failed. */
435 r = safe_fork("(sd-umount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
436 if (r < 0)
437 return r;
438 if (r == 0) {
439 log_info("Unmounting '%s'.", m->path);
440
441 /* Start the mount operation here in the child Using MNT_FORCE
442 * causes some filesystems (e.g. FUSE and NFS and other network
443 * filesystems) to abort any pending requests and return -EIO
444 * rather than blocking indefinitely. If the filesysten is
445 * "busy", this may allow processes to die, thus making the
446 * filesystem less busy so the unmount might succeed (rather
447 * then return EBUSY).*/
448 r = umount2(m->path, MNT_FORCE);
449 if (r < 0)
450 log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path);
451
452 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
453 }
454
455 r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC);
456 if (r == -ETIMEDOUT) {
457 log_error_errno(r, "Unmounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid);
458 (void) kill(pid, SIGKILL);
459 } else if (r == -EPROTO)
460 log_debug_errno(r, "Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid);
461 else if (r < 0)
462 log_error_errno(r, "Unmounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid);
463
464 return r;
465 }
466
467 /* This includes remounting readonly, which changes the kernel mount options.
468 * Therefore the list passed to this function is invalidated, and should not be reused. */
469 static int mount_points_list_umount(MountPoint **head, bool *changed, int umount_log_level) {
470 MountPoint *m;
471 int n_failed = 0;
472
473 assert(head);
474 assert(changed);
475
476 LIST_FOREACH(mount_point, m, *head) {
477 if (m->try_remount_ro) {
478 /* We always try to remount directories
479 * read-only first, before we go on and umount
480 * them.
481 *
482 * Mount points can be stacked. If a mount
483 * point is stacked below / or /usr, we
484 * cannot umount or remount it directly,
485 * since there is no way to refer to the
486 * underlying mount. There's nothing we can do
487 * about it for the general case, but we can
488 * do something about it if it is aliased
489 * somehwere else via a bind mount. If we
490 * explicitly remount the super block of that
491 * alias read-only we hence should be
492 * relatively safe regarding keeping a dirty fs
493 * we cannot otherwise see.
494 *
495 * Since the remount can hang in the instance of
496 * remote filesystems, we remount asynchronously
497 * and skip the subsequent umount if it fails. */
498 if (remount_with_timeout(m, umount_log_level) < 0) {
499 /* Remount failed, but try unmounting anyway,
500 * unless this is a mount point we want to skip. */
501 if (nonunmountable_path(m->path)) {
502 n_failed++;
503 continue;
504 }
505 }
506 }
507
508 /* Skip / and /usr since we cannot unmount that
509 * anyway, since we are running from it. They have
510 * already been remounted ro. */
511 if (nonunmountable_path(m->path))
512 continue;
513
514 /* Trying to umount */
515 if (umount_with_timeout(m, umount_log_level) < 0)
516 n_failed++;
517 else
518 *changed = true;
519 }
520
521 return n_failed;
522 }
523
524 static int swap_points_list_off(MountPoint **head, bool *changed) {
525 MountPoint *m, *n;
526 int n_failed = 0;
527
528 assert(head);
529 assert(changed);
530
531 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
532 log_info("Deactivating swap %s.", m->path);
533 if (swapoff(m->path) == 0) {
534 *changed = true;
535 mount_point_free(head, m);
536 } else {
537 log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path);
538 n_failed++;
539 }
540 }
541
542 return n_failed;
543 }
544
545 static int loopback_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
546 MountPoint *m, *n;
547 int n_failed = 0, k;
548 struct stat root_st;
549
550 assert(head);
551 assert(changed);
552
553 k = lstat("/", &root_st);
554
555 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
556 int r;
557 struct stat loopback_st;
558
559 if (k >= 0 &&
560 major(root_st.st_dev) != 0 &&
561 lstat(m->path, &loopback_st) >= 0 &&
562 root_st.st_dev == loopback_st.st_rdev) {
563 n_failed++;
564 continue;
565 }
566
567 log_info("Detaching loopback %s.", m->path);
568 r = delete_loopback(m->path);
569 if (r >= 0) {
570 if (r > 0)
571 *changed = true;
572
573 mount_point_free(head, m);
574 } else {
575 log_full_errno(umount_log_level, errno, "Could not detach loopback %s: %m", m->path);
576 n_failed++;
577 }
578 }
579
580 return n_failed;
581 }
582
583 static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
584 MountPoint *m, *n;
585 int n_failed = 0, r;
586 dev_t rootdev;
587
588 assert(head);
589 assert(changed);
590
591 r = get_block_device("/", &rootdev);
592 if (r <= 0)
593 rootdev = 0;
594
595 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
596
597 if (major(rootdev) != 0 && rootdev == m->devnum) {
598 n_failed ++;
599 continue;
600 }
601
602 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
603 r = delete_dm(m->devnum);
604 if (r >= 0) {
605 *changed = true;
606 mount_point_free(head, m);
607 } else {
608 log_full_errno(umount_log_level, errno, "Could not detach DM %s: %m", m->path);
609 n_failed++;
610 }
611 }
612
613 return n_failed;
614 }
615
616 static int umount_all_once(bool *changed, int umount_log_level) {
617 int r;
618 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
619
620 assert(changed);
621
622 LIST_HEAD_INIT(mp_list_head);
623 r = mount_points_list_get(NULL, &mp_list_head);
624 if (r < 0)
625 return r;
626
627 return mount_points_list_umount(&mp_list_head, changed, umount_log_level);
628 }
629
630 int umount_all(bool *changed, int umount_log_level) {
631 bool umount_changed;
632 int r;
633
634 assert(changed);
635
636 /* Retry umount, until nothing can be umounted anymore. Mounts are
637 * processed in order, newest first. The retries are needed when
638 * an old mount has been moved, to a path inside a newer mount. */
639 do {
640 umount_changed = false;
641
642 r = umount_all_once(&umount_changed, umount_log_level);
643 if (umount_changed)
644 *changed = true;
645 } while (umount_changed);
646
647 return r;
648 }
649
650 int swapoff_all(bool *changed) {
651 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, swap_list_head);
652 int r;
653
654 assert(changed);
655
656 LIST_HEAD_INIT(swap_list_head);
657
658 r = swap_list_get(NULL, &swap_list_head);
659 if (r < 0)
660 return r;
661
662 return swap_points_list_off(&swap_list_head, changed);
663 }
664
665 int loopback_detach_all(bool *changed, int umount_log_level) {
666 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, loopback_list_head);
667 int r;
668
669 assert(changed);
670
671 LIST_HEAD_INIT(loopback_list_head);
672
673 r = loopback_list_get(&loopback_list_head);
674 if (r < 0)
675 return r;
676
677 return loopback_points_list_detach(&loopback_list_head, changed, umount_log_level);
678 }
679
680 int dm_detach_all(bool *changed, int umount_log_level) {
681 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, dm_list_head);
682 int r;
683
684 assert(changed);
685
686 LIST_HEAD_INIT(dm_list_head);
687
688 r = dm_list_get(&dm_list_head);
689 if (r < 0)
690 return r;
691
692 return dm_points_list_detach(&dm_list_head, changed, umount_log_level);
693 }