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