diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2015-09-13 12:53:09 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2015-09-13 12:53:09 +0000 |
commit | 4148b2cfdde7ec43766c662153854adb1e16a3b3 (patch) | |
tree | d38879ede29d2752a04cfa108f1a066159c58fa9 /sys | |
parent | fd2af42f47b733056e17c4f7a49fead4b756e6f3 (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.c | 102 | ||||
-rw-r--r-- | sys/sys/disklabel.h | 6 |
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); |