]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/dissect-image.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / shared / dissect-image.c
index 505a83f54f8f829b5a9599b89ba924f11263a7ed..5bb0d3a478ccc24bfae574e3fee42cc7c52045d9 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
 #include <libcryptsetup.h>
+#ifndef CRYPT_LUKS
+#define CRYPT_LUKS NULL
+#endif
 #endif
 #include <sys/mount.h>
 
@@ -43,7 +47,7 @@
 #include "xattr-util.h"
 
 _unused_ static int probe_filesystem(const char *node, char **ret_fstype) {
-#ifdef HAVE_BLKID
+#if HAVE_BLKID
         _cleanup_blkid_free_probe_ blkid_probe b = NULL;
         const char *fstype;
         int r;
@@ -57,7 +61,7 @@ _unused_ static int probe_filesystem(const char *node, char **ret_fstype) {
 
         errno = 0;
         r = blkid_do_safeprobe(b);
-        if (r == -2 || r == 1) {
+        if (IN_SET(r, -2, 1)) {
                 log_debug("Failed to identify any partition type on partition %s", node);
                 goto not_found;
         }
@@ -87,7 +91,7 @@ not_found:
 
 int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret) {
 
-#ifdef HAVE_BLKID
+#if HAVE_BLKID
         sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL;
         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
         bool is_gpt, is_mbr, generic_rw, multiple_generic = false;
@@ -156,7 +160,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
 
         errno = 0;
         r = blkid_do_safeprobe(b);
-        if (r == -2 || r == 1) {
+        if (IN_SET(r, -2, 1)) {
                 log_debug("Failed to identify any partition table.");
                 return -ENOPKG;
         }
@@ -266,18 +270,34 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
                         return -EIO;
                 }
                 if (n < z + 1) {
-                        unsigned j;
+                        unsigned j = 0;
 
                         /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running
                          * or it got EBUSY because udev already opened the device. Let's reprobe the device, which is a
                          * synchronous call that waits until probing is complete. */
 
-                        for (j = 0; j < 20; j++) {
+                        for (;;) {
+                                if (j++ > 20)
+                                        return -EBUSY;
 
-                                r = ioctl(fd, BLKRRPART, 0);
-                                if (r < 0)
+                                if (ioctl(fd, BLKRRPART, 0) < 0) {
                                         r = -errno;
-                                if (r >= 0 || r != -EBUSY)
+
+                                        if (r == -EINVAL) {
+                                                struct loop_info64 info;
+
+                                                /* If we are running on a loop device that has partition scanning off,
+                                                 * return an explicit recognizable error about this, so that callers
+                                                 * can generate a proper message explaining the situation. */
+
+                                                if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0 && (info.lo_flags & LO_FLAGS_PARTSCAN) == 0) {
+                                                        log_debug("Device is loop device and partition scanning is off!");
+                                                        return -EPROTONOSUPPORT;
+                                                }
+                                        }
+                                        if (r != -EBUSY)
+                                                return r;
+                                } else
                                         break;
 
                                 /* If something else has the device open, such as an udev rule, the ioctl will return
@@ -286,11 +306,8 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
                                  *
                                  * This is really something they should fix in the kernel! */
 
-                                usleep(50 * USEC_PER_MSEC);
+                                (void) usleep(50 * USEC_PER_MSEC);
                         }
-
-                        if (r < 0)
-                                return r;
                 }
 
                 e = udev_enumerate_unref(e);
@@ -591,6 +608,9 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI
 
                 if (streq_ptr(p->fstype, "crypto_LUKS"))
                         m->encrypted = true;
+
+                if (p->fstype && fstype_is_ro(p->fstype))
+                        p->rw = false;
         }
 
         *ret = m;
@@ -681,7 +701,7 @@ static int mount_partition(
                 p = where;
 
         /* If requested, turn on discard support. */
-        if (STR_IN_SET(fstype, "btrfs", "ext4", "vfat", "xfs") &&
+        if (fstype_can_discard(fstype) &&
             ((flags & DISSECT_IMAGE_DISCARD) ||
              ((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node))))
                 options = "discard";
@@ -734,7 +754,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, DissectImageFlag
         return 0;
 }
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
 typedef struct DecryptedPartition {
         struct crypt_device *device;
         char *name;
@@ -749,7 +769,7 @@ struct DecryptedImage {
 #endif
 
 DecryptedImage* decrypted_image_unref(DecryptedImage* d) {
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
         size_t i;
         int r;
 
@@ -775,7 +795,7 @@ DecryptedImage* decrypted_image_unref(DecryptedImage* d) {
         return NULL;
 }
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
 
 static int make_dm_name_and_node(const void *original_node, const char *suffix, char **ret_name, char **ret_node) {
         _cleanup_free_ char *name = NULL, *node = NULL;
@@ -838,15 +858,19 @@ static int decrypt_partition(
 
         r = crypt_init(&cd, m->node);
         if (r < 0)
-                return r;
+                return log_debug_errno(r, "Failed to initialize dm-crypt: %m");
 
-        r = crypt_load(cd, CRYPT_LUKS1, NULL);
-        if (r < 0)
+        r = crypt_load(cd, CRYPT_LUKS, NULL);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to load LUKS metadata: %m");
                 goto fail;
+        }
 
         r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase),
                                          ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) |
                                          ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0));
+        if (r < 0)
+                log_debug_errno(r, "Failed to activate LUKS device: %m");
         if (r == -EPERM) {
                 r = -EKEYREJECTED;
                 goto fail;
@@ -945,7 +969,7 @@ int dissected_image_decrypt(
                 DecryptedImage **ret) {
 
         _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL;
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
         unsigned i;
         int r;
 #endif
@@ -969,7 +993,7 @@ int dissected_image_decrypt(
                 return 0;
         }
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
         if (m->encrypted && !passphrase)
                 return -ENOKEY;
 
@@ -1051,7 +1075,7 @@ int dissected_image_decrypt_interactively(
         }
 }
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
 static int deferred_remove(DecryptedPartition *p) {
 
         struct dm_ioctl dm = {
@@ -1085,7 +1109,7 @@ static int deferred_remove(DecryptedPartition *p) {
 
 int decrypted_image_relinquish(DecryptedImage *d) {
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
         size_t i;
         int r;
 #endif
@@ -1095,7 +1119,7 @@ int decrypted_image_relinquish(DecryptedImage *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 */
 
-#ifdef HAVE_LIBCRYPTSETUP
+#if HAVE_LIBCRYPTSETUP
         for (i = 0; i < d->n_decrypted; i++) {
                 DecryptedPartition *p = d->decrypted + i;