]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: cast to uint64_t before *512 for sig lookup
authorChris Mason <clm@meta.com>
Fri, 22 May 2026 16:13:50 +0000 (09:13 -0700)
committerLennart Poettering <lennart@amutable.com>
Fri, 22 May 2026 20:16:07 +0000 (22:16 +0200)
In the PARTITION_ROOT_VERITY_SIG / PARTITION_USR_VERITY_SIG branch of
dissect_image(), the call to acquire_sig_for_roothash() passes the
partition offset and size as

    acquire_sig_for_roothash(fd,
                             start * 512,
                             size * 512,
                             &root_hash, NULL);

where start and size are blkid_loff_t (int64_t). The literal 512 is
int, so the multiplication is performed in int64_t and overflows for
LBA values in (INT64_MAX/512, INT64_MAX]. The overflowed signed result
is then converted to the uint64_t parameters of
acquire_sig_for_roothash(), yielding a near-UINT64_MAX
partition_offset that slips past the sole offset guard (an exact
== UINT64_MAX sentinel) and reaches pread() with a corrupt disk
offset. An overflowed partition_size would be rejected by the 4 MiB
EFBIG check at src/shared/dissect-image.c:710-712 before pread(); the
dangerous scenario is a corrupt offset combined with a legitimate
small size.

The three sibling call sites at src/shared/dissect-image.c:1284,
1589-1590 and 1671-1672 all cast to uint64_t before multiplying by
512; only this call site was missed.

Fix by casting start and size to uint64_t before the multiplication,
matching the sibling sites and making the arithmetic well-defined.

Fixes: 98ca65c36aa9 ("dissect: check that roothash in signature matches before selecting partition")
Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
src/shared/dissect-image.c

index db813a7eb4e336506f3f0578923b03ffcd907875..e00dce3fbd96908aaa3cb3cb584a53c93ede271b 100644 (file)
@@ -1417,8 +1417,8 @@ static int dissect_image(
 
                                         r = acquire_sig_for_roothash(
                                                         fd,
-                                                        start * 512,
-                                                        size * 512,
+                                                        (uint64_t) start * 512,
+                                                        (uint64_t) size * 512,
                                                         &root_hash,
                                                         /* ret_root_hash_sig= */ NULL);
                                         if (r < 0)