]>
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; | |
8c1be37e LP |
36 | }; |
37 | ||
babd5b08 YW |
38 | #define DISSECTED_PARTITION_NULL \ |
39 | ((DissectedPartition) { \ | |
40 | .partno = -1, \ | |
41 | .architecture = _ARCHITECTURE_INVALID, \ | |
f7725647 | 42 | .mount_node_fd = -1, \ |
babd5b08 YW |
43 | }) |
44 | ||
18b5886e | 45 | typedef enum DissectImageFlags { |
08f14be4 YW |
46 | DISSECT_IMAGE_DEVICE_READ_ONLY = 1 << 0, /* Make device read-only */ |
47 | DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */ | |
48 | DISSECT_IMAGE_DISCARD = 1 << 2, /* Turn on "discard" if file system supports it, on all block devices */ | |
49 | DISSECT_IMAGE_DISCARD_ON_CRYPTO = 1 << 3, /* Turn on "discard" also on crypto devices */ | |
50 | DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP | | |
51 | DISSECT_IMAGE_DISCARD | | |
52 | DISSECT_IMAGE_DISCARD_ON_CRYPTO, | |
53 | DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */ | |
54 | DISSECT_IMAGE_GENERIC_ROOT = 1 << 5, /* If no partition table or only single generic partition, assume it's the root fs */ | |
55 | DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */ | |
56 | DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */ | |
57 | DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */ | |
58 | DISSECT_IMAGE_VALIDATE_OS_EXT = 1 << 9, /* Refuse mounting images that aren't identifiable as OS extension images */ | |
59 | DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */ | |
60 | DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */ | |
61 | DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */ | |
62 | DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */ | |
63 | DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */ | |
64 | 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 */ | |
65 | 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) */ | |
66 | DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */ | |
67 | DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY | | |
68 | DISSECT_IMAGE_MOUNT_READ_ONLY, | |
69 | DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */ | |
70 | 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= */ | |
71 | DISSECT_IMAGE_MANAGE_PARTITION_DEVICES = 1 << 20, /* Manage partition devices, e.g. probe each partition in more detail */ | |
f7725647 YW |
72 | DISSECT_IMAGE_OPEN_PARTITION_DEVICES = 1 << 21, /* Open dissected partitions and decrypted partitions */ |
73 | DISSECT_IMAGE_BLOCK_DEVICE = DISSECT_IMAGE_MANAGE_PARTITION_DEVICES | | |
74 | DISSECT_IMAGE_OPEN_PARTITION_DEVICES, | |
75 | DISSECT_IMAGE_RELAX_SYSEXT_CHECK = 1 << 22, /* Don't insist that the extension-release file name matches the image name */ | |
18b5886e | 76 | } DissectImageFlags; |
8c1be37e LP |
77 | |
78 | struct DissectedImage { | |
4623e8e6 | 79 | bool encrypted:1; |
c3c88d67 | 80 | bool has_verity:1; /* verity available in image, but not necessarily used */ |
8ee9615e | 81 | bool has_verity_sig:1; /* pkcs#7 signature embedded in image */ |
c3c88d67 | 82 | bool verity_ready:1; /* verity available, fully specified and usable */ |
8ee9615e | 83 | bool verity_sig_ready:1; /* verity signature logic, fully specified and usable */ |
e7cbe5cb | 84 | bool single_file_system:1; /* MBR/GPT or single file system */ |
3b925504 | 85 | |
1e63dc4f | 86 | LoopDevice *loop; |
8c1be37e | 87 | DissectedPartition partitions[_PARTITION_DESIGNATOR_MAX]; |
ac1e1b5f | 88 | DecryptedImage *decrypted_image; |
3b925504 | 89 | |
8ee9615e | 90 | /* Meta information extracted from /etc/os-release and similar */ |
593fe6c0 | 91 | char *image_name; |
b387778c | 92 | sd_id128_t image_uuid; |
3b925504 LP |
93 | char *hostname; |
94 | sd_id128_t machine_id; | |
95 | char **machine_info; | |
96 | char **os_release; | |
fab22946 | 97 | char **initrd_release; |
7718ac97 | 98 | char **extension_release; |
a4e0d617 | 99 | int has_init_system; |
8c1be37e LP |
100 | }; |
101 | ||
18d73705 | 102 | struct MountOptions { |
569a0e42 | 103 | PartitionDesignator partition_designator; |
18d73705 LB |
104 | char *options; |
105 | LIST_FIELDS(MountOptions, mount_options); | |
106 | }; | |
107 | ||
89e62e0b LP |
108 | struct VeritySettings { |
109 | /* Binary root hash for the Verity Merkle tree */ | |
110 | void *root_hash; | |
111 | size_t root_hash_size; | |
112 | ||
113 | /* PKCS#7 signature of the above */ | |
114 | void *root_hash_sig; | |
115 | size_t root_hash_sig_size; | |
116 | ||
117 | /* Path to the verity data file, if stored externally */ | |
118 | char *data_path; | |
aee36b4e LP |
119 | |
120 | /* PARTITION_ROOT or PARTITION_USR, depending on what these Verity settings are for */ | |
121 | PartitionDesignator designator; | |
89e62e0b LP |
122 | }; |
123 | ||
aee36b4e LP |
124 | #define VERITY_SETTINGS_DEFAULT { \ |
125 | .designator = _PARTITION_DESIGNATOR_INVALID \ | |
126 | } | |
127 | ||
18d73705 LB |
128 | MountOptions* mount_options_free_all(MountOptions *options); |
129 | DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all); | |
569a0e42 | 130 | const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator); |
18d73705 | 131 | |
d2c6e79d YW |
132 | int probe_filesystem_full(int fd, const char *path, char **ret_fstype); |
133 | static inline int probe_filesystem(const char *path, char **ret_fstype) { | |
134 | return probe_filesystem_full(-1, path, ret_fstype); | |
135 | } | |
08f14be4 YW |
136 | int dissect_image_file( |
137 | const char *path, | |
369de26f YW |
138 | const VeritySettings *verity, |
139 | const MountOptions *mount_options, | |
369de26f YW |
140 | DissectImageFlags flags, |
141 | DissectedImage **ret); | |
1e63dc4f YW |
142 | int dissect_loop_device(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); |
143 | int dissect_loop_device_and_warn(LoopDevice *loop, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); | |
8c1be37e LP |
144 | |
145 | DissectedImage* dissected_image_unref(DissectedImage *m); | |
146 | DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); | |
147 | ||
e330f97a YW |
148 | int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags); |
149 | int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags); | |
21b61b1d LP |
150 | int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, uid_t uid_range, DissectImageFlags flags); |
151 | int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, uid_t uid_range, DissectImageFlags flags); | |
18b5886e | 152 | |
22847508 | 153 | int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_flags); |
3b925504 | 154 | |
9321ad51 | 155 | DecryptedImage* decrypted_image_ref(DecryptedImage *p); |
18b5886e LP |
156 | DecryptedImage* decrypted_image_unref(DecryptedImage *p); |
157 | DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref); | |
f906075a | 158 | |
f906075a | 159 | int dissected_image_relinquish(DissectedImage *m); |
8c1be37e | 160 | |
89e62e0b LP |
161 | int verity_settings_load(VeritySettings *verity, const char *image, const char *root_hash_path, const char *root_hash_sig_path); |
162 | void verity_settings_done(VeritySettings *verity); | |
163 | ||
88b3300f LP |
164 | int dissected_image_load_verity_sig_partition(DissectedImage *m, int fd, VeritySettings *verity); |
165 | ||
49536766 LP |
166 | bool dissected_image_verity_candidate(const DissectedImage *image, PartitionDesignator d); |
167 | bool dissected_image_verity_ready(const DissectedImage *image, PartitionDesignator d); | |
8ee9615e | 168 | bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesignator d); |
6aa05ebd | 169 | |
e330f97a | 170 | int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device); |
4beda316 | 171 | |
cedf5b1a | 172 | 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); |