summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2015-09-13 12:53:09 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2015-09-13 12:53:09 +0000
commit4148b2cfdde7ec43766c662153854adb1e16a3b3 (patch)
treed38879ede29d2752a04cfa108f1a066159c58fa9 /sys
parentfd2af42f47b733056e17c4f7a49fead4b756e6f3 (diff)
Rename readgptlabel() to spoofgptlabel() because that's what we
really want it to do. Handle all the actual disklabel reading in readdoslabel(). Makes the code much simpler to understand. ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/subr_disk.c102
-rw-r--r--sys/sys/disklabel.h6
2 files changed, 42 insertions, 66 deletions
diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c
index 5c029a252b6..491d557b698 100644
--- a/sys/kern/subr_disk.c
+++ b/sys/kern/subr_disk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_disk.c,v 1.214 2015/09/11 17:51:30 krw Exp $ */
+/* $OpenBSD: subr_disk.c,v 1.215 2015/09/13 12:53:08 krw Exp $ */
/* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */
/*
@@ -328,6 +328,7 @@ int
readdoslabel(struct buf *bp, void (*strat)(struct buf *),
struct disklabel *lp, daddr_t *partoffp, int spoofonly)
{
+ struct disklabel *gptlp;
u_int64_t dospartoff = 0, dospartend = DL_GETBEND(lp);
int i, ourpart = -1, wander = 1, n = 0, loop = 0, offset;
struct dos_partition dp[NDOSPART], *dp2;
@@ -370,23 +371,37 @@ readdoslabel(struct buf *bp, void (*strat)(struct buf *),
(bp->b_data[511] & 0xff);
if (mbrtest != 0x55aa)
goto notmbr;
- if (gpt_chk_mbr(dp, lp) == 0) {
- error = readgptlabel(bp, strat, lp,
- partoffp ? &dospartoff : NULL, spoofonly);
- if (error == 0) {
- if (partoffp)
- *partoffp = dospartoff;
- return (0);
- } else {
- /* Restore all potentially tweakee's */
- dospartoff = 0;
- DL_SETBSTART(lp, 0);
- DL_SETBEND(lp, DL_GETDSIZE(lp));
- goto notmbr;
+
+ if (gpt_chk_mbr(dp, lp) != 0)
+ goto notgpt;
+
+ gptlp = malloc(sizeof(struct disklabel), M_DEVBUF,
+ M_NOWAIT);
+ if (gptlp == NULL)
+ return (ENOMEM);
+ *gptlp = *lp;
+ error = spoofgptlabel(bp, strat, gptlp);
+ if (error == 0) {
+ dospartoff = DL_GETBSTART(gptlp);
+ dospartoff = DL_GETBEND(gptlp);
+ if (partoffp) {
+ if (dospartoff == 0)
+ return (ENXIO);
+ else
+ goto notfat;
}
+ *lp = *gptlp;
+ free(gptlp, M_DEVBUF,
+ sizeof(struct disklabel));
+ goto notfat;
+ } else {
+ free(gptlp, M_DEVBUF,
+ sizeof(struct disklabel));
+ goto notmbr;
}
}
+notgpt:
if (ourpart == -1) {
/* Search for our MBR partition */
for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
@@ -729,15 +744,11 @@ gpt_get_fstype(struct uuid *uuid_part)
}
/*
- * If gpt partition table requested, attempt to load it and
- * find disklabel inside a GPT partition. Return buffer
- * for use in signalling errors if requested.
- *
- * XXX: readgptlabel() is based on readdoslabel(), so they should be merged
+ * Spoof a disklabel based on the GPT information on the disk.
*/
int
-readgptlabel(struct buf *bp, void (*strat)(struct buf *),
- struct disklabel *lp, daddr_t *partoffp, int spoofonly)
+spoofgptlabel(struct buf *bp, void (*strat)(struct buf *),
+ struct disklabel *lp)
{
static const u_int8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD;
struct gpt_header gh;
@@ -747,7 +758,7 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *),
size_t gpsz;
u_int64_t ghlbaend, ghlbastart, gptpartoff, gptpartend, sector;
u_int64_t start, end;
- int i, altheader = 0, error, n, offset;
+ int i, altheader = 0, error, n;
uint32_t ghpartnum;
uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd);
@@ -760,8 +771,6 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *),
error = readdisksector(bp, strat, lp, sector);
if (error) {
DPRINTF("error reading from disk\n");
- /*wrong*/ if (partoffp)
- /*wrong*/ *partoffp = -1;
return (error);
}
@@ -797,8 +806,6 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *),
for (i = 0; i < ghpartnum / ghpartspersec; i++, sector++) {
error = readdisksector(bp, strat, lp, sector);
if (error) {
- /*wrong*/ if (partoffp)
- /*wrong*/ *partoffp = -1;
free(gp, M_DEVBUF, gpsz);
return (error);
}
@@ -838,20 +845,11 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *),
continue; /* Do *NOT* spoof OpenBSD partitions! */
}
- /*
- * In case the disklabel read below fails, we want to
- * provide a fake label in i-p.
- */
-
- /*
- * Don't set fstype/offset/size when just looking for
- * the offset of the OpenBSD partition. It would
- * invalidate the disklabel checksum!
- *
+ /*
* Don't try to spoof more than 8 partitions, i.e.
* 'i' -'p'.
*/
- if (partoffp || n >= 8)
+ if (n >= 8)
continue;
pp = &lp->d_partitions[8+n];
@@ -861,35 +859,13 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *),
DL_SETPSIZE(pp, end - start + 1);
}
- if (gptpartoff == 0)
- spoofonly = 1; /* No disklabel to read from disk. */
-
free(gp, M_DEVBUF, gpsz);
- /* record the OpenBSD partition's placement for the caller */
- if (partoffp)
- *partoffp = DL_SECTOBLK(lp, gptpartoff);
- else {
- DL_SETBSTART(lp, gptpartoff);
- DL_SETBEND(lp, (gptpartend < DL_GETDSIZE(lp)) ? gptpartend :
- DL_GETDSIZE(lp));
- }
-
- /* don't read the on-disk label if we are in spoofed-only mode */
- if (spoofonly)
- return (0);
-
- error = readdisksector(bp, strat, lp, gptpartoff +
- DL_BLKTOSEC(lp, DOS_LABELSECTOR));
- if (error)
- return (bp->b_error);
-
- offset = DL_BLKOFFSET(lp, DOS_LABELSECTOR);
- error = checkdisklabel(bp->b_data + offset, lp,
- DL_GETBSTART((struct disklabel*)(bp->b_data+offset)),
- DL_GETBEND((struct disklabel *)(bp->b_data+offset)));
+ DL_SETBSTART(lp, gptpartoff);
+ DL_SETBEND(lp, (gptpartend < DL_GETDSIZE(lp)) ? gptpartend :
+ DL_GETDSIZE(lp));
- return (error);
+ return (0);
}
/*
diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h
index 590082c9f09..4abe999456a 100644
--- a/sys/sys/disklabel.h
+++ b/sys/sys/disklabel.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: disklabel.h,v 1.68 2015/09/10 16:30:23 krw Exp $ */
+/* $OpenBSD: disklabel.h,v 1.69 2015/09/13 12:53:08 krw Exp $ */
/* $NetBSD: disklabel.h,v 1.41 1996/05/10 23:07:37 mark Exp $ */
/*
@@ -541,8 +541,8 @@ int writedisklabel(dev_t, void (*)(struct buf *), struct disklabel *);
int bounds_check_with_label(struct buf *, struct disklabel *);
int readdoslabel(struct buf *, void (*)(struct buf *),
struct disklabel *, daddr_t *, int);
-int readgptlabel(struct buf *, void (*)(struct buf *),
- struct disklabel *, daddr_t *, int);
+int spoofgptlabel(struct buf *, void (*)(struct buf *),
+ struct disklabel *);
#ifdef CD9660
int iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
struct disklabel *lp);