]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
loop-util: insist on setting the sector size correctly
authorLennart Poettering <lennart@poettering.net>
Tue, 17 Jan 2023 14:49:31 +0000 (15:49 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Jan 2023 09:10:57 +0000 (10:10 +0100)
If we attach a disk image to a loopback device the sector size of the
image must match the one of the loopback device, hence be more careful
here.

src/shared/loop-util.c

index 4b63e0340b9a3a80433fa9d93e66ea2f9f48d4d7..f6ae769d89201b34a9c364dd4aa238dc04c854ae 100644 (file)
@@ -131,8 +131,10 @@ static int loop_configure_verify(int fd, const struct loop_config *c) {
                 if (r < 0)
                         return r;
 
-                if (ssz != c->block_size)
+                if (ssz != c->block_size) {
                         log_debug("LOOP_CONFIGURE didn't honour requested block size %" PRIu32 ", got %" PRIu32 " instead. Ignoring.", c->block_size, ssz);
+                        broken = true;
+                }
         }
 
         if (c->info.lo_sizelimit != 0) {
@@ -173,6 +175,7 @@ static int loop_configure_verify(int fd, const struct loop_config *c) {
 
 static int loop_configure_fallback(int fd, const struct loop_config *c) {
         struct loop_info64 info_copy;
+        int r;
 
         assert(fd >= 0);
         assert(c);
@@ -220,6 +223,21 @@ static int loop_configure_fallback(int fd, const struct loop_config *c) {
                 if (ioctl(fd, BLKFLSBUF, 0) < 0)
                         log_debug_errno(errno, "Failed to issue BLKFLSBUF ioctl, ignoring: %m");
 
+        /* If a block size is requested then try to configure it. If that doesn't work, ignore errors, but
+         * afterwards, let's validate what is in effect, and if it doesn't match what we want, fail */
+        if (c->block_size != 0) {
+                uint32_t ssz;
+
+                if (ioctl(fd, LOOP_SET_BLOCK_SIZE, (unsigned long) c->block_size) < 0)
+                        log_debug_errno(errno, "Failed to set sector size, ignoring: %m");
+
+                r = blockdev_get_sector_size(fd, &ssz);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to read sector size: %m");
+                if (ssz != c->block_size)
+                        return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Sector size of loopback device doesn't match what we requested, refusing.");
+        }
+
         /* LO_FLAGS_DIRECT_IO is a flags we need to configure via explicit ioctls. */
         if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_DIRECT_IO))
                 if (ioctl(fd, LOOP_SET_DIRECT_IO, 1UL) < 0)