[PATCH] gpt: verify CRC32 of partition table entry array, too
Jim Meyering
meyering at redhat.com
Wed Oct 14 18:50:39 UTC 2009
The partition table entry array's CRC was not being verified at all.
This adds an interim check. The full-blown change required to make
this implementation conform to the EFI spec will be more invasive.
* libparted/labels/gpt.c (gpt_read): Check CRC of PTE array, too.
* tests/t0280-gpt-corrupt.sh: New test for this.
Reported by Karel Zak.
---
libparted/labels/gpt.c | 16 ++++++--
tests/t0280-gpt-corrupt.sh | 95 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+), 4 deletions(-)
create mode 100755 tests/t0280-gpt-corrupt.sh
diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c
index 3f4edf7..7fa70d5 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -819,7 +819,6 @@ gpt_read (PedDisk * disk)
GPTDiskData *gpt_disk_data = disk->disk_specific;
GuidPartitionTableHeader_t* gpt;
void* ptes;
- size_t ptes_sectors;
int i;
#ifndef DISCOVER_ONLY
int write_back = 0;
@@ -914,9 +913,9 @@ gpt_read (PedDisk * disk)
goto error_free_gpt;
uint32_t p_ent_size = PED_LE32_TO_CPU (gpt->SizeOfPartitionEntry);
- ptes_sectors = ped_div_round_up (p_ent_size
- * gpt_disk_data->entry_count,
- disk->dev->sector_size);
+ size_t ptes_bytes = p_ent_size * gpt_disk_data->entry_count;
+ size_t ptes_sectors = ped_div_round_up (ptes_bytes,
+ disk->dev->sector_size);
if (xalloc_oversized (ptes_sectors, disk->dev->sector_size))
goto error_free_gpt;
@@ -927,6 +926,15 @@ gpt_read (PedDisk * disk)
ptes_sectors))
goto error_free_ptes;
+ uint32_t ptes_crc = efi_crc32 (ptes, ptes_bytes);
+ if (ptes_crc != gpt->PartitionEntryArrayCRC32) {
+ ped_exception_throw (
+ PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("partition table array (FIXME:which?) CRC mismatch"));
+ goto error_free_ptes;
+ }
+
for (i = 0; i < gpt_disk_data->entry_count; i++) {
GuidPartitionEntry_t* pte
= (GuidPartitionEntry_t*) ((char *)ptes + i * p_ent_size);
diff --git a/tests/t0280-gpt-corrupt.sh b/tests/t0280-gpt-corrupt.sh
new file mode 100755
index 0000000..89ab818
--- /dev/null
+++ b/tests/t0280-gpt-corrupt.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+test_description="corrupt a GPT table; ensure parted takes notice"
+
+peek()
+{
+ case $# in 2) ;; *) echo "usage: peek FILE 0_BASED_OFFSET" >&2; exit 1;; esac
+ case $2 in *[^0-9]*) echo "peek: invalid offset: $2"; exit 1 ;; esac
+ dd if="$1" bs=1 skip="$2" count=1
+}
+
+poke()
+{
+ case $# in 3) ;; *) echo "usage: poke FILE 0_BASED_OFFSET BYTE" >&2; exit 1;;
+ esac
+ case $2 in *[^0-9]*) echo "poke: invalid offset: $2"; exit 1 ;; esac
+ case $3 in ?) ;; *) echo "poke: invalid byte: '$3'"; exit 1 ;; esac
+ printf %s "$3" | dd of="$1" bs=1 seek="$2" count=1 conv=notrunc
+}
+
+: ${srcdir=.}
+. $srcdir/test-lib.sh
+
+dev=loop-file
+
+ss=$sector_size_
+n_sectors=200
+
+test_expect_success \
+ "setup: create zeroed device" \
+ 'dd if=/dev/null of=$dev bs=$ss seek=$n_sectors'
+
+test_expect_success \
+ 'create gpt label' \
+ 'parted -s $dev mklabel gpt > empty 2>&1'
+test_expect_success 'expect no output' 'compare /dev/null empty'
+
+test_expect_success \
+ 'print the empty table' \
+ 'parted -m -s $dev unit s print > t 2>&1 &&
+ sed 's,.*/$dev:,$dev:,' t > out'
+
+test_expect_success \
+ 'check for expected output' \
+ 'printf "BYT;\n$dev:${n_sectors}s:file:$sector_size_:$sector_size_:gpt:;\n"\
+ > exp &&
+ compare exp out'
+
+test_expect_success \
+ 'create a partition' \
+ 'parted -s $dev mkpart sw linux-swap 60s 100s > empty 2>&1'
+test_expect_success 'expect no output' 'compare /dev/null empty'
+
+# We're going to change the name of the first partition,
+# thus invalidating the PartitionEntryArrayCRC32 checksum.
+
+# byte 56 of the partition entry is the first byte of its 72-byte name field
+pte_offset=$(expr $ss \* 2 + 56)
+
+test_expect_success \
+ 'get the first byte of the name' \
+ 'pte_byte=$(peek $dev $pte_offset)'
+
+test x"$pte_byte" = xA && new_byte=B || new_byte=A
+
+test_expect_success \
+ 'Replace with a different byte' \
+ 'poke $dev $pte_offset "$new_byte"'
+
+test_expect_success \
+ 'try to print the table' \
+ 'parted -s $dev print > err 2>&1;
+ test $? = 1'
+
+test_expect_success \
+ 'check for expected diagnostic' \
+ 'echo "Error: partition table array CRC mismatch" > exp &&
+ compare exp err'
+
+test_done
--
1.6.5.1.258.g5b20
More information about the parted-devel
mailing list