This is just a stop-gap fix. >From 33fbfd9f1cd09c96e0e04a6723fe6f7bc9a33f9e Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyer...@redhat.com> Date: Wed, 14 Oct 2009 20:50:39 +0200 Subject: [PATCH] gpt: verify CRC32 of partition table entry array, too
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 _______________________________________________ parted-devel mailing list parted-devel@lists.alioth.debian.org http://lists.alioth.debian.org/mailman/listinfo/parted-devel