diff --git a/httpboot.c b/httpboot.c index b34dd49c2..ac9ea25c5 100644 --- a/httpboot.c +++ b/httpboot.c @@ -719,18 +719,20 @@ http_fetch (EFI_HANDLE image, EFI_HANDLE device, } EFI_STATUS -httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) +httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size, + CHAR8 *name) { EFI_STATUS efi_status; EFI_HANDLE nic; - CHAR8 next_loader[sizeof DEFAULT_LOADER_CHAR]; + CHAR8 *next_loader; CHAR8 *next_uri = NULL; CHAR8 *hostname = NULL; if (!uri) return EFI_NOT_READY; - translate_slashes(next_loader, DEFAULT_LOADER_CHAR); + next_loader = (CHAR8 *)AllocatePool((strlen(name) + 1) * sizeof (CHAR8)); + translate_slashes(next_loader, name); /* Create the URI for the next loader based on the original URI */ efi_status = generate_next_uri(uri, next_loader, &next_uri); diff --git a/include/httpboot.h b/include/httpboot.h index ea9c57fed..119c546d0 100644 --- a/include/httpboot.h +++ b/include/httpboot.h @@ -12,6 +12,6 @@ extern BOOLEAN find_httpboot(EFI_HANDLE device); extern EFI_STATUS httpboot_fetch_buffer(EFI_HANDLE image, VOID **buffer, - UINT64 *buf_size); + UINT64 *buf_size, CHAR8 *name); #endif /* SHIM_HTTPBOOT_H */ diff --git a/include/netboot.h b/include/netboot.h index 98b174a34..a7bf6cd8f 100644 --- a/include/netboot.h +++ b/include/netboot.h @@ -5,7 +5,7 @@ extern BOOLEAN findNetboot(EFI_HANDLE image_handle); -extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle); +extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle, CHAR8 *name); extern EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz); diff --git a/netboot.c b/netboot.c index 832deecd0..d8b109355 100644 --- a/netboot.c +++ b/netboot.c @@ -160,25 +160,30 @@ static CHAR8 *str2ip6(CHAR8 *str) return (CHAR8 *)ip; } -static BOOLEAN extract_tftp_info(CHAR8 *url) +static BOOLEAN extract_tftp_info(CHAR8 *url, CHAR8 *name) { CHAR8 *start, *end; CHAR8 ip6str[40]; CHAR8 ip6inv[16]; - CHAR8 template[sizeof DEFAULT_LOADER_CHAR]; + int template_len = 0; + CHAR8 *template; - translate_slashes(template, DEFAULT_LOADER_CHAR); + while (name[template_len++] != '\0'); + template = (CHAR8 *)AllocatePool((template_len + 1) * sizeof (CHAR8)); + translate_slashes(template, name); // to check against str2ip6() errors memset(ip6inv, 0, sizeof(ip6inv)); if (strncmp((const char *)url, (const char *)"tftp://", 7)) { console_print(L"URLS MUST START WITH tftp://\n"); + FreePool(template); return FALSE; } start = url + 7; if (*start != '[') { console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); + FreePool(template); return FALSE; } @@ -188,22 +193,28 @@ static BOOLEAN extract_tftp_info(CHAR8 *url) end++; if (end - start >= (int)sizeof(ip6str)) { console_print(L"TFTP URL includes malformed IPv6 address\n"); + FreePool(template); return FALSE; } } if (*end == '\0') { console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); + FreePool(template); return FALSE; } memset(ip6str, 0, sizeof(ip6str)); memcpy(ip6str, start, end - start); end++; memcpy(&tftp_addr.v6, str2ip6(ip6str), 16); - if (memcmp(&tftp_addr.v6, ip6inv, sizeof(ip6inv)) == 0) + if (memcmp(&tftp_addr.v6, ip6inv, sizeof(ip6inv)) == 0) { + FreePool(template); return FALSE; + } full_path = AllocateZeroPool(strlen(end)+strlen(template)+1); - if (!full_path) + if (!full_path) { + FreePool(template); return FALSE; + } memcpy(full_path, end, strlen(end)); end = (CHAR8 *)strrchr((char *)full_path, '/'); if (!end) @@ -211,10 +222,11 @@ static BOOLEAN extract_tftp_info(CHAR8 *url) memcpy(end, template, strlen(template)); end[strlen(template)] = '\0'; + FreePool(template); return TRUE; } -static EFI_STATUS parseDhcp6() +static EFI_STATUS parseDhcp6(CHAR8 *name) { EFI_PXE_BASE_CODE_DHCPV6_PACKET *packet = (EFI_PXE_BASE_CODE_DHCPV6_PACKET *)&pxe->Mode->DhcpAck.Raw; CHAR8 *bootfile_url; @@ -222,7 +234,7 @@ static EFI_STATUS parseDhcp6() bootfile_url = get_v6_bootfile_url(packet); if (!bootfile_url) return EFI_NOT_FOUND; - if (extract_tftp_info(bootfile_url) == FALSE) { + if (extract_tftp_info(bootfile_url, name) == FALSE) { FreePool(bootfile_url); return EFI_NOT_FOUND; } @@ -230,14 +242,16 @@ static EFI_STATUS parseDhcp6() return EFI_SUCCESS; } -static EFI_STATUS parseDhcp4() +static EFI_STATUS parseDhcp4(CHAR8 *name) { - CHAR8 template[sizeof DEFAULT_LOADER_CHAR]; - INTN template_len; + CHAR8 *template; + INTN template_len = 0; UINTN template_ofs = 0; EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4; - translate_slashes(template, DEFAULT_LOADER_CHAR); + while (name[template_len++] != '\0'); + template = (CHAR8 *)AllocatePool((template_len + 1) * sizeof (CHAR8)); + translate_slashes(template, name); template_len = strlen(template) + 1; if(pxe->Mode->ProxyOfferReceived) { @@ -270,8 +284,10 @@ static EFI_STATUS parseDhcp4() full_path = AllocateZeroPool(dir_len + template_len); - if (!full_path) + if (!full_path) { + FreePool(template); return EFI_OUT_OF_RESOURCES; + } if (dir_len > 0) { strncpy(full_path, (CHAR8 *)dir, dir_len); @@ -292,10 +308,11 @@ static EFI_STATUS parseDhcp4() strcat(full_path, template + template_ofs); memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4); + FreePool(template); return EFI_SUCCESS; } -EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED) +EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED, CHAR8 *netbootname) { EFI_STATUS efi_status; @@ -310,9 +327,9 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED) * if its ipv4 or ipv6 */ if (pxe->Mode->UsingIpv6){ - efi_status = parseDhcp6(); + efi_status = parseDhcp6(netbootname); } else - efi_status = parseDhcp4(); + efi_status = parseDhcp4(netbootname); return efi_status; } @@ -324,7 +341,7 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle UNUSED, VOID **buffer, UINT BOOLEAN nobuffer = FALSE; UINTN blksz = 512; - console_print(L"Fetching Netboot Image\n"); + console_print(L"Fetching Netboot Image %a\n", full_path); if (*buffer == NULL) { *buffer = AllocatePool(4096 * 1024); if (!*buffer) diff --git a/shim.c b/shim.c index 3854fbde9..fd196cd99 100644 --- a/shim.c +++ b/shim.c @@ -1070,6 +1070,23 @@ restore_loaded_image(VOID) CopyMem(shim_li, &shim_li_bak, sizeof(shim_li_bak)); } +/* If gets used on static data it probably needs boundary checking */ +void +str16_to_str8(CHAR16 *str16, CHAR8 **str8) +{ + int i = 0; + + while (str16[i++] != '\0'); + *str8 = (CHAR8 *)AllocatePool((i + 1) * sizeof (CHAR8)); + + i = 0; + while (str16[i] != '\0') { + (*str8)[i] = (CHAR8)str16[i]; + i++; + } + (*str8)[i] = '\0'; +} + /* * Load and run an EFI executable */ @@ -1079,6 +1096,7 @@ EFI_STATUS read_image(EFI_HANDLE image_handle, CHAR16 *ImagePath, EFI_STATUS efi_status; void *sourcebuffer = NULL; UINT64 sourcesize = 0; + CHAR8 *netbootname; /* * We need to refer to the loaded image protocol on the running @@ -1102,11 +1120,13 @@ EFI_STATUS read_image(EFI_HANDLE image_handle, CHAR16 *ImagePath, } if (findNetboot(shim_li->DeviceHandle)) { - efi_status = parseNetbootinfo(image_handle); + str16_to_str8(ImagePath, &netbootname); + efi_status = parseNetbootinfo(image_handle, netbootname); if (EFI_ERROR(efi_status)) { perror(L"Netboot parsing failed: %r\n", efi_status); return EFI_PROTOCOL_ERROR; } + FreePool(netbootname); efi_status = FetchNetbootimage(image_handle, &sourcebuffer, &sourcesize); if (EFI_ERROR(efi_status)) { @@ -1117,12 +1137,14 @@ EFI_STATUS read_image(EFI_HANDLE image_handle, CHAR16 *ImagePath, *data = sourcebuffer; *datasize = sourcesize; } else if (find_httpboot(shim_li->DeviceHandle)) { + str16_to_str8(ImagePath, &netbootname); efi_status = httpboot_fetch_buffer (image_handle, &sourcebuffer, - &sourcesize); + &sourcesize, + netbootname); if (EFI_ERROR(efi_status)) { - perror(L"Unable to fetch HTTP image: %r\n", - efi_status); + perror(L"Unable to fetch HTTP image %a: %r\n", + netbootname, efi_status); return efi_status; } *data = sourcebuffer; @@ -1566,7 +1588,8 @@ load_unbundled_trust(EFI_HANDLE image_handle) efi_status = gBS->HandleProtocol(device, &EFI_SIMPLE_FILE_SYSTEM_GUID, (void **)&drive); if (EFI_ERROR(efi_status)) { - perror(L"Failed to find fs: %r\n", efi_status); + dprint(L"Failed to find fs on local drive (netboot?): %r \n", + efi_status); goto done; }