|
|
e97c83 |
From e253c2a2c07bc526de1528ed9839b2b584025fa2 Mon Sep 17 00:00:00 2001
|
|
|
e97c83 |
From: Sebastian Krahmer <krahmer@suse.com>
|
|
|
e97c83 |
Date: Tue, 29 Jul 2014 09:55:00 +0000
|
|
|
e97c83 |
Subject: [PATCH 70/74] shim buffer overflow on ipv6 option parsing
|
|
|
e97c83 |
|
|
|
e97c83 |
---
|
|
|
e97c83 |
netboot.c | 102 ++++++++++++++++++++++++++++++++++++++------------------------
|
|
|
e97c83 |
1 file changed, 62 insertions(+), 40 deletions(-)
|
|
|
e97c83 |
|
|
|
e97c83 |
diff --git a/netboot.c b/netboot.c
|
|
|
e97c83 |
index 238937d..f884cba 100644
|
|
|
e97c83 |
--- a/netboot.c
|
|
|
e97c83 |
+++ b/netboot.c
|
|
|
e97c83 |
@@ -108,29 +108,34 @@ BOOLEAN findNetboot(EFI_HANDLE device)
|
|
|
e97c83 |
|
|
|
e97c83 |
static CHAR8 *get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt)
|
|
|
e97c83 |
{
|
|
|
e97c83 |
- void *optr;
|
|
|
e97c83 |
- EFI_DHCP6_PACKET_OPTION *option;
|
|
|
e97c83 |
- CHAR8 *url;
|
|
|
e97c83 |
- UINT32 urllen;
|
|
|
e97c83 |
+ void *optr = NULL, *end = NULL;
|
|
|
e97c83 |
+ EFI_DHCP6_PACKET_OPTION *option = NULL;
|
|
|
e97c83 |
+ CHAR8 *url = NULL;
|
|
|
e97c83 |
+ UINT32 urllen = 0;
|
|
|
e97c83 |
|
|
|
e97c83 |
optr = pkt->DhcpOptions;
|
|
|
e97c83 |
+ end = optr + sizeof(pkt->DhcpOptions);
|
|
|
e97c83 |
|
|
|
e97c83 |
- for(;;) {
|
|
|
e97c83 |
+ for (;;) {
|
|
|
e97c83 |
option = (EFI_DHCP6_PACKET_OPTION *)optr;
|
|
|
e97c83 |
|
|
|
e97c83 |
if (ntohs(option->OpCode) == 0)
|
|
|
e97c83 |
- return NULL;
|
|
|
e97c83 |
+ break;
|
|
|
e97c83 |
|
|
|
e97c83 |
if (ntohs(option->OpCode) == 59) {
|
|
|
e97c83 |
/* This is the bootfile url option */
|
|
|
e97c83 |
urllen = ntohs(option->Length);
|
|
|
e97c83 |
- url = AllocateZeroPool(urllen+1);
|
|
|
e97c83 |
+ if ((void *)(option->Data + urllen) > end)
|
|
|
e97c83 |
+ break;
|
|
|
e97c83 |
+ url = AllocateZeroPool(urllen + 1);
|
|
|
e97c83 |
if (!url)
|
|
|
e97c83 |
- return NULL;
|
|
|
e97c83 |
+ break;
|
|
|
e97c83 |
memcpy(url, option->Data, urllen);
|
|
|
e97c83 |
return url;
|
|
|
e97c83 |
}
|
|
|
e97c83 |
optr += 4 + ntohs(option->Length);
|
|
|
e97c83 |
+ if (optr + sizeof(EFI_DHCP6_PACKET_OPTION) > end)
|
|
|
e97c83 |
+ break;
|
|
|
e97c83 |
}
|
|
|
e97c83 |
|
|
|
e97c83 |
return NULL;
|
|
|
e97c83 |
@@ -156,45 +161,60 @@ static CHAR16 str2ns(CHAR8 *str)
|
|
|
e97c83 |
|
|
|
e97c83 |
static CHAR8 *str2ip6(CHAR8 *str)
|
|
|
e97c83 |
{
|
|
|
e97c83 |
- UINT8 i, j, p;
|
|
|
e97c83 |
- size_t len;
|
|
|
e97c83 |
- CHAR8 *a, *b, t;
|
|
|
e97c83 |
- static UINT16 ip[8];
|
|
|
e97c83 |
+ UINT8 i = 0, j = 0, p = 0;
|
|
|
e97c83 |
+ size_t len = 0, dotcount = 0;
|
|
|
e97c83 |
+ enum { MAX_IP6_DOTS = 7 };
|
|
|
e97c83 |
+ CHAR8 *a = NULL, *b = NULL, t = 0;
|
|
|
e97c83 |
+ static UINT16 ip[8];
|
|
|
e97c83 |
|
|
|
e97c83 |
- for(i=0; i < 8; i++) {
|
|
|
e97c83 |
- ip[i] = 0;
|
|
|
e97c83 |
- }
|
|
|
e97c83 |
- len = strlen(str);
|
|
|
e97c83 |
- a = b = str;
|
|
|
e97c83 |
- for(i=p=0; i < len; i++, b++) {
|
|
|
e97c83 |
- if (*b != ':')
|
|
|
e97c83 |
- continue;
|
|
|
e97c83 |
- *b = '\0';
|
|
|
e97c83 |
- ip[p++] = str2ns(a);
|
|
|
e97c83 |
- *b = ':';
|
|
|
e97c83 |
- a = b + 1;
|
|
|
e97c83 |
- if ( *(b+1) == ':' )
|
|
|
e97c83 |
- break;
|
|
|
e97c83 |
- }
|
|
|
e97c83 |
- a = b = (str + len);
|
|
|
e97c83 |
- for(j=len, p=7; j > i; j--, a--) {
|
|
|
e97c83 |
- if (*a != ':')
|
|
|
e97c83 |
- continue;
|
|
|
e97c83 |
- t = *b;
|
|
|
e97c83 |
- *b = '\0';
|
|
|
e97c83 |
- ip[p--] = str2ns(a+1);
|
|
|
e97c83 |
- *b = t;
|
|
|
e97c83 |
- b = a;
|
|
|
e97c83 |
- }
|
|
|
e97c83 |
- return (CHAR8 *)ip;
|
|
|
e97c83 |
+ memset(ip, 0, sizeof(ip));
|
|
|
e97c83 |
+
|
|
|
e97c83 |
+ /* Count amount of ':' to prevent overflows.
|
|
|
e97c83 |
+ * max. count = 7. Returns an invalid ip6 that
|
|
|
e97c83 |
+ * can be checked against
|
|
|
e97c83 |
+ */
|
|
|
e97c83 |
+ for (a = str; *a != 0; ++a) {
|
|
|
e97c83 |
+ if (*a == ':')
|
|
|
e97c83 |
+ ++dotcount;
|
|
|
e97c83 |
+ }
|
|
|
e97c83 |
+ if (dotcount > MAX_IP6_DOTS)
|
|
|
e97c83 |
+ return (CHAR8 *)ip;
|
|
|
e97c83 |
+
|
|
|
e97c83 |
+ len = strlen(str);
|
|
|
e97c83 |
+ a = b = str;
|
|
|
e97c83 |
+ for (i = p = 0; i < len; i++, b++) {
|
|
|
e97c83 |
+ if (*b != ':')
|
|
|
e97c83 |
+ continue;
|
|
|
e97c83 |
+ *b = '\0';
|
|
|
e97c83 |
+ ip[p++] = str2ns(a);
|
|
|
e97c83 |
+ *b = ':';
|
|
|
e97c83 |
+ a = b + 1;
|
|
|
e97c83 |
+ if (b[1] == ':' )
|
|
|
e97c83 |
+ break;
|
|
|
e97c83 |
+ }
|
|
|
e97c83 |
+ a = b = (str + len);
|
|
|
e97c83 |
+ for (j = len, p = 7; j > i; j--, a--) {
|
|
|
e97c83 |
+ if (*a != ':')
|
|
|
e97c83 |
+ continue;
|
|
|
e97c83 |
+ t = *b;
|
|
|
e97c83 |
+ *b = '\0';
|
|
|
e97c83 |
+ ip[p--] = str2ns(a+1);
|
|
|
e97c83 |
+ *b = t;
|
|
|
e97c83 |
+ b = a;
|
|
|
e97c83 |
+ }
|
|
|
e97c83 |
+ return (CHAR8 *)ip;
|
|
|
e97c83 |
}
|
|
|
e97c83 |
|
|
|
e97c83 |
static BOOLEAN extract_tftp_info(CHAR8 *url)
|
|
|
e97c83 |
{
|
|
|
e97c83 |
CHAR8 *start, *end;
|
|
|
e97c83 |
CHAR8 ip6str[40];
|
|
|
e97c83 |
+ CHAR8 ip6inv[16];
|
|
|
e97c83 |
CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR);
|
|
|
e97c83 |
|
|
|
e97c83 |
+ // to check against str2ip6() errors
|
|
|
e97c83 |
+ memset(ip6inv, 0, sizeof(ip6inv));
|
|
|
e97c83 |
+
|
|
|
e97c83 |
if (strncmp((UINT8 *)url, (UINT8 *)"tftp://", 7)) {
|
|
|
e97c83 |
Print(L"URLS MUST START WITH tftp://\n");
|
|
|
e97c83 |
return FALSE;
|
|
|
e97c83 |
@@ -209,7 +229,7 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
|
|
|
e97c83 |
end = start;
|
|
|
e97c83 |
while ((*end != '\0') && (*end != ']')) {
|
|
|
e97c83 |
end++;
|
|
|
e97c83 |
- if (end - start > 39) {
|
|
|
e97c83 |
+ if (end - start >= (int)sizeof(ip6str)) {
|
|
|
e97c83 |
Print(L"TFTP URL includes malformed IPv6 address\n");
|
|
|
e97c83 |
return FALSE;
|
|
|
e97c83 |
}
|
|
|
e97c83 |
@@ -218,10 +238,12 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
|
|
|
e97c83 |
Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
|
|
|
e97c83 |
return FALSE;
|
|
|
e97c83 |
}
|
|
|
e97c83 |
- memset(ip6str, 0, 40);
|
|
|
e97c83 |
+ memset(ip6str, 0, sizeof(ip6str));
|
|
|
e97c83 |
memcpy(ip6str, start, end - start);
|
|
|
e97c83 |
end++;
|
|
|
e97c83 |
memcpy(&tftp_addr.v6, str2ip6(ip6str), 16);
|
|
|
e97c83 |
+ if (memcmp(&tftp_addr.v6, ip6inv, sizeof(ip6inv)) == 0)
|
|
|
e97c83 |
+ return FALSE;
|
|
|
e97c83 |
full_path = AllocateZeroPool(strlen(end)+strlen(template)+1);
|
|
|
e97c83 |
if (!full_path)
|
|
|
e97c83 |
return FALSE;
|
|
|
e97c83 |
--
|
|
|
e97c83 |
1.9.3
|
|
|
e97c83 |
|