]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/machine-image.c
Merge pull request #7395 from poettering/nametohandleat-loop
[thirdparty/systemd.git] / src / shared / machine-image.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
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 <dirent.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/file.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <linux/fs.h>
31
32 #include "alloc-util.h"
33 #include "btrfs-util.h"
34 #include "chattr-util.h"
35 #include "copy.h"
36 #include "dirent-util.h"
37 #include "dissect-image.h"
38 #include "env-util.h"
39 #include "fd-util.h"
40 #include "fileio.h"
41 #include "fs-util.h"
42 #include "hashmap.h"
43 #include "hostname-util.h"
44 #include "id128-util.h"
45 #include "lockfile-util.h"
46 #include "log.h"
47 #include "loop-util.h"
48 #include "machine-image.h"
49 #include "macro.h"
50 #include "mkdir.h"
51 #include "path-util.h"
52 #include "rm-rf.h"
53 #include "string-table.h"
54 #include "string-util.h"
55 #include "strv.h"
56 #include "time-util.h"
57 #include "utf8.h"
58 #include "util.h"
59 #include "xattr-util.h"
60
61 static const char image_search_path[] =
62 "/var/lib/machines\0"
63 "/var/lib/container\0" /* legacy */
64 "/usr/local/lib/machines\0"
65 "/usr/lib/machines\0";
66
67 Image *image_unref(Image *i) {
68 if (!i)
69 return NULL;
70
71 free(i->name);
72 free(i->path);
73
74 free(i->hostname);
75 strv_free(i->machine_info);
76 strv_free(i->os_release);
77
78 return mfree(i);
79 }
80
81 static char **image_settings_path(Image *image) {
82 _cleanup_strv_free_ char **l = NULL;
83 char **ret;
84 const char *fn, *s;
85 unsigned i = 0;
86
87 assert(image);
88
89 l = new0(char*, 4);
90 if (!l)
91 return NULL;
92
93 fn = strjoina(image->name, ".nspawn");
94
95 FOREACH_STRING(s, "/etc/systemd/nspawn/", "/run/systemd/nspawn/") {
96 l[i] = strappend(s, fn);
97 if (!l[i])
98 return NULL;
99
100 i++;
101 }
102
103 l[i] = file_in_same_dir(image->path, fn);
104 if (!l[i])
105 return NULL;
106
107 ret = l;
108 l = NULL;
109
110 return ret;
111 }
112
113 static char *image_roothash_path(Image *image) {
114 const char *fn;
115
116 assert(image);
117
118 fn = strjoina(image->name, ".roothash");
119
120 return file_in_same_dir(image->path, fn);
121 }
122
123 static int image_new(
124 ImageType t,
125 const char *pretty,
126 const char *path,
127 const char *filename,
128 bool read_only,
129 usec_t crtime,
130 usec_t mtime,
131 Image **ret) {
132
133 _cleanup_(image_unrefp) Image *i = NULL;
134
135 assert(t >= 0);
136 assert(t < _IMAGE_TYPE_MAX);
137 assert(pretty);
138 assert(filename);
139 assert(ret);
140
141 i = new0(Image, 1);
142 if (!i)
143 return -ENOMEM;
144
145 i->type = t;
146 i->read_only = read_only;
147 i->crtime = crtime;
148 i->mtime = mtime;
149 i->usage = i->usage_exclusive = (uint64_t) -1;
150 i->limit = i->limit_exclusive = (uint64_t) -1;
151
152 i->name = strdup(pretty);
153 if (!i->name)
154 return -ENOMEM;
155
156 if (path)
157 i->path = strjoin(path, "/", filename);
158 else
159 i->path = strdup(filename);
160
161 if (!i->path)
162 return -ENOMEM;
163
164 path_kill_slashes(i->path);
165
166 *ret = i;
167 i = NULL;
168
169 return 0;
170 }
171
172 static int image_make(
173 const char *pretty,
174 int dfd,
175 const char *path,
176 const char *filename,
177 Image **ret) {
178
179 struct stat st;
180 bool read_only;
181 int r;
182
183 assert(filename);
184
185 /* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block
186 * devices into /var/lib/machines/, and treat them normally. */
187
188 if (fstatat(dfd, filename, &st, 0) < 0)
189 return -errno;
190
191 read_only =
192 (path && path_startswith(path, "/usr")) ||
193 (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS);
194
195 if (S_ISDIR(st.st_mode)) {
196 _cleanup_close_ int fd = -1;
197 unsigned file_attr = 0;
198
199 if (!ret)
200 return 1;
201
202 if (!pretty)
203 pretty = filename;
204
205 fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
206 if (fd < 0)
207 return -errno;
208
209 /* btrfs subvolumes have inode 256 */
210 if (st.st_ino == 256) {
211
212 r = btrfs_is_filesystem(fd);
213 if (r < 0)
214 return r;
215 if (r) {
216 BtrfsSubvolInfo info;
217
218 /* It's a btrfs subvolume */
219
220 r = btrfs_subvol_get_info_fd(fd, 0, &info);
221 if (r < 0)
222 return r;
223
224 r = image_new(IMAGE_SUBVOLUME,
225 pretty,
226 path,
227 filename,
228 info.read_only || read_only,
229 info.otime,
230 0,
231 ret);
232 if (r < 0)
233 return r;
234
235 if (btrfs_quota_scan_ongoing(fd) == 0) {
236 BtrfsQuotaInfo quota;
237
238 r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
239 if (r >= 0) {
240 (*ret)->usage = quota.referenced;
241 (*ret)->usage_exclusive = quota.exclusive;
242
243 (*ret)->limit = quota.referenced_max;
244 (*ret)->limit_exclusive = quota.exclusive_max;
245 }
246 }
247
248 return 1;
249 }
250 }
251
252 /* If the IMMUTABLE bit is set, we consider the
253 * directory read-only. Since the ioctl is not
254 * supported everywhere we ignore failures. */
255 (void) read_attr_fd(fd, &file_attr);
256
257 /* It's just a normal directory. */
258 r = image_new(IMAGE_DIRECTORY,
259 pretty,
260 path,
261 filename,
262 read_only || (file_attr & FS_IMMUTABLE_FL),
263 0,
264 0,
265 ret);
266 if (r < 0)
267 return r;
268
269 return 1;
270
271 } else if (S_ISREG(st.st_mode) && endswith(filename, ".raw")) {
272 usec_t crtime = 0;
273
274 /* It's a RAW disk image */
275
276 if (!ret)
277 return 1;
278
279 fd_getcrtime_at(dfd, filename, &crtime, 0);
280
281 if (!pretty)
282 pretty = strndupa(filename, strlen(filename) - 4);
283
284 r = image_new(IMAGE_RAW,
285 pretty,
286 path,
287 filename,
288 !(st.st_mode & 0222) || read_only,
289 crtime,
290 timespec_load(&st.st_mtim),
291 ret);
292 if (r < 0)
293 return r;
294
295 (*ret)->usage = (*ret)->usage_exclusive = st.st_blocks * 512;
296 (*ret)->limit = (*ret)->limit_exclusive = st.st_size;
297
298 return 1;
299
300 } else if (S_ISBLK(st.st_mode)) {
301 _cleanup_close_ int block_fd = -1;
302 uint64_t size = UINT64_MAX;
303
304 /* A block device */
305
306 if (!ret)
307 return 1;
308
309 if (!pretty)
310 pretty = filename;
311
312 block_fd = openat(dfd, filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
313 if (block_fd < 0)
314 log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path, filename);
315 else {
316 if (fstat(block_fd, &st) < 0)
317 return -errno;
318 if (!S_ISBLK(st.st_mode)) /* Verify that what we opened is actually what we think it is */
319 return -ENOTTY;
320
321 if (!read_only) {
322 int state = 0;
323
324 if (ioctl(block_fd, BLKROGET, &state) < 0)
325 log_debug_errno(errno, "Failed to issue BLKROGET on device %s/%s, ignoring: %m", path, filename);
326 else if (state)
327 read_only = true;
328 }
329
330 if (ioctl(block_fd, BLKGETSIZE64, &size) < 0)
331 log_debug_errno(errno, "Failed to issue BLKFLSBUF on device %s/%s, ignoring: %m", path, filename);
332
333 block_fd = safe_close(block_fd);
334 }
335
336 r = image_new(IMAGE_BLOCK,
337 pretty,
338 path,
339 filename,
340 !(st.st_mode & 0222) || read_only,
341 0,
342 0,
343 ret);
344 if (r < 0)
345 return r;
346
347 if (size != 0 && size != UINT64_MAX)
348 (*ret)->usage = (*ret)->usage_exclusive = (*ret)->limit = (*ret)->limit_exclusive = size;
349
350 return 1;
351 }
352
353 return 0;
354 }
355
356 int image_find(const char *name, Image **ret) {
357 const char *path;
358 int r;
359
360 assert(name);
361
362 /* There are no images with invalid names */
363 if (!image_name_is_valid(name))
364 return 0;
365
366 NULSTR_FOREACH(path, image_search_path) {
367 _cleanup_closedir_ DIR *d = NULL;
368
369 d = opendir(path);
370 if (!d) {
371 if (errno == ENOENT)
372 continue;
373
374 return -errno;
375 }
376
377 r = image_make(NULL, dirfd(d), path, name, ret);
378 if (IN_SET(r, 0, -ENOENT)) {
379 _cleanup_free_ char *raw = NULL;
380
381 raw = strappend(name, ".raw");
382 if (!raw)
383 return -ENOMEM;
384
385 r = image_make(NULL, dirfd(d), path, raw, ret);
386 if (IN_SET(r, 0, -ENOENT))
387 continue;
388 }
389 if (r < 0)
390 return r;
391
392 return 1;
393 }
394
395 if (streq(name, ".host"))
396 return image_make(".host", AT_FDCWD, NULL, "/", ret);
397
398 return 0;
399 };
400
401 int image_discover(Hashmap *h) {
402 const char *path;
403 int r;
404
405 assert(h);
406
407 NULSTR_FOREACH(path, image_search_path) {
408 _cleanup_closedir_ DIR *d = NULL;
409 struct dirent *de;
410
411 d = opendir(path);
412 if (!d) {
413 if (errno == ENOENT)
414 continue;
415
416 return -errno;
417 }
418
419 FOREACH_DIRENT_ALL(de, d, return -errno) {
420 _cleanup_(image_unrefp) Image *image = NULL;
421
422 if (!image_name_is_valid(de->d_name))
423 continue;
424
425 if (hashmap_contains(h, de->d_name))
426 continue;
427
428 r = image_make(NULL, dirfd(d), path, de->d_name, &image);
429 if (IN_SET(r, 0, -ENOENT))
430 continue;
431 if (r < 0)
432 return r;
433
434 r = hashmap_put(h, image->name, image);
435 if (r < 0)
436 return r;
437
438 image = NULL;
439 }
440 }
441
442 if (!hashmap_contains(h, ".host")) {
443 _cleanup_(image_unrefp) Image *image = NULL;
444
445 r = image_make(".host", AT_FDCWD, NULL, "/", &image);
446 if (r < 0)
447 return r;
448
449 r = hashmap_put(h, image->name, image);
450 if (r < 0)
451 return r;
452
453 image = NULL;
454
455 }
456
457 return 0;
458 }
459
460 void image_hashmap_free(Hashmap *map) {
461 Image *i;
462
463 while ((i = hashmap_steal_first(map)))
464 image_unref(i);
465
466 hashmap_free(map);
467 }
468
469 int image_remove(Image *i) {
470 _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
471 _cleanup_strv_free_ char **settings = NULL;
472 _cleanup_free_ char *roothash = NULL;
473 char **j;
474 int r;
475
476 assert(i);
477
478 if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
479 return -EROFS;
480
481 settings = image_settings_path(i);
482 if (!settings)
483 return -ENOMEM;
484
485 roothash = image_roothash_path(i);
486 if (!roothash)
487 return -ENOMEM;
488
489 /* Make sure we don't interfere with a running nspawn */
490 r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
491 if (r < 0)
492 return r;
493
494 switch (i->type) {
495
496 case IMAGE_SUBVOLUME:
497
498 /* Let's unlink first, maybe it is a symlink? If that works we are happy. Otherwise, let's get out the
499 * big guns */
500 if (unlink(i->path) < 0) {
501 r = btrfs_subvol_remove(i->path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
502 if (r < 0)
503 return r;
504 }
505
506 break;
507
508 case IMAGE_DIRECTORY:
509 /* Allow deletion of read-only directories */
510 (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL);
511 r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
512 if (r < 0)
513 return r;
514
515 break;
516
517 case IMAGE_BLOCK:
518
519 /* If this is inside of /dev, then it's a real block device, hence let's not touch the device node
520 * itself (but let's remove the stuff stored alongside it). If it's anywhere else, let's try to unlink
521 * the thing (it's most likely a symlink after all). */
522
523 if (path_startswith(i->path, "/dev"))
524 break;
525
526 _fallthrough_;
527 case IMAGE_RAW:
528 if (unlink(i->path) < 0)
529 return -errno;
530 break;
531
532 default:
533 return -EOPNOTSUPP;
534 }
535
536 STRV_FOREACH(j, settings) {
537 if (unlink(*j) < 0 && errno != ENOENT)
538 log_debug_errno(errno, "Failed to unlink %s, ignoring: %m", *j);
539 }
540
541 if (unlink(roothash) < 0 && errno != ENOENT)
542 log_debug_errno(errno, "Failed to unlink %s, ignoring: %m", roothash);
543
544 return 0;
545 }
546
547 static int rename_auxiliary_file(const char *path, const char *new_name, const char *suffix) {
548 _cleanup_free_ char *rs = NULL;
549 const char *fn;
550
551 fn = strjoina(new_name, suffix);
552
553 rs = file_in_same_dir(path, fn);
554 if (!rs)
555 return -ENOMEM;
556
557 return rename_noreplace(AT_FDCWD, path, AT_FDCWD, rs);
558 }
559
560 int image_rename(Image *i, const char *new_name) {
561 _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT;
562 _cleanup_free_ char *new_path = NULL, *nn = NULL, *roothash = NULL;
563 _cleanup_strv_free_ char **settings = NULL;
564 unsigned file_attr = 0;
565 char **j;
566 int r;
567
568 assert(i);
569
570 if (!image_name_is_valid(new_name))
571 return -EINVAL;
572
573 if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
574 return -EROFS;
575
576 settings = image_settings_path(i);
577 if (!settings)
578 return -ENOMEM;
579
580 roothash = image_roothash_path(i);
581 if (!roothash)
582 return -ENOMEM;
583
584 /* Make sure we don't interfere with a running nspawn */
585 r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
586 if (r < 0)
587 return r;
588
589 /* Make sure nobody takes the new name, between the time we
590 * checked it is currently unused in all search paths, and the
591 * time we take possession of it */
592 r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock);
593 if (r < 0)
594 return r;
595
596 r = image_find(new_name, NULL);
597 if (r < 0)
598 return r;
599 if (r > 0)
600 return -EEXIST;
601
602 switch (i->type) {
603
604 case IMAGE_DIRECTORY:
605 /* Turn of the immutable bit while we rename the image, so that we can rename it */
606 (void) read_attr_path(i->path, &file_attr);
607
608 if (file_attr & FS_IMMUTABLE_FL)
609 (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL);
610
611 _fallthrough_;
612 case IMAGE_SUBVOLUME:
613 new_path = file_in_same_dir(i->path, new_name);
614 break;
615
616 case IMAGE_BLOCK:
617
618 /* Refuse renaming raw block devices in /dev, the names are picked by udev after all. */
619 if (path_startswith(i->path, "/dev"))
620 return -EROFS;
621
622 new_path = file_in_same_dir(i->path, new_name);
623 break;
624
625 case IMAGE_RAW: {
626 const char *fn;
627
628 fn = strjoina(new_name, ".raw");
629 new_path = file_in_same_dir(i->path, fn);
630 break;
631 }
632
633 default:
634 return -EOPNOTSUPP;
635 }
636
637 if (!new_path)
638 return -ENOMEM;
639
640 nn = strdup(new_name);
641 if (!nn)
642 return -ENOMEM;
643
644 r = rename_noreplace(AT_FDCWD, i->path, AT_FDCWD, new_path);
645 if (r < 0)
646 return r;
647
648 /* Restore the immutable bit, if it was set before */
649 if (file_attr & FS_IMMUTABLE_FL)
650 (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL);
651
652 free(i->path);
653 i->path = new_path;
654 new_path = NULL;
655
656 free(i->name);
657 i->name = nn;
658 nn = NULL;
659
660 STRV_FOREACH(j, settings) {
661 r = rename_auxiliary_file(*j, new_name, ".nspawn");
662 if (r < 0 && r != -ENOENT)
663 log_debug_errno(r, "Failed to rename settings file %s, ignoring: %m", *j);
664 }
665
666 r = rename_auxiliary_file(roothash, new_name, ".roothash");
667 if (r < 0 && r != -ENOENT)
668 log_debug_errno(r, "Failed to rename roothash file %s, ignoring: %m", roothash);
669
670 return 0;
671 }
672
673 static int clone_auxiliary_file(const char *path, const char *new_name, const char *suffix) {
674 _cleanup_free_ char *rs = NULL;
675 const char *fn;
676
677 fn = strjoina(new_name, suffix);
678
679 rs = file_in_same_dir(path, fn);
680 if (!rs)
681 return -ENOMEM;
682
683 return copy_file_atomic(path, rs, 0664, 0, COPY_REFLINK);
684 }
685
686 int image_clone(Image *i, const char *new_name, bool read_only) {
687 _cleanup_release_lock_file_ LockFile name_lock = LOCK_FILE_INIT;
688 _cleanup_strv_free_ char **settings = NULL;
689 _cleanup_free_ char *roothash = NULL;
690 const char *new_path;
691 char **j;
692 int r;
693
694 assert(i);
695
696 if (!image_name_is_valid(new_name))
697 return -EINVAL;
698
699 settings = image_settings_path(i);
700 if (!settings)
701 return -ENOMEM;
702
703 roothash = image_roothash_path(i);
704 if (!roothash)
705 return -ENOMEM;
706
707 /* Make sure nobody takes the new name, between the time we
708 * checked it is currently unused in all search paths, and the
709 * time we take possession of it */
710 r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock);
711 if (r < 0)
712 return r;
713
714 r = image_find(new_name, NULL);
715 if (r < 0)
716 return r;
717 if (r > 0)
718 return -EEXIST;
719
720 switch (i->type) {
721
722 case IMAGE_SUBVOLUME:
723 case IMAGE_DIRECTORY:
724 /* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain
725 * directory. */
726
727 new_path = strjoina("/var/lib/machines/", new_name);
728
729 r = btrfs_subvol_snapshot(i->path, new_path,
730 (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
731 BTRFS_SNAPSHOT_FALLBACK_COPY |
732 BTRFS_SNAPSHOT_FALLBACK_DIRECTORY |
733 BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE |
734 BTRFS_SNAPSHOT_RECURSIVE |
735 BTRFS_SNAPSHOT_QUOTA);
736 if (r >= 0)
737 /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */
738 (void) btrfs_subvol_auto_qgroup(new_path, 0, true);
739
740 break;
741
742 case IMAGE_RAW:
743 new_path = strjoina("/var/lib/machines/", new_name, ".raw");
744
745 r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, FS_NOCOW_FL, COPY_REFLINK);
746 break;
747
748 case IMAGE_BLOCK:
749 default:
750 return -EOPNOTSUPP;
751 }
752
753 if (r < 0)
754 return r;
755
756 STRV_FOREACH(j, settings) {
757 r = clone_auxiliary_file(*j, new_name, ".nspawn");
758 if (r < 0 && r != -ENOENT)
759 log_debug_errno(r, "Failed to clone settings %s, ignoring: %m", *j);
760 }
761
762 r = clone_auxiliary_file(roothash, new_name, ".roothash");
763 if (r < 0 && r != -ENOENT)
764 log_debug_errno(r, "Failed to clone root hash file %s, ignoring: %m", roothash);
765
766 return 0;
767 }
768
769 int image_read_only(Image *i, bool b) {
770 _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
771 int r;
772
773 assert(i);
774
775 if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
776 return -EROFS;
777
778 /* Make sure we don't interfere with a running nspawn */
779 r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
780 if (r < 0)
781 return r;
782
783 switch (i->type) {
784
785 case IMAGE_SUBVOLUME:
786
787 /* Note that we set the flag only on the top-level
788 * subvolume of the image. */
789
790 r = btrfs_subvol_set_read_only(i->path, b);
791 if (r < 0)
792 return r;
793
794 break;
795
796 case IMAGE_DIRECTORY:
797 /* For simple directory trees we cannot use the access
798 mode of the top-level directory, since it has an
799 effect on the container itself. However, we can
800 use the "immutable" flag, to at least make the
801 top-level directory read-only. It's not as good as
802 a read-only subvolume, but at least something, and
803 we can read the value back. */
804
805 r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL);
806 if (r < 0)
807 return r;
808
809 break;
810
811 case IMAGE_RAW: {
812 struct stat st;
813
814 if (stat(i->path, &st) < 0)
815 return -errno;
816
817 if (chmod(i->path, (st.st_mode & 0444) | (b ? 0000 : 0200)) < 0)
818 return -errno;
819
820 /* If the images is now read-only, it's a good time to
821 * defrag it, given that no write patterns will
822 * fragment it again. */
823 if (b)
824 (void) btrfs_defrag(i->path);
825 break;
826 }
827
828 case IMAGE_BLOCK: {
829 _cleanup_close_ int fd = -1;
830 struct stat st;
831 int state = b;
832
833 fd = open(i->path, O_CLOEXEC|O_RDONLY|O_NONBLOCK|O_NOCTTY);
834 if (fd < 0)
835 return -errno;
836
837 if (fstat(fd, &st) < 0)
838 return -errno;
839 if (!S_ISBLK(st.st_mode))
840 return -ENOTTY;
841
842 if (ioctl(fd, BLKROSET, &state) < 0)
843 return -errno;
844
845 break;
846 }
847
848 default:
849 return -EOPNOTSUPP;
850 }
851
852 return 0;
853 }
854
855 int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local) {
856 _cleanup_free_ char *p = NULL;
857 LockFile t = LOCK_FILE_INIT;
858 struct stat st;
859 int r;
860
861 assert(path);
862 assert(global);
863 assert(local);
864
865 /* Locks an image path. This actually creates two locks: one
866 * "local" one, next to the image path itself, which might be
867 * shared via NFS. And another "global" one, in /run, that
868 * uses the device/inode number. This has the benefit that we
869 * can even lock a tree that is a mount point, correctly. */
870
871 if (!path_is_absolute(path))
872 return -EINVAL;
873
874 if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) {
875 *local = *global = (LockFile) LOCK_FILE_INIT;
876 return 0;
877 }
878
879 if (path_equal(path, "/"))
880 return -EBUSY;
881
882 if (stat(path, &st) >= 0) {
883 if (S_ISBLK(st.st_mode))
884 r = asprintf(&p, "/run/systemd/nspawn/locks/block-%u:%u", major(st.st_rdev), minor(st.st_rdev));
885 else if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))
886 r = asprintf(&p, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino);
887 else
888 return -ENOTTY;
889
890 if (r < 0)
891 return -ENOMEM;
892 }
893
894 /* For block devices we don't need the "local" lock, as the major/minor lock above should be sufficient, since
895 * block devices are device local anyway. */
896 if (!path_startswith(path, "/dev")) {
897 r = make_lock_file_for(path, operation, &t);
898 if (r < 0)
899 return r;
900 }
901
902 if (p) {
903 mkdir_p("/run/systemd/nspawn/locks", 0700);
904
905 r = make_lock_file(p, operation, global);
906 if (r < 0) {
907 release_lock_file(&t);
908 return r;
909 }
910 } else
911 *global = (LockFile) LOCK_FILE_INIT;
912
913 *local = t;
914 return 0;
915 }
916
917 int image_set_limit(Image *i, uint64_t referenced_max) {
918 assert(i);
919
920 if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i))
921 return -EROFS;
922
923 if (i->type != IMAGE_SUBVOLUME)
924 return -EOPNOTSUPP;
925
926 /* We set the quota both for the subvolume as well as for the
927 * subtree. The latter is mostly for historical reasons, since
928 * we didn't use to have a concept of subtree quota, and hence
929 * only modified the subvolume quota. */
930
931 (void) btrfs_qgroup_set_limit(i->path, 0, referenced_max);
932 (void) btrfs_subvol_auto_qgroup(i->path, 0, true);
933 return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max);
934 }
935
936 int image_read_metadata(Image *i) {
937 _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
938 int r;
939
940 assert(i);
941
942 r = image_path_lock(i->path, LOCK_SH|LOCK_NB, &global_lock, &local_lock);
943 if (r < 0)
944 return r;
945
946 switch (i->type) {
947
948 case IMAGE_SUBVOLUME:
949 case IMAGE_DIRECTORY: {
950 _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL;
951 sd_id128_t machine_id = SD_ID128_NULL;
952 _cleanup_free_ char *hostname = NULL;
953 _cleanup_free_ char *path = NULL;
954
955 r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT, &path);
956 if (r < 0 && r != -ENOENT)
957 log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name);
958 else if (r >= 0) {
959 r = read_etc_hostname(path, &hostname);
960 if (r < 0)
961 log_debug_errno(errno, "Failed to read /etc/hostname of image %s: %m", i->name);
962 }
963
964 path = mfree(path);
965
966 r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT, &path);
967 if (r < 0 && r != -ENOENT)
968 log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name);
969 else if (r >= 0) {
970 _cleanup_close_ int fd = -1;
971
972 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
973 if (fd < 0)
974 log_debug_errno(errno, "Failed to open %s: %m", path);
975 else {
976 r = id128_read_fd(fd, ID128_PLAIN, &machine_id);
977 if (r < 0)
978 log_debug_errno(r, "Image %s contains invalid machine ID.", i->name);
979 }
980 }
981
982 path = mfree(path);
983
984 r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT, &path);
985 if (r < 0 && r != -ENOENT)
986 log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name);
987 else if (r >= 0) {
988 r = load_env_file_pairs(NULL, path, NULL, &machine_info);
989 if (r < 0)
990 log_debug_errno(r, "Failed to parse machine-info data of %s: %m", i->name);
991 }
992
993 path = mfree(path);
994
995 r = chase_symlinks("/etc/os-release", i->path, CHASE_PREFIX_ROOT, &path);
996 if (r == -ENOENT)
997 r = chase_symlinks("/usr/lib/os-release", i->path, CHASE_PREFIX_ROOT, &path);
998 if (r < 0 && r != -ENOENT)
999 log_debug_errno(r, "Failed to chase os-release in image: %m");
1000 else if (r >= 0) {
1001 r = load_env_file_pairs(NULL, path, NULL, &os_release);
1002 if (r < 0)
1003 log_debug_errno(r, "Failed to parse os-release data of %s: %m", i->name);
1004 }
1005
1006 free_and_replace(i->hostname, hostname);
1007 i->machine_id = machine_id;
1008 strv_free_and_replace(i->machine_info, machine_info);
1009 strv_free_and_replace(i->os_release, os_release);
1010
1011 break;
1012 }
1013
1014 case IMAGE_RAW:
1015 case IMAGE_BLOCK: {
1016 _cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
1017 _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
1018
1019 r = loop_device_make_by_path(i->path, O_RDONLY, &d);
1020 if (r < 0)
1021 return r;
1022
1023 r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_REQUIRE_ROOT, &m);
1024 if (r < 0)
1025 return r;
1026
1027 r = dissected_image_acquire_metadata(m);
1028 if (r < 0)
1029 return r;
1030
1031 free_and_replace(i->hostname, m->hostname);
1032 i->machine_id = m->machine_id;
1033 strv_free_and_replace(i->machine_info, m->machine_info);
1034 strv_free_and_replace(i->os_release, m->os_release);
1035
1036 break;
1037 }
1038
1039 default:
1040 return -EOPNOTSUPP;
1041 }
1042
1043 i->metadata_valid = true;
1044
1045 return 0;
1046 }
1047
1048 int image_name_lock(const char *name, int operation, LockFile *ret) {
1049 const char *p;
1050
1051 assert(name);
1052 assert(ret);
1053
1054 /* Locks an image name, regardless of the precise path used. */
1055
1056 if (!image_name_is_valid(name))
1057 return -EINVAL;
1058
1059 if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) {
1060 *ret = (LockFile) LOCK_FILE_INIT;
1061 return 0;
1062 }
1063
1064 if (streq(name, ".host"))
1065 return -EBUSY;
1066
1067 mkdir_p("/run/systemd/nspawn/locks", 0700);
1068 p = strjoina("/run/systemd/nspawn/locks/name-", name);
1069
1070 return make_lock_file(p, operation, ret);
1071 }
1072
1073 bool image_name_is_valid(const char *s) {
1074 if (!filename_is_valid(s))
1075 return false;
1076
1077 if (string_has_cc(s, NULL))
1078 return false;
1079
1080 if (!utf8_is_valid(s))
1081 return false;
1082
1083 /* Temporary files for atomically creating new files */
1084 if (startswith(s, ".#"))
1085 return false;
1086
1087 return true;
1088 }
1089
1090 static const char* const image_type_table[_IMAGE_TYPE_MAX] = {
1091 [IMAGE_DIRECTORY] = "directory",
1092 [IMAGE_SUBVOLUME] = "subvolume",
1093 [IMAGE_RAW] = "raw",
1094 [IMAGE_BLOCK] = "block",
1095 };
1096
1097 DEFINE_STRING_TABLE_LOOKUP(image_type, ImageType);