summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkrw <krw@openbsd.org>2015-02-10 01:20:10 +0000
committerkrw <krw@openbsd.org>2015-02-10 01:20:10 +0000
commit3f4f9081e007d0dc1cda81e6543566635d3ffac7 (patch)
tree9a2c429c1c220c0188444cf0c89a291b132892a9
parentPass SOCK_NONBLOCK | SOCK_CLOEXEC to some more sockets. We never want to (diff)
downloadwireguard-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.c12
-rw-r--r--sbin/fdisk/mbr.c152
-rw-r--r--sbin/fdisk/mbr.h5
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 */