Skip to content

Commit

Permalink
netboot read_image() should not hardcode DEFAULT_LOADER
Browse files Browse the repository at this point in the history
The netboot path up until now hardcodes DEFAULT_LOADER as
the only possible filename to load. This is pretty limiting
and needs to be fixed.

Signed-off-by: Jan Setje-Eilers <[email protected]>
  • Loading branch information
jsetje authored and vathpela committed Jan 22, 2024
1 parent 6f395c2 commit a23e2f0
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 26 deletions.
8 changes: 5 additions & 3 deletions httpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion include/httpboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
2 changes: 1 addition & 1 deletion include/netboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
49 changes: 33 additions & 16 deletions netboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -188,56 +193,65 @@ 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)
end = (CHAR8 *)full_path;
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;

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;
}
FreePool(bootfile_url);
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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}

Expand All @@ -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)
Expand Down
33 changes: 28 additions & 5 deletions shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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
Expand All @@ -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)) {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit a23e2f0

Please sign in to comment.