From: Thomas Weißschuh Date: Tue, 6 Aug 2024 17:07:48 +0000 (+0200) Subject: libblkid: apfs: validate checksums X-Git-Tag: v2.42-start~229^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2011a616aa533c336f9242f25017ce7043557e4c;p=thirdparty%2Futil-linux.git libblkid: apfs: validate checksums The apfs superblock contains a checksum based on Fletcher-64. Validate the checksum to make the probing more robust. Signed-off-by: Thomas Weißschuh --- diff --git a/libblkid/src/superblocks/apfs.c b/libblkid/src/superblocks/apfs.c index b7f09f334..4557abcbf 100644 --- a/libblkid/src/superblocks/apfs.c +++ b/libblkid/src/superblocks/apfs.c @@ -35,7 +35,38 @@ struct apfs_super_block { uint64_t read_only_features; uint64_t incompatible_features; uint8_t uuid[16]; -}; + + uint8_t padding[4008]; // Pad to 4096 bytes for checksum +} __attribute__((packed)); + +static uint64_t apfs_fletcher64(const uint8_t *buf, size_t size) +{ + uint64_t lo32 = 0, hi32 = 0, csum_hi; + uint32_t csum_low; + size_t i; + + for (i = 0; i < size / 4; i++) { + lo32 += le32_to_cpu(((uint32_t *)buf)[i]); + hi32 += lo32; + } + + csum_low = ~((lo32 + hi32) % UINT32_MAX); + csum_hi = ~((lo32 + csum_low) % UINT32_MAX); + + return csum_hi << 32 | csum_low; +} + +static int apfs_verify_checksum(blkid_probe pr, + const struct apfs_super_block *sb) +{ + const size_t csummed_start_offset = offsetof(__typeof__(*sb), oid); + uint64_t csum; + + csum = apfs_fletcher64(((const uint8_t *)sb) + csummed_start_offset, + sizeof(*sb) - csummed_start_offset); + + return blkid_probe_verify_csum(pr, csum, le64_to_cpu(sb->checksum)); +} static int probe_apfs(blkid_probe pr, const struct blkid_idmag *mag) { @@ -45,6 +76,9 @@ static int probe_apfs(blkid_probe pr, const struct blkid_idmag *mag) if (!sb) return errno ? -errno : BLKID_PROBE_NONE; + if (!apfs_verify_checksum(pr, sb)) + return BLKID_PROBE_NONE; + if (le16_to_cpu(sb->type) != APFS_CONTAINER_SUPERBLOCK_TYPE) return BLKID_PROBE_NONE;