Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sbin/fdisk Fix intuit_translated_geometry() calculation.



details:   https://anonhg.NetBSD.org/src/rev/ec40e6809525
branches:  trunk
changeset: 569884:ec40e6809525
user:      dsl <dsl%NetBSD.org@localhost>
date:      Sun Sep 12 07:46:24 2004 +0000

description:
Fix intuit_translated_geometry() calculation.
>From Izumi Tsutsui in PR bin/26917

diffstat:

 sbin/fdisk/fdisk.c |  120 +++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 94 insertions(+), 26 deletions(-)

diffs (168 lines):

diff -r f271a033006c -r ec40e6809525 sbin/fdisk/fdisk.c
--- a/sbin/fdisk/fdisk.c        Sun Sep 12 04:51:32 2004 +0000
+++ b/sbin/fdisk/fdisk.c        Sun Sep 12 07:46:24 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fdisk.c,v 1.81 2004/07/30 23:42:29 dbj Exp $ */
+/*     $NetBSD: fdisk.c,v 1.82 2004/09/12 07:46:24 dsl Exp $ */
 
 /*
  * Mach Operating System
@@ -35,7 +35,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: fdisk.c,v 1.81 2004/07/30 23:42:29 dbj Exp $");
+__RCSID("$NetBSD: fdisk.c,v 1.82 2004/09/12 07:46:24 dsl Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -1380,10 +1380,10 @@
        for (i = 0; i < MBR_PART_COUNT * 2 - 1; i++) {
                if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
                        continue;
+               a1 -= s1;
                for (j = i + 1; j < MBR_PART_COUNT * 2; j++) {
                        if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
                                continue;
-                       a1 -= s1;
                        a2 -= s2;
                        num = (uint64_t)h1 * a2 - (uint64_t)h2 * a1;
                        denom = (uint64_t)c2 * a1 - (uint64_t)c1 * a2;
@@ -2288,10 +2288,62 @@
        return (0);
 }
 
+#ifdef BOOTSEL
+/*
+ * Rather unfortunately the bootsel 'magic' number is at the end of the
+ * the structure, and there is no checksum.  So when other operating
+ * systems install mbr code by only writing the length of their code they
+ * can overwrite part of the structure but keeping the magic number intact.
+ * This code attempts to empirically detect this problem.
+ */
+static int
+validate_bootsel(struct mbr_bootsel *mbs)
+{
+       uint key = mbs->mbrbs_defkey;
+       uint tmo;
+       int i;
+
+       if (v_flag)
+               return 0;
+
+       /*
+        * Check default key is sane
+        * - this is the most likely field to be stuffed
+        * 12 disks and 12 bootable partitions seems enough!
+        * (the keymap decode starts falling apart at that point)
+        */
+       if (key != 0 && !(key == SCAN_ENTER
+           || (key >= SCAN_1 && key < SCAN_1 + 12)
+           || (key >= SCAN_F1 && key < SCAN_F1 + 12)))
+               return 1;
+
+       /* Checking the flags will lead to breakage... */
+
+       /* Timeout value is expecyed to be a multiple of a second */
+       tmo = htole16(mbs->mbrbs_timeo);
+       if (tmo != 0 && tmo != 0xffff && tmo != (10 * tmo + 9) / 182 * 182 / 10)
+               return 2;
+
+       /* Check the menu strings are printable */
+       /* Unfortunately they aren't zero filled... */
+       for (i = 0; i < sizeof(mbs->mbrbs_nametab); i++) {
+               int c = (uint8_t)mbs->mbrbs_nametab[0][i];
+               if (c == 0 || isprint(c))
+                       continue;
+               return 3;
+       }
+
+       return 0;
+}
+#endif
+
 int
 read_s0(daddr_t offset, struct mbr_sector *boot)
 {
        const char *tabletype = offset ? "extended" : "primary";
+#ifdef BOOTSEL
+       static int reported;
+#endif
 
        if (read_disk(offset, boot) == -1) {
                warn("Can't read %s partition table", tabletype);
@@ -2301,35 +2353,51 @@
                warnx("%s partition table invalid, "
                    "no magic in sector %"PRIdaddr, tabletype, offset);
                return -1;
+
        }
 #ifdef BOOTSEL
-       if (le16toh(boot->mbr_bootsel_magic) == MBR_MAGIC) {
-                               /* mbr_bootsel in old location */
+       if (le16toh(boot->mbr_bootsel_magic) == MBR_BS_MAGIC) {
+               /* mbr_bootsel in new location */
+               if (validate_bootsel(&boot->mbr_bootsel)) {
+                       warnx("removing corrupt bootsel information");
+                       boot->mbr_bootsel_magic = 0;
+               }
+               return 0;
+       }
+       if (le16toh(boot->mbr_bootsel_magic) != MBR_MAGIC)
+               return 0;
+
+       /* mbr_bootsel in old location */
+       if (!reported)
                warnx("%s partition table: using old-style bootsel information",
                    tabletype);
-               memmove((u_int8_t *)boot + MBR_BS_OFFSET,
-                       (u_int8_t *)boot + MBR_BS_OFFSET + 4,
-                       sizeof(struct mbr_bootsel));
-               if ( ! (boot->mbr_bootsel.mbrbs_flags & MBR_BS_NEWMBR)) {
-                               /* old style default key */
-                       int id;
-                               /* F1..F4 => ptn 0..3, F5+ => disk 0+ */
-                       id = boot->mbr_bootsel.mbrbs_defkey;
-                       id -= SCAN_F1;
-                       if (id >= MBR_PART_COUNT)
-                               id -= MBR_PART_COUNT; /* Use number of disk */
-                       else if (mboot.mbr_parts[id].mbrp_type != 0)
-                               id = le32toh(boot->mbr_parts[id].mbrp_start);
-                       else
-                               id = DEFAULT_ACTIVE;
-                       boot->mbr_bootsel.mbrbs_defkey = id;
-               }
-               boot->mbr_bootsel_magic = htole16(MBR_BS_MAGIC);
-                       /* highlight that new bootsel code is necessar */
-               boot->mbr_bootsel.mbrbs_flags &= ~ MBR_BS_NEWMBR;
+       reported = 1;
+       if (validate_bootsel((void *)((uint8_t *)boot + MBR_BS_OFFSET + 4))) {
+               warnx("%s bootsel information corrupt - ignoring", tabletype);
+               return 0;
        }
+       memmove((u_int8_t *)boot + MBR_BS_OFFSET,
+               (u_int8_t *)boot + MBR_BS_OFFSET + 4,
+               sizeof(struct mbr_bootsel));
+       if ( ! (boot->mbr_bootsel.mbrbs_flags & MBR_BS_NEWMBR)) {
+                       /* old style default key */
+               int id;
+                       /* F1..F4 => ptn 0..3, F5+ => disk 0+ */
+               id = boot->mbr_bootsel.mbrbs_defkey;
+               id -= SCAN_F1;
+               if (id >= MBR_PART_COUNT)
+                       id -= MBR_PART_COUNT; /* Use number of disk */
+               else if (mboot.mbr_parts[id].mbrp_type != 0)
+                       id = le32toh(boot->mbr_parts[id].mbrp_start);
+               else
+                       id = DEFAULT_ACTIVE;
+               boot->mbr_bootsel.mbrbs_defkey = id;
+       }
+       boot->mbr_bootsel_magic = htole16(MBR_BS_MAGIC);
+               /* highlight that new bootsel code is necessary */
+       boot->mbr_bootsel.mbrbs_flags &= ~MBR_BS_NEWMBR;
 #endif /* BOOTSEL */
-       return (0);
+       return 0;
 }
 
 int



Home | Main Index | Thread Index | Old Index