]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/dissect-image.c
tree-wide: use UINT64_MAX or friends
[thirdparty/systemd.git] / src / shared / dissect-image.c
index 6ad68584e5d1a0fea2a78814720285c9f1a762dd..997b265259bde7a1c5584499569322c3038ac7e8 100644 (file)
@@ -27,6 +27,7 @@
 #include "dissect-image.h"
 #include "dm-util.h"
 #include "env-file.h"
+#include "extension-release.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
@@ -1550,13 +1551,12 @@ struct DecryptedImage {
 
 DecryptedImage* decrypted_image_unref(DecryptedImage* d) {
 #if HAVE_LIBCRYPTSETUP
-        size_t i;
         int r;
 
         if (!d)
                 return NULL;
 
-        for (i = 0; i < d->n_decrypted; i++) {
+        for (size_t i = 0; i < d->n_decrypted; i++) {
                 DecryptedPartition *p = d->decrypted + i;
 
                 if (p->device && p->name && !p->relinquished) {
@@ -2002,19 +2002,15 @@ int dissected_image_decrypt_interactively(
 }
 
 int decrypted_image_relinquish(DecryptedImage *d) {
-
-#if HAVE_LIBCRYPTSETUP
-        size_t i;
-        int r;
-#endif
-
         assert(d);
 
-        /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so
-         * that we don't clean it up ourselves either anymore */
+        /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a
+         * boolean so that we don't clean it up ourselves either anymore */
 
 #if HAVE_LIBCRYPTSETUP
-        for (i = 0; i < d->n_decrypted; i++) {
+        int r;
+
+        for (size_t i = 0; i < d->n_decrypted; i++) {
                 DecryptedPartition *p = d->decrypted + i;
 
                 if (p->relinquished)
@@ -2264,7 +2260,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
         _cleanup_(sigkill_waitp) pid_t child = 0;
         sd_id128_t machine_id = SD_ID128_NULL;
         _cleanup_free_ char *hostname = NULL;
-        unsigned n_meta_initialized = 0, k;
+        unsigned n_meta_initialized = 0;
         int fds[2 * _META_MAX], r, v;
         ssize_t n;
 
@@ -2315,7 +2311,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
                         _exit(EXIT_FAILURE);
                 }
 
-                for (k = 0; k < _META_MAX; k++) {
+                for (unsigned k = 0; k < _META_MAX; k++) {
                         _cleanup_close_ int fd = -ENOENT;
                         const char *p;
 
@@ -2335,7 +2331,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
                                 continue;
                         }
 
-                        r = copy_bytes(fd, fds[2*k+1], (uint64_t) -1, 0);
+                        r = copy_bytes(fd, fds[2*k+1], UINT64_MAX, 0);
                         if (r < 0) {
                                 (void) write(error_pipe[1], &r, sizeof(r));
                                 _exit(EXIT_FAILURE);
@@ -2349,7 +2345,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
 
         error_pipe[1] = safe_close(error_pipe[1]);
 
-        for (k = 0; k < _META_MAX; k++) {
+        for (unsigned k = 0; k < _META_MAX; k++) {
                 _cleanup_fclose_ FILE *f = NULL;
 
                 if (!paths[k])
@@ -2438,7 +2434,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
         strv_free_and_replace(m->extension_release, extension_release);
 
 finish:
-        for (k = 0; k < n_meta_initialized; k++)
+        for (unsigned k = 0; k < n_meta_initialized; k++)
                 safe_close_pair(fds + 2*k);
 
         return r;
@@ -2621,7 +2617,14 @@ static const char *const partition_designator_table[] = {
         [PARTITION_VAR] = "var",
 };
 
-int verity_dissect_and_mount(const char *src, const char *dest, const MountOptions *options) {
+int verity_dissect_and_mount(
+                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) {
+
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
         _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
@@ -2683,6 +2686,30 @@ int verity_dissect_and_mount(const char *src, const char *dest, const MountOptio
         if (r < 0)
                 return log_debug_errno(r, "Failed to mount image: %m");
 
+        /* If we got os-release values from the caller, then we need to match them with the image's
+         * extension-release.d/ content. Return -EINVAL if there's any mismatch.
+         * First, check the distro ID. If that matches, then check the new SYSEXT_LEVEL value if
+         * available, or else fallback to VERSION_ID. */
+        if (required_host_os_release_id &&
+            (required_host_os_release_version_id || required_host_os_release_sysext_level)) {
+                _cleanup_strv_free_ char **extension_release = NULL;
+
+                r = load_extension_release_pairs(dest, dissected_image->image_name, &extension_release);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to parse image %s extension-release metadata: %m", dissected_image->image_name);
+
+                r = extension_release_validate(
+                        dissected_image->image_name,
+                        required_host_os_release_id,
+                        required_host_os_release_version_id,
+                        required_host_os_release_sysext_level,
+                        extension_release);
+                if (r == 0)
+                        return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", dissected_image->image_name);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", dissected_image->image_name);
+        }
+
         if (decrypted_image) {
                 r = decrypted_image_relinquish(decrypted_image);
                 if (r < 0)