diff options
author | 2015-02-10 01:20:10 +0000 | |
---|---|---|
committer | 2015-02-10 01:20:10 +0000 | |
commit | 3f4f9081e007d0dc1cda81e6543566635d3ffac7 (patch) | |
tree | 9a2c429c1c220c0188444cf0c89a291b132892a9 | |
parent | Pass SOCK_NONBLOCK | SOCK_CLOEXEC to some more sockets. We never want to (diff) | |
download | wireguard-openbsd-3f4f9081e007d0dc1cda81e6543566635d3ffac7.tar.xz wireguard-openbsd-3f4f9081e007d0dc1cda81e6543566635d3ffac7.zip |
If 'write' is issued after a 'reinit' command, and the MBR to be
written does not contain an EFI partition, zap any GPT signature
found on the 2nd (LBA 1) and last sectors on the disk. The install
script uses this sequence.
This is a temporary workaround until more GPT support is imported
post-5.7.
Should fix at least some machines who insist on using the GPT even
after we have overritten the 'protective' MBR.
ok deraadt@ tedu@ beck@ millert@
-rw-r--r-- | sbin/fdisk/cmd.c | 12 | ||||
-rw-r--r-- | sbin/fdisk/mbr.c | 152 | ||||
-rw-r--r-- | sbin/fdisk/mbr.h | 5 |
3 files changed, 119 insertions, 50 deletions
diff --git a/sbin/fdisk/cmd.c b/sbin/fdisk/cmd.c index 038c70085c9..e9083b11215 100644 --- a/sbin/fdisk/cmd.c +++ b/sbin/fdisk/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.72 2015/02/09 04:27:15 krw Exp $ */ +/* $OpenBSD: cmd.c,v 1.73 2015/02/10 01:20:10 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -43,6 +43,8 @@ #include "user.h" #include "cmd.h" +int reinited; + int Xreinit(char *args, struct disk *disk, struct mbr *mbr, struct mbr *tt, int offset) @@ -54,6 +56,7 @@ Xreinit(char *args, struct disk *disk, struct mbr *mbr, struct mbr *tt, MBR_parse(disk, &dos_mbr, mbr->offset, mbr->reloffset, mbr); MBR_init(disk, mbr); + reinited = 1; /* Tell em we did something */ printf("In memory copy is initialized to:\n"); @@ -305,11 +308,16 @@ Xwrite(char *args, struct disk *disk, struct mbr *mbr, struct mbr *tt, errno = saved_errno; return (CMD_CONT); } - close(fd); + + /* Make sure GPT doesn't get in the way. */ + if (reinited) + MBR_zapgpt(fd, &dos_mbr, disk->size - 1); /* Refresh in memory copy to reflect what was just written. */ MBR_parse(disk, &dos_mbr, mbr->offset, mbr->reloffset, mbr); + close(fd); + return (CMD_CLEAN); } diff --git a/sbin/fdisk/mbr.c b/sbin/fdisk/mbr.c index 95d4ec104a0..dbd31482a7d 100644 --- a/sbin/fdisk/mbr.c +++ b/sbin/fdisk/mbr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mbr.c,v 1.42 2015/01/16 06:39:57 deraadt Exp $ */ +/* $OpenBSD: mbr.c,v 1.43 2015/02/10 01:20:10 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -179,79 +179,37 @@ MBR_print(struct mbr *mbr, char *units) int MBR_read(int fd, off_t where, struct dos_mbr *dos_mbr) { - const int secsize = unit_types[SECTORS].conversion; - ssize_t len; - off_t off; char *secbuf; - where *= secsize; - off = lseek(fd, where, SEEK_SET); - if (off != where) - return (-1); - - secbuf = calloc(1, secsize); + secbuf = MBR_readsector(fd, where); if (secbuf == NULL) return (-1); - len = read(fd, secbuf, secsize); memcpy(dos_mbr, secbuf, sizeof(*dos_mbr)); free(secbuf); - if (len == -1) - return (-1); - if (len < sizeof(*dos_mbr)) { - /* short read */ - errno = EIO; - return (-1); - } - return (0); } int MBR_write(int fd, off_t where, struct dos_mbr *dos_mbr) { - const int secsize = unit_types[SECTORS].conversion; - ssize_t len; - off_t off; char *secbuf; - /* Read the sector we want to store the MBR in. */ - where *= secsize; - off = lseek(fd, where, SEEK_SET); - if (off != where) - return (-1); - - secbuf = calloc(1, secsize); + secbuf = MBR_readsector(fd, where); if (secbuf == NULL) return (-1); - len = read(fd, secbuf, secsize); - if (len == -1 || len != secsize) - goto done; - /* * Place the new MBR at the start of the sector and * write the sector back to "disk". */ memcpy(secbuf, dos_mbr, sizeof(*dos_mbr)); - off = lseek(fd, where, SEEK_SET); - if (off == where) - len = write(fd, secbuf, secsize); - else - len = -1; + MBR_writesector(fd, secbuf, where); + ioctl(fd, DIOCRLDINFO, 0); -done: free(secbuf); - if (len == -1) - return (-1); - if (len != secsize) { - /* short read or write */ - errno = EIO; - return (-1); - } - ioctl(fd, DIOCRLDINFO, 0); return (0); } @@ -278,3 +236,103 @@ MBR_pcopy(struct disk *disk, struct mbr *mbr) for (i = 0; i < NDOSPART; i++) PRT_parse(disk, &dos_parts[i], 0, 0, &mbr->part[i]); } + +/* + * Read the sector at 'where' into a sector sized buf and return the latter. + */ +char * +MBR_readsector(int fd, off_t where) +{ + char *secbuf; + const int secsize = unit_types[SECTORS].conversion; + ssize_t len; + off_t off; + + where *= secsize; + off = lseek(fd, where, SEEK_SET); + if (off != where) + return (NULL); + + secbuf = calloc(1, secsize); + if (secbuf == NULL) + return (NULL); + + len = read(fd, secbuf, secsize); + if (len == -1 || len != secsize) { + free(secbuf); + return (NULL); + } + + return (secbuf); +} + +/* + * Write the sector sized 'secbuf' to the sector at 'where'. + */ +int +MBR_writesector(int fd, char *secbuf, off_t where) +{ + const int secsize = unit_types[SECTORS].conversion; + ssize_t len; + off_t off; + + len = -1; + + where *= secsize; + off = lseek(fd, where, SEEK_SET); + if (off == where) + len = write(fd, secbuf, secsize); + + if (len == -1 || len != secsize) { + /* short read or write */ + errno = EIO; + return (-1); + } + + return (0); +} + +/* + * If *dos_mbr has a 0xee or 0xef partition, nothing needs to happen. If no + * such partition is present but the first or last sector on the disk has a + * GPT, zero the GPT to ensure the MBR takes priority and fewer BIOSes get + * confused. + */ +void +MBR_zapgpt(int fd, struct dos_mbr *dos_mbr, uint64_t lastsec) +{ + const int secsize = unit_types[SECTORS].conversion; + struct dos_partition dos_parts[NDOSPART]; + char *secbuf; + uint64_t sig; + int i; + + memcpy(dos_parts, dos_mbr->dmbr_parts, sizeof(dos_parts)); + + for (i = 0; i < NDOSPART; i++) + if ((dos_parts[i].dp_typ == DOSPTYP_EFI) || + (dos_parts[i].dp_typ == DOSPTYP_EFISYS)) + return; + + secbuf = MBR_readsector(fd, GPTSECTOR); + if (secbuf == NULL) + return; + + memcpy(&sig, secbuf, sizeof(sig)); + if (sig == GPTSIGNATURE) { + memset(secbuf, 0, sizeof(sig)); + MBR_writesector(fd, secbuf, GPTSECTOR); + } + free(secbuf); + + secbuf = MBR_readsector(fd, lastsec); + if (secbuf == NULL) + return; + + memcpy(&sig, secbuf, sizeof(sig)); + if (sig == GPTSIGNATURE) { + memset(secbuf, 0, sizeof(sig)); + MBR_writesector(fd, secbuf, lastsec); + } + free(secbuf); +} diff --git a/sbin/fdisk/mbr.h b/sbin/fdisk/mbr.h index d01e1f9a7c3..0c49b56fed4 100644 --- a/sbin/fdisk/mbr.h +++ b/sbin/fdisk/mbr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mbr.h,v 1.17 2014/03/23 13:56:24 krw Exp $ */ +/* $OpenBSD: mbr.h,v 1.18 2015/02/10 01:20:10 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -44,5 +44,8 @@ void MBR_init(struct disk *, struct mbr *); int MBR_read(int, off_t, struct dos_mbr *); int MBR_write(int, off_t, struct dos_mbr *); void MBR_pcopy(struct disk *, struct mbr *); +char *MBR_readsector(int, off_t); +int MBR_writesector(int, char *, off_t); +void MBR_zapgpt(int, struct dos_mbr *, uint64_t); #endif /* _MBR_H */ |