Blob Blame History Raw
From 71ac1ab735eeaa71af0198253c06f783c8582362 Mon Sep 17 00:00:00 2001
From: Torsten Hilbrich <torsten.hilbrich@secunet.com>
Date: Mon, 20 Jun 2016 07:09:10 +0200
Subject: [PATCH 194/197] liblkid: Add length check in probe_nilfs2 before
 crc32

The bytes variable is read from the file system to probe and must be
checked before used as length parameter in the crc32 call.

The following problems may occur here:

- bytes smaller than sumoff + 4: underflow in length calculation
- bytes larger than remaining space in sb: overflow of buffer

This fixes a problem where an encrypted volume had the correct magic
values 0x3434 at offset 0x406 and the following uint16_t (which is
read into the nilfs_super_block.s_bytes struct) was parsed as 1.

Then crc32 was called with the length value 18446744073709551597
causing a segmentation fault.

[kzak@redhat.com: - fix probe_nilfs2() return code
		  - RHEL-7: return 1 if superblock bytes are out if
		    range; we use the same for invalid superblock in
                    current upstream tree]

Upstream: http://github.com/karelzak/util-linux/commit/ac681a310c32319423297544833932f4d689a7a2
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1802240
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 libblkid/src/superblocks/nilfs.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/libblkid/src/superblocks/nilfs.c b/libblkid/src/superblocks/nilfs.c
index a7e4939a2..a4b3c22b6 100644
--- a/libblkid/src/superblocks/nilfs.c
+++ b/libblkid/src/superblocks/nilfs.c
@@ -78,6 +78,7 @@ static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
 	static unsigned char sum[4];
 	const int sumoff = offsetof(struct nilfs_super_block, s_sum);
 	size_t bytes;
+	const size_t crc_start = sumoff + 4;
 	uint32_t crc;
 
 	sb = blkid_probe_get_sb(pr, mag, struct nilfs_super_block);
@@ -85,9 +86,15 @@ static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
 		return errno ? -errno : 1;
 
 	bytes = le16_to_cpu(sb->s_bytes);
+	/* ensure that no underrun can happen in the length parameter
+	 * of the crc32 call or more data are processed than read into
+	 * sb */
+	if (bytes < crc_start || bytes > sizeof(struct nilfs_super_block))
+		return 1;
+
 	crc = crc32(le32_to_cpu(sb->s_crc_seed), (unsigned char *)sb, sumoff);
 	crc = crc32(crc, sum, 4);
-	crc = crc32(crc, (unsigned char *)sb + sumoff + 4, bytes - sumoff - 4);
+	crc = crc32(crc, (unsigned char *)sb + crc_start, bytes - crc_start);
 
 	if (crc != le32_to_cpu(sb->s_sum))
 		return 1;
-- 
2.25.2