]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
8c1be37e LP |
2 | #pragma once |
3 | ||
8c1be37e LP |
4 | #include <stdbool.h> |
5 | ||
dccca82b LP |
6 | #include "sd-id128.h" |
7 | ||
49ae9d91 | 8 | #include "architecture.h" |
dd894023 | 9 | #include "gpt.h" |
18d73705 | 10 | #include "list.h" |
6aa05ebd | 11 | #include "loop-util.h" |
8c1be37e LP |
12 | #include "macro.h" |
13 | ||
14 | typedef struct DissectedImage DissectedImage; | |
15 | typedef struct DissectedPartition DissectedPartition; | |
18b5886e | 16 | typedef struct DecryptedImage DecryptedImage; |
18d73705 | 17 | typedef struct MountOptions MountOptions; |
89e62e0b | 18 | typedef struct VeritySettings VeritySettings; |
8c1be37e LP |
19 | |
20 | struct DissectedPartition { | |
21 | bool found:1; | |
22 | bool rw:1; | |
de98f631 | 23 | bool growfs:1; |
6b41a7b2 LP |
24 | int partno; /* -1 if there was no partition and the images contains a file system directly */ |
25 | Architecture architecture; /* Intended architecture: either native, secondary or unset ARCHITECTURE_INVALID. */ | |
26 | sd_id128_t uuid; /* Partition entry UUID as reported by the GPT */ | |
8c1be37e LP |
27 | char *fstype; |
28 | char *node; | |
08fe0a53 | 29 | char *label; |
18b5886e LP |
30 | char *decrypted_node; |
31 | char *decrypted_fstype; | |
18d73705 | 32 | char *mount_options; |
f7725647 | 33 | int mount_node_fd; |
88b3300f LP |
34 | uint64_t size; |
35 | uint64_t offset; | |
d90b03f8 | 36 | uint64_t gpt_flags; |
8c1be37e LP |
37 | }; |
38 | ||
babd5b08 YW |
39 | #define DISSECTED_PARTITION_NULL \ |
40 | ((DissectedPartition) { \ | |
41 | .partno = -1, \ | |
42 | .architecture = _ARCHITECTURE_INVALID, \ | |
254d1313 | 43 | .mount_node_fd = -EBADF, \ |
babd5b08 | 44 | }) |
088377e0 YW |
45 | #define TAKE_PARTITION(p) \ |
46 | ({ \ | |
47 | DissectedPartition *_pp = &(p), _p = *_pp; \ | |
48 | *_pp = DISSECTED_PARTITION_NULL; \ | |
49 | _p; \ | |
50 | }) | |
babd5b08 | 51 | |
18b5886e | 52 | typedef enum DissectImageFlags { |
08f14be4 YW |
53 | DISSECT_IMAGE_DEVICE_READ_ONLY = 1 << 0, /* Make device read-only */ |
54 | DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */ | |
55 | DISSECT_IMAGE_DISCARD = 1 << 2, /* Turn on "discard" if file system supports it, on all block devices */ | |
56 | DISSECT_IMAGE_DISCARD_ON_CRYPTO = 1 << 3, /* Turn on "discard" also on crypto devices */ | |
57 | DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP | | |
58 | DISSECT_IMAGE_DISCARD | | |
59 | DISSECT_IMAGE_DISCARD_ON_CRYPTO, | |
60 | DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */ | |
61 | DISSECT_IMAGE_GENERIC_ROOT = 1 << 5, /* If no partition table or only single generic partition, assume it's the root fs */ | |
62 | DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */ | |
63 | DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */ | |
64 | DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */ | |
65 | DISSECT_IMAGE_VALIDATE_OS_EXT = 1 << 9, /* Refuse mounting images that aren't identifiable as OS extension images */ | |
66 | DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */ | |
67 | DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */ | |
68 | DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */ | |
69 | DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */ | |
70 | DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */ | |
71 | DISSECT_IMAGE_USR_NO_ROOT = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */ | |
72 | DISSECT_IMAGE_REQUIRE_ROOT = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */ | |
73 | DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */ | |
74 | DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY | | |
75 | DISSECT_IMAGE_MOUNT_READ_ONLY, | |
76 | DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */ | |
77 | DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */ | |
73d88b80 LP |
78 | DISSECT_IMAGE_ADD_PARTITION_DEVICES = 1 << 20, /* Create partition devices via BLKPG_ADD_PARTITION */ |
79 | DISSECT_IMAGE_PIN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions and pin them by fd */ | |
f7725647 | 80 | DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */ |
18b5886e | 81 | } DissectImageFlags; |
8c1be37e LP |
82 | |
83 | struct DissectedImage { | |
4623e8e6 | 84 | bool encrypted:1; |
c3c88d67 | 85 | bool has_verity:1; /* verity available in image, but not necessarily used */ |
8ee9615e | 86 | bool has_verity_sig:1; /* pkcs#7 signature embedded in image */ |
c3c88d67 | 87 | bool verity_ready:1; /* verity available, fully specified and usable */ |
8ee9615e | 88 | bool verity_sig_ready:1; /* verity signature logic, fully specified and usable */ |
e7cbe5cb | 89 | bool single_file_system:1; /* MBR/GPT or single file system */ |
3b925504 | 90 | |
1e63dc4f | 91 | LoopDevice *loop; |
8c1be37e | 92 | DissectedPartition partitions[_PARTITION_DESIGNATOR_MAX]; |
ac1e1b5f | 93 | DecryptedImage *decrypted_image; |
3b925504 | 94 | |
8ee9615e | 95 | /* Meta information extracted from /etc/os-release and similar */ |
593fe6c0 | 96 | char *image_name; |
b387778c | 97 | sd_id128_t image_uuid; |
3b925504 LP |
98 | char *hostname; |
99 | sd_id128_t machine_id; | |
100 | char **machine_info; | |
101 | char **os_release; | |
fab22946 | 102 | char **initrd_release; |
7718ac97 | 103 | char **extension_release; |
a4e0d617 | 104 | int has_init_system; |
8c1be37e LP |
105 | }; |
106 | ||
18d73705 | 107 | struct MountOptions { |
569a0e42 | 108 | PartitionDesignator partition_designator; |
18d73705 LB |
109 | char *options; |
110 | LIST_FIELDS(MountOptions, mount_options); | |
111 | }; | |
112 | ||
89e62e0b LP |
113 | struct VeritySettings { |
114 | /* Binary root hash for the Verity Merkle tree */ | |
115 | void *root_hash; | |
116 | size_t root_hash_size; | |
117 | ||
118 | /* PKCS#7 signature of the above */ | |
119 | void *root_hash_sig; | |
120 | size_t root_hash_sig_size; | |
121 | ||
122 | /* Path to the verity data file, if stored externally */ | |
123 | char *data_path; | |
aee36b4e LP |
124 | |
125 | /* PARTITION_ROOT or PARTITION_USR, depending on what these Verity settings are for */ | |
126 | PartitionDesignator designator; | |
89e62e0b LP |
127 | }; |
128 | ||
aee36b4e LP |
129 | #define VERITY_SETTINGS_DEFAULT { \ |
130 | .designator = _PARTITION_DESIGNATOR_INVALID \ | |
131 | } | |
132 | ||
18d73705 LB |
133 | MountOptions* mount_options_free_all(MountOptions *options); |
134 | DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all); | |
569a0e42 | 135 | const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator); |
18d73705 | 136 | |
c80c9079 | 137 | int probe_filesystem_full(int fd, const char *path, uint64_t offset, uint64_t size, char **ret_fstype); |
d2c6e79d | 138 | static inline int probe_filesystem(const char *path, char **ret_fstype) { |
c80c9079 | 139 | return probe_filesystem_full(-1, path, 0, UINT64_MAX, ret_fstype); |
d2c6e79d | 140 | } |
08f14be4 YW |
141 | int dissect_image_file( |
142 | const char *path, | |
369de26f YW |
143 | const VeritySettings *verity, |
144 | const MountOptions *mount_options, | |
369de26f YW |
145 | DissectImageFlags flags, |
146 | DissectedImage **ret); | |
1e63dc4f YW |
147 | int dissect_loop_device(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); |
148 | int dissect_loop_device_and_warn(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); | |
8c1be37e LP |
149 | |
150 | DissectedImage* dissected_image_unref(DissectedImage *m); | |
151 | DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); | |
152 | ||
e330f97a YW |
153 | int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags); |
154 | int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags); | |
21b61b1d LP |
155 | int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, uid_t uid_range, DissectImageFlags flags); |
156 | int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, uid_t uid_range, DissectImageFlags flags); | |
18b5886e | 157 | |
22847508 | 158 | int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_flags); |
3b925504 | 159 | |
9321ad51 | 160 | DecryptedImage* decrypted_image_ref(DecryptedImage *p); |
18b5886e LP |
161 | DecryptedImage* decrypted_image_unref(DecryptedImage *p); |
162 | DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref); | |
f906075a | 163 | |
f906075a | 164 | int dissected_image_relinquish(DissectedImage *m); |
8c1be37e | 165 | |
89e62e0b LP |
166 | int verity_settings_load(VeritySettings *verity, const char *image, const char *root_hash_path, const char *root_hash_sig_path); |
167 | void verity_settings_done(VeritySettings *verity); | |
168 | ||
c2534821 LP |
169 | static inline bool verity_settings_data_covers(const VeritySettings *verity, PartitionDesignator d) { |
170 | /* Returns true if the verity settings contain sufficient information to cover the specified partition */ | |
171 | return verity && | |
172 | ((d >= 0 && verity->designator == d) || (d == PARTITION_ROOT && verity->designator < 0)) && | |
173 | verity->root_hash && | |
174 | verity->data_path; | |
175 | } | |
176 | ||
88b3300f LP |
177 | int dissected_image_load_verity_sig_partition(DissectedImage *m, int fd, VeritySettings *verity); |
178 | ||
49536766 LP |
179 | bool dissected_image_verity_candidate(const DissectedImage *image, PartitionDesignator d); |
180 | bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignator d); | |
8ee9615e | 181 | bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesignator d); |
6aa05ebd | 182 | |
e330f97a | 183 | int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device); |
4beda316 | 184 | |
cedf5b1a | 185 | int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, const MountOptions *options, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_sysext_scope); |