From: Chris Mason Date: Fri, 22 May 2026 16:13:50 +0000 (-0700) Subject: dissect-image: cast to uint64_t before *512 for sig lookup X-Git-Tag: v261-rc2~34^2~4 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=2eff83757409db0a3eedfcdff1f2445a291c8ab7;p=thirdparty%2Fsystemd.git dissect-image: cast to uint64_t before *512 for sig lookup 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 --- diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index db813a7eb4e..e00dce3fbd9 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -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)