r2309 - in trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian: . patches patches/series
Christoph Hellwig
hch-guest@costa.debian.org
Sun, 16 Jan 2005 14:59:05 +0100
Author: hch-guest
Date: 2005-01-16 14:59:04 +0100 (Sun, 16 Jan 2005)
New Revision: 2309
Added:
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/fs-partitions-efi-update.dpatch
Modified:
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13
Log:
* Backport EFI partition support fixes from 2.6.10. Patch supplied by Tore
Anderson <tore@debian.org> (Christoph Hellwig) (closes: #281905).
Modified: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog 2005-01-16 11:27:01 UTC (rev 2308)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog 2005-01-16 13:59:04 UTC (rev 2309)
@@ -20,6 +20,9 @@
is used (Andres Salomon).
* Apply patch to fix compat cmsg_len checks (Christoph Hellwig).
+
+ * Backport EFI partition support fixes from 2.6.10. Patch supplied by Tore
+ Anderson <tore@debian.org> (Christoph Hellwig) (closes: #281905).
-- Norbert Tretkowski <nobse@debian.org> Thu, 13 Jan 2005 17:23:35 +0100
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/fs-partitions-efi-update.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/fs-partitions-efi-update.dpatch 2005-01-16 11:27:01 UTC (rev 2308)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/fs-partitions-efi-update.dpatch 2005-01-16 13:59:04 UTC (rev 2309)
@@ -0,0 +1,447 @@
+#! /bin/sh -e
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: EFI GPT: reduce alternate header probing
+## DP: Patch author: Matt Domsch <Matt_Domsch@dell.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2004/11/09 17:07:52-08:00 Matt_Domsch@dell.com
+# [PATCH] EFI GPT: reduce alternate header probing
+#
+# EFI partitioning scheme was reading the last reported sector of the
+# block device to look for the alternate GPT header, before it had
+# confirmed that it should. This causes problems for devices with the
+# following problems: a) those who misreport their size (typically
+# off-by-one), and b) those who fail when asked to read a block
+# outside their range.
+#
+# This patch moves the test for the Protective Master Boot Record (PMBR)
+# ahead of the tests for the Primary and Alternate GPT headers. If the
+# PMBR is not valid, the disk is assumed to not be a GPT disk. This can
+# be overridden with the 'gpt' kernel command line option. If the
+# Primary GPT header is not valid, the Alternate GPT header is not
+# probed automatically unless the 'gpt' kernel command line option is
+# passed. If the both the PMBR and Primary GPT header are valid, then
+# the Alternate GPT header at the end of the disk is probed.
+#
+# Also re-enables CONFIG_EFI_PARTITION for all architectures.
+#
+# Signed-off-by: Matt Domsch <Matt_Domsch@dell.com>
+# Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+#
+# fs/partitions/efi.c
+# 2004/11/09 12:43:34-08:00 Matt_Domsch@dell.com +129 -129
+# EFI GPT: reduce alternate header probing
+#
+diff -Nru a/fs/partitions/efi.c b/fs/partitions/efi.c
+--- a/fs/partitions/efi.c 2005-01-13 14:43:37 -08:00
++++ b/fs/partitions/efi.c 2005-01-13 14:43:37 -08:00
+@@ -3,7 +3,7 @@
+ * Per Intel EFI Specification v1.02
+ * http://developer.intel.com/technology/efi/efi.htm
+ * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
+- * Copyright 2000,2001,2002 Dell Inc.
++ * Copyright 2000,2001,2002,2004 Dell 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
+@@ -23,6 +23,11 @@
+ * TODO:
+ *
+ * Changelog:
++ * Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com>
++ * - test for valid PMBR and valid PGPT before ever reading
++ * AGPT, allow override with 'gpt' kernel command line option.
++ * - check for first/last_usable_lba outside of size of disk
++ *
+ * Tue Mar 26 2002 Matt Domsch <Matt_Domsch@dell.com>
+ * - Ported to 2.5.7-pre1 and 2.5.7-dj2
+ * - Applied patch to avoid fault in alternate header handling
+@@ -131,32 +136,6 @@
+ }
+
+ /**
+- * is_pmbr_valid(): test Protective MBR for validity
+- * @mbr: pointer to a legacy mbr structure
+- *
+- * Description: Returns 1 if PMBR is valid, 0 otherwise.
+- * Validity depends on two things:
+- * 1) MSDOS signature is in the last two bytes of the MBR
+- * 2) One partition of type 0xEE is found
+- */
+-static int
+-is_pmbr_valid(legacy_mbr *mbr)
+-{
+- int i, found = 0, signature = 0;
+- if (!mbr)
+- return 0;
+- signature = (le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
+- for (i = 0; signature && i < 4; i++) {
+- if (mbr->partition_record[i].sys_ind ==
+- EFI_PMBR_OSTYPE_EFI_GPT) {
+- found = 1;
+- break;
+- }
+- }
+- return (signature && found);
+-}
+-
+-/**
+ * last_lba(): return number of last logical block of device
+ * @bdev: block device
+ *
+@@ -168,7 +147,40 @@
+ static u64
+ last_lba(struct block_device *bdev)
+ {
+- return (bdev->bd_inode->i_size >> 9) - 1;
++ if (!bdev || !bdev->bd_inode)
++ return 0;
++ return (bdev->bd_inode->i_size >> 9) - 1ULL;
++}
++
++static inline int
++pmbr_part_valid(struct partition *part, u64 lastlba)
++{
++ if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
++ le32_to_cpu(part->start_sect) == 1UL)
++ return 1;
++ return 0;
++}
++
++/**
++ * is_pmbr_valid(): test Protective MBR for validity
++ * @mbr: pointer to a legacy mbr structure
++ * @lastlba: last_lba for the whole device
++ *
++ * Description: Returns 1 if PMBR is valid, 0 otherwise.
++ * Validity depends on two things:
++ * 1) MSDOS signature is in the last two bytes of the MBR
++ * 2) One partition of type 0xEE is found
++ */
++static int
++is_pmbr_valid(legacy_mbr *mbr, u64 lastlba)
++{
++ int i;
++ if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
++ return 0;
++ for (i = 0; i < 4; i++)
++ if (pmbr_part_valid(&mbr->partition_record[i], lastlba))
++ return 1;
++ return 0;
+ }
+
+ /**
+@@ -186,8 +198,8 @@
+ {
+ size_t totalreadcount = 0;
+
+- if (!bdev || !buffer)
+- return 0;
++ if (!bdev || !buffer || lba > last_lba(bdev))
++ return 0;
+
+ while (count) {
+ int copied = 512;
+@@ -206,7 +218,6 @@
+ return totalreadcount;
+ }
+
+-
+ /**
+ * alloc_read_gpt_entries(): reads partition entries from disk
+ * @bdev
+@@ -289,6 +300,7 @@
+ gpt_header **gpt, gpt_entry **ptes)
+ {
+ u32 crc, origcrc;
++ u64 lastlba;
+
+ if (!bdev || !gpt || !ptes)
+ return 0;
+@@ -301,9 +313,7 @@
+ "%lld != %lld\n",
+ (unsigned long long)le64_to_cpu((*gpt)->signature),
+ (unsigned long long)GPT_HEADER_SIGNATURE);
+- kfree(*gpt);
+- *gpt = NULL;
+- return 0;
++ goto fail;
+ }
+
+ /* Check the GUID Partition Table CRC */
+@@ -315,9 +325,7 @@
+ Dprintk
+ ("GUID Partition Table Header CRC is wrong: %x != %x\n",
+ crc, origcrc);
+- kfree(*gpt);
+- *gpt = NULL;
+- return 0;
++ goto fail;
+ }
+ (*gpt)->header_crc32 = cpu_to_le32(origcrc);
+
+@@ -327,16 +335,28 @@
+ Dprintk("GPT my_lba incorrect: %lld != %lld\n",
+ (unsigned long long)le64_to_cpu((*gpt)->my_lba),
+ (unsigned long long)lba);
+- kfree(*gpt);
+- *gpt = NULL;
+- return 0;
++ goto fail;
+ }
+
+- if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt))) {
+- kfree(*gpt);
+- *gpt = NULL;
+- return 0;
++ /* Check the first_usable_lba and last_usable_lba are
++ * within the disk.
++ */
++ lastlba = last_lba(bdev);
++ if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
++ Dprintk("GPT: first_usable_lba incorrect: %lld > %lld\n",
++ (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
++ (unsigned long long)lastlba);
++ goto fail;
+ }
++ if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) {
++ Dprintk("GPT: last_usable_lba incorrect: %lld > %lld\n",
++ (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
++ (unsigned long long)lastlba);
++ goto fail;
++ }
++
++ if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt)))
++ goto fail;
+
+ /* Check the GUID Partition Entry Array CRC */
+ crc = efi_crc32((const unsigned char *) (*ptes),
+@@ -345,15 +365,36 @@
+
+ if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
+ Dprintk("GUID Partitition Entry Array CRC check failed.\n");
+- kfree(*gpt);
+- *gpt = NULL;
+- kfree(*ptes);
+- *ptes = NULL;
+- return 0;
++ goto fail_ptes;
+ }
+
+ /* We're done, all's well */
+ return 1;
++
++ fail_ptes:
++ kfree(*ptes);
++ *ptes = NULL;
++ fail:
++ kfree(*gpt);
++ *gpt = NULL;
++ return 0;
++}
++
++/**
++ * is_pte_valid() - tests one PTE for validity
++ * @pte is the pte to check
++ * @lastlba is last lba of the disk
++ *
++ * Description: returns 1 if valid, 0 on error.
++ */
++static inline int
++is_pte_valid(const gpt_entry *pte, const u64 lastlba)
++{
++ if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
++ le64_to_cpu(pte->starting_lba) > lastlba ||
++ le64_to_cpu(pte->ending_lba) > lastlba)
++ return 0;
++ return 1;
+ }
+
+ /**
+@@ -464,8 +505,13 @@
+ * @ptes is a PTEs ptr, filled on return.
+ * Description: Returns 1 if valid, 0 on error.
+ * If valid, returns pointers to newly allocated GPT header and PTEs.
+- * Validity depends on finding either the Primary GPT header and PTEs valid,
+- * or the Alternate GPT header and PTEs valid, and the PMBR valid.
++ * Validity depends on PMBR being valid (or being overridden by the
++ * 'gpt' kernel command line option) and finding either the Primary
++ * GPT header and PTEs valid, or the Alternate GPT header and PTEs
++ * valid. If the Primary GPT header is not valid, the Alternate GPT header
++ * is not checked unless the 'gpt' kernel command line option is passed.
++ * This protects against devices which misreport their size, and forces
++ * the user to decide to use the Alternate GPT.
+ */
+ static int
+ find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes)
+@@ -479,70 +525,43 @@
+ return 0;
+
+ lastlba = last_lba(bdev);
++ if (!force_gpt) {
++ /* This will be added to the EFI Spec. per Intel after v1.02. */
++ legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
++ if (legacymbr) {
++ memset(legacymbr, 0, sizeof (*legacymbr));
++ read_lba(bdev, 0, (u8 *) legacymbr,
++ sizeof (*legacymbr));
++ good_pmbr = is_pmbr_valid(legacymbr, lastlba);
++ kfree(legacymbr);
++ legacymbr=NULL;
++ }
++ if (!good_pmbr)
++ goto fail;
++ }
++
+ good_pgpt = is_gpt_valid(bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
+ &pgpt, &pptes);
+- if (good_pgpt) {
++ if (good_pgpt)
+ good_agpt = is_gpt_valid(bdev,
+- le64_to_cpu(pgpt->alternate_lba),
++ le64_to_cpu(pgpt->alternate_lba),
+ &agpt, &aptes);
+- if (!good_agpt) {
+- good_agpt = is_gpt_valid(bdev, lastlba,
+- &agpt, &aptes);
+- }
+- }
+- else {
++ if (!good_agpt && force_gpt)
+ good_agpt = is_gpt_valid(bdev, lastlba,
+ &agpt, &aptes);
+- }
+
+ /* The obviously unsuccessful case */
+- if (!good_pgpt && !good_agpt) {
+- goto fail;
+- }
+-
+- /* This will be added to the EFI Spec. per Intel after v1.02. */
+- legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
+- if (legacymbr) {
+- memset(legacymbr, 0, sizeof (*legacymbr));
+- read_lba(bdev, 0, (u8 *) legacymbr,
+- sizeof (*legacymbr));
+- good_pmbr = is_pmbr_valid(legacymbr);
+- kfree(legacymbr);
+- legacymbr=NULL;
+- }
+-
+- /* Failure due to bad PMBR */
+- if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
+- printk(KERN_WARNING
+- " Warning: Disk has a valid GPT signature "
+- "but invalid PMBR.\n");
+- printk(KERN_WARNING
+- " Assuming this disk is *not* a GPT disk anymore.\n");
+- printk(KERN_WARNING
+- " Use gpt kernel option to override. "
+- "Use GNU Parted to correct disk.\n");
++ if (!good_pgpt && !good_agpt)
+ goto fail;
+- }
+-
+- /* Would fail due to bad PMBR, but force GPT anyhow */
+- if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
+- printk(KERN_WARNING
+- " Warning: Disk has a valid GPT signature but "
+- "invalid PMBR.\n");
+- printk(KERN_WARNING
+- " Use GNU Parted to correct disk.\n");
+- printk(KERN_WARNING
+- " gpt option taken, disk treated as GPT.\n");
+- }
+
+ compare_gpts(pgpt, agpt, lastlba);
+
+ /* The good cases */
+- if (good_pgpt && (good_pmbr || force_gpt)) {
++ if (good_pgpt) {
+ *gpt = pgpt;
+ *ptes = pptes;
+- if (agpt) { kfree(agpt); agpt = NULL; }
+- if (aptes) { kfree(aptes); aptes = NULL; }
++ kfree(agpt);
++ kfree(aptes);
+ if (!good_agpt) {
+ printk(KERN_WARNING
+ "Alternate GPT is invalid, "
+@@ -550,21 +569,21 @@
+ }
+ return 1;
+ }
+- else if (good_agpt && (good_pmbr || force_gpt)) {
++ else if (good_agpt) {
+ *gpt = agpt;
+ *ptes = aptes;
+- if (pgpt) { kfree(pgpt); pgpt = NULL; }
+- if (pptes) { kfree(pptes); pptes = NULL; }
++ kfree(pgpt);
++ kfree(pptes);
+ printk(KERN_WARNING
+ "Primary GPT is invalid, using alternate GPT.\n");
+ return 1;
+ }
+
+ fail:
+- if (pgpt) { kfree(pgpt); pgpt=NULL; }
+- if (agpt) { kfree(agpt); agpt=NULL; }
+- if (pptes) { kfree(pptes); pptes=NULL; }
+- if (aptes) { kfree(aptes); aptes=NULL; }
++ kfree(pgpt);
++ kfree(agpt);
++ kfree(pptes);
++ kfree(aptes);
+ *gpt = NULL;
+ *ptes = NULL;
+ return 0;
+@@ -606,15 +625,15 @@
+ Dprintk("GUID Partition Table is valid! Yea!\n");
+
+ for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
+- if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID))
++ if (!is_pte_valid(&ptes[i], last_lba(bdev)))
+ continue;
+
+ put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba),
+ (le64_to_cpu(ptes[i].ending_lba) -
+ le64_to_cpu(ptes[i].starting_lba) +
+- 1));
++ 1ULL));
+
+- /* If there's this is a RAID volume, tell md */
++ /* If this is a RAID volume, tell md */
+ if (!efi_guidcmp(ptes[i].partition_type_guid,
+ PARTITION_LINUX_RAID_GUID))
+ state->parts[i+1].flags = 1;
+@@ -624,22 +643,3 @@
+ printk("\n");
+ return 1;
+ }
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only. This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-indent-level: 4
+- * c-brace-imaginary-offset: 0
+- * c-brace-offset: -4
+- * c-argdecl-indent: 4
+- * c-label-offset: -4
+- * c-continued-statement-offset: 4
+- * c-continued-brace-offset: 0
+- * indent-tabs-mode: nil
+- * tab-width: 8
+- * End:
+- */
Modified: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13 2005-01-16 11:27:01 UTC (rev 2308)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13 2005-01-16 13:59:04 UTC (rev 2309)
@@ -4,3 +4,4 @@
+ 034-stack_resize_exploit.dpatch
+ 035-do_brk_security_fixes-2.dpatch
+ cmsg-compat-signedness-fix-fix.dpatch
++ fs-partitions-efi-update.dpatch