diff --git a/src/creator.c b/src/creator.c index e62188ce..f780a80b 100644 --- a/src/creator.c +++ b/src/creator.c @@ -221,12 +221,7 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size, debug("EFIBOOT_ABBREV_EDD10"); if (options & EFIBOOT_ABBREV_EDD10) { - va_list aq; - va_copy(aq, ap); - - dev->edd10_devicenum = va_arg(aq, uint32_t); - - va_end(aq); + dev->edd10_devicenum = va_arg(ap, uint32_t); } if (!(options & (EFIBOOT_ABBREV_FILE|EFIBOOT_ABBREV_HD)) diff --git a/src/dp-acpi.c b/src/dp-acpi.c index c9d15862..ff79fd4a 100644 --- a/src/dp-acpi.c +++ b/src/dp-acpi.c @@ -101,10 +101,17 @@ _format_acpi_dn(unsigned char *buf, size_t size, const_efidp dp) return off; } else if (dp->subtype != EFIDP_ACPI_HID_EX && dp->subtype != EFIDP_ACPI_HID) { + ssize_t limit = efidp_node_size(dp); + debug("DP subtype %d, formatting as ACPI Path", dp->subtype); + if (SUB(limit, 4, &limit) || + DIV(limit, 2, &limit) || + limit < 0) { + efi_error("bad DP node size"); + return -1; + } format(buf, size, off, "AcpiPath", "AcpiPath(%d,", dp->subtype); - format_hex(buf, size, off, "AcpiPath", (uint8_t *)dp+4, - (efidp_node_size(dp)-4) / 2); + format_hex(buf, size, off, "AcpiPath", (uint8_t *)dp+4, limit); format(buf, size, off, "AcpiPath", ")"); return off; } else if (dp->subtype == EFIDP_ACPI_HID_EX) { diff --git a/src/dp-hw.c b/src/dp-hw.c index e09984db..e94cf7bc 100644 --- a/src/dp-hw.c +++ b/src/dp-hw.c @@ -58,13 +58,20 @@ _format_hw_dn(unsigned char *buf, size_t size, const_efidp dp) format(buf, size, off, "BMC", "BMC(%d,0x%"PRIx64")", dp->bmc.interface_type, dp->bmc.base_addr); break; - default: + default: { + ssize_t sz = efidp_node_size(dp); + + if (SUB(sz, 4, &sz) || + sz < 0) { + efi_error("bad DP node size"); + return -1; + } format(buf, size, off, "Hardware", "HardwarePath(%d,", dp->subtype); - format_hex(buf, size, off, "Hardware", (uint8_t *)dp+4, - efidp_node_size(dp)-4); + format_hex(buf, size, off, "Hardware", (uint8_t *)dp+4, sz); format(buf, size, off, "Hardware", ")"); break; + } } return off; } diff --git a/src/dp-media.c b/src/dp-media.c index ffda361b..f8b1c490 100644 --- a/src/dp-media.c +++ b/src/dp-media.c @@ -58,8 +58,14 @@ _format_media_dn(unsigned char *buf, size_t size, const_efidp dp) format_vendor(buf, size, off, "VenMedia", dp); break; case EFIDP_MEDIA_FILE: { - size_t limit = (efidp_node_size(dp) - - offsetof(efidp_file, name)) / 2; + ssize_t limit = efidp_node_size(dp); + size_t offset = offsetof(efidp_usb_wwid, serial_number); + if (limit < 0 || + SUB(limit, offset, &limit) || + DIV(limit, 2, &limit)) { + efi_error("bad DP node size"); + return -1; + } format_ucs2(buf, size, off, "File", dp->file.name, limit); break; } @@ -126,12 +132,19 @@ _format_media_dn(unsigned char *buf, size_t size, const_efidp dp) format(buf, size, off, "Ramdisk", ")"); break; } - default: + default: { + ssize_t limit = efidp_node_size(dp); + if (limit < 0 || + SUB(limit, 4, &limit) || + DIV(limit, 2, &limit)) { + efi_error("bad DP node size"); + return -1; + } format(buf, size, off, "Media", "MediaPath(%d,", dp->subtype); - format_hex(buf, size, off, "Media", (uint8_t *)dp+4, - (efidp_node_size(dp)-4) / 2); + format_hex(buf, size, off, "Media", (uint8_t *)dp+4, limit); format(buf,size,off, "Media",")"); break; + } } return off; } diff --git a/src/dp-message.c b/src/dp-message.c index bad4a3cb..464fe0f9 100644 --- a/src/dp-message.c +++ b/src/dp-message.c @@ -504,9 +504,14 @@ _format_message_dn(unsigned char *buf, size_t size, const_efidp dp) format_helper(format_usb_class, buf, size, off, "UsbClass", dp); break; case EFIDP_MSG_USB_WWID: { - size_t limit = (efidp_node_size(dp) - - offsetof(efidp_usb_wwid, serial_number)) - / 2; + ssize_t limit = efidp_node_size(dp); + size_t offset = offsetof(efidp_usb_wwid, serial_number); + if (limit <= 0 || + SUB(limit, offset, &limit) || + DIV(limit, 2, &limit)) { + efi_error("bad DP node size"); + return -1; + } format(buf, size, off, "UsbWwid", "UsbWwid(%"PRIx16",%"PRIx16",%d,", dp->usb_wwid.vendor_id, dp->usb_wwid.product_id, @@ -633,12 +638,18 @@ _format_message_dn(unsigned char *buf, size_t size, const_efidp dp) format_guid(buf, size, off, "NVDIMM", &dp->nvdimm.uuid); format(buf, size, off, "NVDIMM", ")"); break; - default: + default: { + ssize_t limit = efidp_node_size(dp); + if (SUB(limit, 4, &limit) || + limit < 0) { + efi_error("bad DP node size"); + return -1; + } format(buf, size, off, "Msg", "Msg(%d,", dp->subtype); - format_hex(buf, size, off, "Msg", (uint8_t *)dp+4, - efidp_node_size(dp)-4); + format_hex(buf, size, off, "Msg", (uint8_t *)dp+4, limit); format(buf, size, off, "Msg", ")"); break; + } } return off; } diff --git a/src/dp.c b/src/dp.c index 0dc7492a..83acf9ee 100644 --- a/src/dp.c +++ b/src/dp.c @@ -298,6 +298,12 @@ efidp_format_device_path(unsigned char *buf, size_t size, const_efidp dp, memset(buf, 0, size); while (limit) { + ssize_t sz = efidp_node_size(dp); + if (SUB(sz, 4, &sz) || + sz < 0) { + efi_error("bad DP node size"); + return -1; + } if (limit >= 0 && (limit < 4 || efidp_node_size(dp) > limit)) { if (off) return off; @@ -339,9 +345,9 @@ efidp_format_device_path(unsigned char *buf, size_t size, const_efidp dp, if (dp->subtype != EFIDP_BIOS_BOOT) { format(buf, size, off, "BbsPath", "BbsPath(%d,", dp->subtype); - format_hex(buf, size, off, "BbsPath", - (uint8_t *)dp+4, - efidp_node_size(dp)-4); + if (sz > 0) + format_hex(buf, size, off, "BbsPath", + (uint8_t *)dp+4, sz); format(buf, size, off, "BbsPath", ")"); break; } @@ -371,8 +377,9 @@ efidp_format_device_path(unsigned char *buf, size_t size, const_efidp dp, default: format(buf, size, off, "Path", "Path(%d,%d,", dp->type, dp->subtype); + if (sz > 0) format_hex(buf, size, off, "Path", (uint8_t *)dp + 4, - efidp_node_size(dp) - 4); + sz); format(buf, size, off, "Path", ")"); break; } diff --git a/src/dp.h b/src/dp.h index 2a7b231d..59f436a0 100644 --- a/src/dp.h +++ b/src/dp.h @@ -101,9 +101,14 @@ format_vendor_helper(unsigned char *buf, size_t size, char *label, const_efidp dp) { ssize_t off = 0; - ssize_t bytes = efidp_node_size(dp) - - sizeof (efidp_header) - - sizeof (efi_guid_t); + ssize_t bytes = efidp_node_size(dp); + + if (SUB(bytes, sizeof (efidp_header), &bytes) || + SUB(bytes, sizeof (efi_guid_t), &bytes) || + bytes < 0) { + efi_error("bad DP node size"); + return -1; + } format(buf, size, off, label, "%s(", label); format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid); diff --git a/src/safemath.h b/src/safemath.h index caa5b1cc..8d98fb61 100644 --- a/src/safemath.h +++ b/src/safemath.h @@ -32,7 +32,7 @@ #define DIV(a, b, res) ({ \ bool ret_ = true; \ if ((b) != 0) { \ - if (!is_null(res)) \ + if (!(res == NULL)) \ (*(res)) = (a) / (b); \ ret_ = false; \ } else { \ @@ -44,7 +44,7 @@ * These really just exists for chaining results easily with || in an expr */ #define MOD(a, b, res) ({ \ - if (!is_null(res)) \ + if (!(res == NULL)) \ (*(res)) = (a) % (b); \ false; \ })