]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/umount.c
Merge pull request #7486 from keszybz/coverity-fixes
[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 "escape.h"
32 #include "fd-util.h"
33 #include "fstab-util.h"
34 #include "linux-3.13/dm-ioctl.h"
35 #include "list.h"
36 #include "mount-setup.h"
37 #include "path-util.h"
38 #include "string-util.h"
39 #include "udev-util.h"
40 #include "umount.h"
41 #include "mount-util.h"
42 #include "util.h"
43 #include "virt.h"
44
45 typedef struct MountPoint {
46 char *path;
47 char *options;
48 char *type;
49 dev_t devnum;
50 LIST_FIELDS(struct MountPoint, mount_point);
51 } MountPoint;
52
53 static void mount_point_free(MountPoint **head, MountPoint *m) {
54 assert(head);
55 assert(m);
56
57 LIST_REMOVE(mount_point, *head, m);
58
59 free(m->path);
60 free(m);
61 }
62
63 static void mount_points_list_free(MountPoint **head) {
64 assert(head);
65
66 while (*head)
67 mount_point_free(head, *head);
68 }
69
70 static int mount_points_list_get(MountPoint **head) {
71 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
72 unsigned int i;
73 int r;
74
75 assert(head);
76
77 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
78 if (!proc_self_mountinfo)
79 return -errno;
80
81 for (i = 1;; i++) {
82 _cleanup_free_ char *path = NULL, *options = NULL, *type = NULL;
83 char *p = NULL;
84 MountPoint *m;
85 int k;
86
87 k = fscanf(proc_self_mountinfo,
88 "%*s " /* (1) mount id */
89 "%*s " /* (2) parent id */
90 "%*s " /* (3) major:minor */
91 "%*s " /* (4) root */
92 "%ms " /* (5) mount point */
93 "%*s" /* (6) mount flags */
94 "%*[^-]" /* (7) optional fields */
95 "- " /* (8) separator */
96 "%ms " /* (9) file system type */
97 "%*s" /* (10) mount source */
98 "%ms" /* (11) mount options */
99 "%*[^\n]", /* some rubbish at the end */
100 &path, &type, &options);
101 if (k != 3) {
102 if (k == EOF)
103 break;
104
105 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
106 continue;
107 }
108
109 r = cunescape(path, UNESCAPE_RELAX, &p);
110 if (r < 0)
111 return r;
112
113 /* Ignore mount points we can't unmount because they
114 * are API or because we are keeping them open (like
115 * /dev/console). Also, ignore all mounts below API
116 * file systems, since they are likely virtual too,
117 * and hence not worth spending time on. Also, in
118 * unprivileged containers we might lack the rights to
119 * unmount these things, hence don't bother. */
120 if (mount_point_is_api(p) ||
121 mount_point_ignore(p) ||
122 path_startswith(p, "/dev") ||
123 path_startswith(p, "/sys") ||
124 path_startswith(p, "/proc")) {
125 free(p);
126 continue;
127 }
128
129 m = new0(MountPoint, 1);
130 if (!m) {
131 free(p);
132 return -ENOMEM;
133 }
134
135 m->path = p;
136 m->options = options;
137 options = NULL;
138 m->type = type;
139 type = NULL;
140
141 LIST_PREPEND(mount_point, *head, m);
142 }
143
144 return 0;
145 }
146
147 static int swap_list_get(MountPoint **head) {
148 _cleanup_fclose_ FILE *proc_swaps = NULL;
149 unsigned int i;
150 int r;
151
152 assert(head);
153
154 proc_swaps = fopen("/proc/swaps", "re");
155 if (!proc_swaps)
156 return (errno == ENOENT) ? 0 : -errno;
157
158 (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
159
160 for (i = 2;; i++) {
161 MountPoint *swap;
162 _cleanup_free_ char *dev = NULL, *d = NULL;
163 int k;
164
165 k = fscanf(proc_swaps,
166 "%ms " /* device/file */
167 "%*s " /* type of swap */
168 "%*s " /* swap size */
169 "%*s " /* used */
170 "%*s\n", /* priority */
171 &dev);
172
173 if (k != 1) {
174 if (k == EOF)
175 break;
176
177 log_warning("Failed to parse /proc/swaps:%u.", i);
178 continue;
179 }
180
181 if (endswith(dev, " (deleted)"))
182 continue;
183
184 r = cunescape(dev, UNESCAPE_RELAX, &d);
185 if (r < 0)
186 return r;
187
188 swap = new0(MountPoint, 1);
189 if (!swap)
190 return -ENOMEM;
191
192 free_and_replace(swap->path, d);
193 LIST_PREPEND(mount_point, *head, swap);
194 }
195
196 return 0;
197 }
198
199 static int loopback_list_get(MountPoint **head) {
200 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
201 struct udev_list_entry *item = NULL, *first = NULL;
202 _cleanup_udev_unref_ struct udev *udev = NULL;
203 int r;
204
205 assert(head);
206
207 udev = udev_new();
208 if (!udev)
209 return -ENOMEM;
210
211 e = udev_enumerate_new(udev);
212 if (!e)
213 return -ENOMEM;
214
215 r = udev_enumerate_add_match_subsystem(e, "block");
216 if (r < 0)
217 return r;
218
219 r = udev_enumerate_add_match_sysname(e, "loop*");
220 if (r < 0)
221 return r;
222
223 r = udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL);
224 if (r < 0)
225 return r;
226
227 r = udev_enumerate_scan_devices(e);
228 if (r < 0)
229 return r;
230
231 first = udev_enumerate_get_list_entry(e);
232 udev_list_entry_foreach(item, first) {
233 MountPoint *lb;
234 _cleanup_udev_device_unref_ struct udev_device *d;
235 char *loop;
236 const char *dn;
237
238 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
239 if (!d)
240 return -ENOMEM;
241
242 dn = udev_device_get_devnode(d);
243 if (!dn)
244 continue;
245
246 loop = strdup(dn);
247 if (!loop)
248 return -ENOMEM;
249
250 lb = new0(MountPoint, 1);
251 if (!lb) {
252 free(loop);
253 return -ENOMEM;
254 }
255
256 lb->path = loop;
257 LIST_PREPEND(mount_point, *head, lb);
258 }
259
260 return 0;
261 }
262
263 static int dm_list_get(MountPoint **head) {
264 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
265 struct udev_list_entry *item = NULL, *first = NULL;
266 _cleanup_udev_unref_ struct udev *udev = NULL;
267 int r;
268
269 assert(head);
270
271 udev = udev_new();
272 if (!udev)
273 return -ENOMEM;
274
275 e = udev_enumerate_new(udev);
276 if (!e)
277 return -ENOMEM;
278
279 r = udev_enumerate_add_match_subsystem(e, "block");
280 if (r < 0)
281 return r;
282
283 r = udev_enumerate_add_match_sysname(e, "dm-*");
284 if (r < 0)
285 return r;
286
287 r = udev_enumerate_scan_devices(e);
288 if (r < 0)
289 return r;
290
291 first = udev_enumerate_get_list_entry(e);
292 udev_list_entry_foreach(item, first) {
293 MountPoint *m;
294 _cleanup_udev_device_unref_ struct udev_device *d;
295 dev_t devnum;
296 char *node;
297 const char *dn;
298
299 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
300 if (!d)
301 return -ENOMEM;
302
303 devnum = udev_device_get_devnum(d);
304 dn = udev_device_get_devnode(d);
305 if (major(devnum) == 0 || !dn)
306 continue;
307
308 node = strdup(dn);
309 if (!node)
310 return -ENOMEM;
311
312 m = new(MountPoint, 1);
313 if (!m) {
314 free(node);
315 return -ENOMEM;
316 }
317
318 m->path = node;
319 m->devnum = devnum;
320 LIST_PREPEND(mount_point, *head, m);
321 }
322
323 return 0;
324 }
325
326 static int delete_loopback(const char *device) {
327 _cleanup_close_ int fd = -1;
328 int r;
329
330 fd = open(device, O_RDONLY|O_CLOEXEC);
331 if (fd < 0)
332 return errno == ENOENT ? 0 : -errno;
333
334 r = ioctl(fd, LOOP_CLR_FD, 0);
335 if (r >= 0)
336 return 1;
337
338 /* ENXIO: not bound, so no error */
339 if (errno == ENXIO)
340 return 0;
341
342 return -errno;
343 }
344
345 static int delete_dm(dev_t devnum) {
346
347 struct dm_ioctl dm = {
348 .version = {
349 DM_VERSION_MAJOR,
350 DM_VERSION_MINOR,
351 DM_VERSION_PATCHLEVEL
352 },
353 .data_size = sizeof(dm),
354 .dev = devnum,
355 };
356
357 _cleanup_close_ int fd = -1;
358
359 assert(major(devnum) != 0);
360
361 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
362 if (fd < 0)
363 return -errno;
364
365 if (ioctl(fd, DM_DEV_REMOVE, &dm) < 0)
366 return -errno;
367
368 return 0;
369 }
370
371 static bool nonunmountable_path(const char *path) {
372 return path_equal(path, "/")
373 #if ! HAVE_SPLIT_USR
374 || path_equal(path, "/usr")
375 #endif
376 || path_startswith(path, "/run/initramfs");
377 }
378
379 /* This includes remounting readonly, which changes the kernel mount options.
380 * Therefore the list passed to this function is invalidated, and should not be reused. */
381
382 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
383 MountPoint *m;
384 int n_failed = 0;
385
386 assert(head);
387
388 LIST_FOREACH(mount_point, m, *head) {
389 bool mount_is_readonly;
390
391 mount_is_readonly = fstab_test_yes_no_option(m->options, "ro\0rw\0");
392
393 /* If we are in a container, don't attempt to
394 read-only mount anything as that brings no real
395 benefits, but might confuse the host, as we remount
396 the superblock here, not the bind mount.
397 If the filesystem is a network fs, also skip the
398 remount. It brings no value (we cannot leave
399 a "dirty fs") and could hang if the network is down.
400 Note that umount2() is more careful and will not
401 hang because of the network being down. */
402 if (detect_container() <= 0 &&
403 !fstype_is_network(m->type) &&
404 !mount_is_readonly) {
405 _cleanup_free_ char *options = NULL;
406 /* MS_REMOUNT requires that the data parameter
407 * should be the same from the original mount
408 * except for the desired changes. Since we want
409 * to remount read-only, we should filter out
410 * rw (and ro too, because it confuses the kernel) */
411 (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
412
413 /* We always try to remount directories
414 * read-only first, before we go on and umount
415 * them.
416 *
417 * Mount points can be stacked. If a mount
418 * point is stacked below / or /usr, we
419 * cannot umount or remount it directly,
420 * since there is no way to refer to the
421 * underlying mount. There's nothing we can do
422 * about it for the general case, but we can
423 * do something about it if it is aliased
424 * somehwere else via a bind mount. If we
425 * explicitly remount the super block of that
426 * alias read-only we hence should be
427 * relatively safe regarding keeping dirty an fs
428 * we cannot otherwise see. */
429 log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
430 if (mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options) < 0) {
431 if (log_error)
432 log_notice_errno(errno, "Failed to remount '%s' read-only: %m", m->path);
433 if (nonunmountable_path(m->path))
434 n_failed++;
435 }
436 }
437
438 /* Skip / and /usr since we cannot unmount that
439 * anyway, since we are running from it. They have
440 * already been remounted ro. */
441 if (nonunmountable_path(m->path))
442 continue;
443
444 /* Trying to umount. Using MNT_FORCE causes some
445 * filesystems (e.g. FUSE and NFS and other network
446 * filesystems) to abort any pending requests and
447 * return -EIO rather than blocking indefinitely.
448 * If the filesysten is "busy", this may allow processes
449 * to die, thus making the filesystem less busy so
450 * the unmount might succeed (rather then return EBUSY).*/
451 log_info("Unmounting %s.", m->path);
452 if (umount2(m->path, MNT_FORCE) == 0) {
453 if (changed)
454 *changed = true;
455 } else {
456 if (log_error)
457 log_warning_errno(errno, "Could not unmount %s: %m", m->path);
458 n_failed++;
459 }
460 }
461
462 return n_failed;
463 }
464
465 static int swap_points_list_off(MountPoint **head, bool *changed) {
466 MountPoint *m, *n;
467 int n_failed = 0;
468
469 assert(head);
470
471 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
472 log_info("Deactivating swap %s.", m->path);
473 if (swapoff(m->path) == 0) {
474 if (changed)
475 *changed = true;
476
477 mount_point_free(head, m);
478 } else {
479 log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path);
480 n_failed++;
481 }
482 }
483
484 return n_failed;
485 }
486
487 static int loopback_points_list_detach(MountPoint **head, bool *changed) {
488 MountPoint *m, *n;
489 int n_failed = 0, k;
490 struct stat root_st;
491
492 assert(head);
493
494 k = lstat("/", &root_st);
495
496 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
497 int r;
498 struct stat loopback_st;
499
500 if (k >= 0 &&
501 major(root_st.st_dev) != 0 &&
502 lstat(m->path, &loopback_st) >= 0 &&
503 root_st.st_dev == loopback_st.st_rdev) {
504 n_failed++;
505 continue;
506 }
507
508 log_info("Detaching loopback %s.", m->path);
509 r = delete_loopback(m->path);
510 if (r >= 0) {
511 if (r > 0 && changed)
512 *changed = true;
513
514 mount_point_free(head, m);
515 } else {
516 log_warning_errno(errno, "Could not detach loopback %s: %m", m->path);
517 n_failed++;
518 }
519 }
520
521 return n_failed;
522 }
523
524 static int dm_points_list_detach(MountPoint **head, bool *changed) {
525 MountPoint *m, *n;
526 int n_failed = 0, r;
527 dev_t rootdev;
528
529 assert(head);
530
531 r = get_block_device("/", &rootdev);
532 if (r <= 0)
533 rootdev = 0;
534
535 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
536
537 if (major(rootdev) != 0)
538 if (rootdev == m->devnum) {
539 n_failed ++;
540 continue;
541 }
542
543 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
544 r = delete_dm(m->devnum);
545 if (r >= 0) {
546 if (changed)
547 *changed = true;
548
549 mount_point_free(head, m);
550 } else {
551 log_warning_errno(errno, "Could not detach DM %s: %m", m->path);
552 n_failed++;
553 }
554 }
555
556 return n_failed;
557 }
558
559 static int umount_all_once(bool *changed, bool log_error) {
560 int r;
561 LIST_HEAD(MountPoint, mp_list_head);
562
563 LIST_HEAD_INIT(mp_list_head);
564 r = mount_points_list_get(&mp_list_head);
565 if (r < 0)
566 goto end;
567
568 r = mount_points_list_umount(&mp_list_head, changed, log_error);
569
570 end:
571 mount_points_list_free(&mp_list_head);
572
573 return r;
574 }
575
576 int umount_all(bool *changed) {
577 bool umount_changed;
578 int r;
579
580 /* retry umount, until nothing can be umounted anymore */
581 do {
582 umount_changed = false;
583
584 umount_all_once(&umount_changed, false);
585 if (umount_changed)
586 *changed = true;
587 } while (umount_changed);
588
589 /* umount one more time with logging enabled */
590 r = umount_all_once(&umount_changed, true);
591 if (umount_changed)
592 *changed = true;
593
594 return r;
595 }
596
597 int swapoff_all(bool *changed) {
598 int r;
599 LIST_HEAD(MountPoint, swap_list_head);
600
601 LIST_HEAD_INIT(swap_list_head);
602
603 r = swap_list_get(&swap_list_head);
604 if (r < 0)
605 goto end;
606
607 r = swap_points_list_off(&swap_list_head, changed);
608
609 end:
610 mount_points_list_free(&swap_list_head);
611
612 return r;
613 }
614
615 int loopback_detach_all(bool *changed) {
616 int r;
617 LIST_HEAD(MountPoint, loopback_list_head);
618
619 LIST_HEAD_INIT(loopback_list_head);
620
621 r = loopback_list_get(&loopback_list_head);
622 if (r < 0)
623 goto end;
624
625 r = loopback_points_list_detach(&loopback_list_head, changed);
626
627 end:
628 mount_points_list_free(&loopback_list_head);
629
630 return r;
631 }
632
633 int dm_detach_all(bool *changed) {
634 int r;
635 LIST_HEAD(MountPoint, dm_list_head);
636
637 LIST_HEAD_INIT(dm_list_head);
638
639 r = dm_list_get(&dm_list_head);
640 if (r < 0)
641 goto end;
642
643 r = dm_points_list_detach(&dm_list_head, changed);
644
645 end:
646 mount_points_list_free(&dm_list_head);
647
648 return r;
649 }