summaryrefslogtreecommitdiff
path: root/usr.sbin/installboot
diff options
context:
space:
mode:
authorkamil <kamil@NetBSD.org>2018-06-23 14:15:57 +0000
committerkamil <kamil@NetBSD.org>2018-06-23 14:15:57 +0000
commit28ac17c1ce24d059b2d6629af13e40ff7b04e299 (patch)
tree8845e5cebdf70d8f88a51168840e5b1c823cdce6 /usr.sbin/installboot
parent2c7c2df99effd7678f1929d8046e4b16e76cf3c7 (diff)
Fix integer overflow in installboot(8)
Add a sanity check of the disk_buf first three bytes. The original code on a disk with nul bytes was causing integer overflow and thus calling the memcmp(3) functin in is_zero() with enormous length. Verity that the 0th byte is JMP, 1th a signed byte >=9 to prevent overflow and 2th byte NOP. Add a comment explaining the check. Detected with MKSANITIZER and ASan.
Diffstat (limited to 'usr.sbin/installboot')
-rw-r--r--usr.sbin/installboot/arch/i386.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/usr.sbin/installboot/arch/i386.c b/usr.sbin/installboot/arch/i386.c
index a18a903900b..16ee5363016 100644
--- a/usr.sbin/installboot/arch/i386.c
+++ b/usr.sbin/installboot/arch/i386.c
@@ -1,4 +1,4 @@
-/* $NetBSD: i386.c,v 1.40 2013/06/14 03:54:43 msaitoh Exp $ */
+/* $NetBSD: i386.c,v 1.41 2018/06/23 14:15:57 kamil Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
#include <sys/cdefs.h>
#if !defined(__lint)
-__RCSID("$NetBSD: i386.c,v 1.40 2013/06/14 03:54:43 msaitoh Exp $");
+__RCSID("$NetBSD: i386.c,v 1.41 2018/06/23 14:15:57 kamil Exp $");
#endif /* !__lint */
#include <sys/param.h>
@@ -418,8 +418,19 @@ i386_setboot(ib_params *params)
return 0;
}
- /* Find size of old BPB, and copy into new bootcode */
- if (!is_zero(disk_buf.b + 3 + 8, disk_buf.b[1] - 1 - 8)) {
+ /*
+ * Find size of old BPB, and copy into new bootcode
+ *
+ * The 2nd byte (b[1]) contains jmp short relative offset.
+ * If it is zero or some invalid input that is smaller than 9,
+ * it will cause overflow and call is_zero() with enormous size.
+ * Add a paranoid check to prevent this scenario.
+ *
+ * Verify that b[0] contains JMP (0xeb) and b[2] NOP (0x90).
+ */
+ if (disk_buf.b[0] == 0xeb && disk_buf.b[1] >= 9 &&
+ disk_buf.b[2] == 0x90 &&
+ !is_zero(disk_buf.b + 3 + 8, disk_buf.b[1] - 1 - 8)) {
struct mbr_bpbFAT16 *bpb = (void *)(disk_buf.b + 3 + 8);
/* Check enough space before the FAT for the bootcode */
u = le16toh(bpb->bpbBytesPerSec)