|
|
00e791 |
From c6bedd5b83529925c3ec08f96a3bf61c81bff0ae Mon Sep 17 00:00:00 2001
|
|
|
00e791 |
From: Laszlo Ersek <lersek@redhat.com>
|
|
|
00e791 |
Date: Tue, 28 Jan 2020 23:33:46 +0100
|
|
|
00e791 |
Subject: [PATCH 44/62] translate_slashes(): don't write to string literals
|
|
|
00e791 |
|
|
|
00e791 |
Currently, all three invocations of the translate_slashes() function may
|
|
|
00e791 |
lead to writes to the string literal that is #defined with the
|
|
|
00e791 |
DEFAULT_LOADER_CHAR macro. According to ISO C99 6.4.5p6, this is undefined
|
|
|
00e791 |
behavior ("If the program attempts to modify such an array, the behavior
|
|
|
00e791 |
is undefined").
|
|
|
00e791 |
|
|
|
00e791 |
This bug crashes shim on e.g. the 64-bit ArmVirtQemu platform ("Data
|
|
|
00e791 |
abort: Permission fault"), where the platform firmware maps the .text
|
|
|
00e791 |
section (which contains the string literal) read-only.
|
|
|
00e791 |
|
|
|
00e791 |
Modify translate_slashes() so that it copies and translates characters
|
|
|
00e791 |
from an input array of "char" to an output array of "CHAR8".
|
|
|
00e791 |
|
|
|
00e791 |
While at it, fix another bug. Before this patch, if translate_slashes()
|
|
|
00e791 |
ever encountered a double backslash (translating it to a single forward
|
|
|
00e791 |
slash), then the output would end up shorter than the input. However, the
|
|
|
00e791 |
output was not NUL-terminated in-place, therefore the original string
|
|
|
00e791 |
length (and according trailing garbage) would be preserved. After this
|
|
|
00e791 |
patch, the NUL-termination on contraction is automatic, as the output
|
|
|
00e791 |
array's contents are indeterminate when entering the function, and so we
|
|
|
00e791 |
must NUL-terminate it anyway.
|
|
|
00e791 |
|
|
|
00e791 |
Fixes: 8e9124227d18475d3bc634c33518963fc8db7c98
|
|
|
00e791 |
Fixes: e62b69a5b0b87c6df7a4fc23906134945309e927
|
|
|
00e791 |
Fixes: 3d79bcb2651b9eae809b975b3e03e2f96c067072
|
|
|
00e791 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1795654
|
|
|
00e791 |
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
00e791 |
Upstream-commit-id: 9813e8bc8b3
|
|
|
00e791 |
---
|
|
|
00e791 |
httpboot.c | 4 ++--
|
|
|
00e791 |
netboot.c | 16 +++++++++++-----
|
|
|
00e791 |
include/str.h | 14 ++++++++------
|
|
|
00e791 |
3 files changed, 21 insertions(+), 13 deletions(-)
|
|
|
00e791 |
|
|
|
00e791 |
diff --git a/httpboot.c b/httpboot.c
|
|
|
00e791 |
index 3622e85867c..2d27e8ed993 100644
|
|
|
00e791 |
--- a/httpboot.c
|
|
|
00e791 |
+++ b/httpboot.c
|
|
|
00e791 |
@@ -743,14 +743,14 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
|
|
|
00e791 |
{
|
|
|
00e791 |
EFI_STATUS efi_status;
|
|
|
00e791 |
EFI_HANDLE nic;
|
|
|
00e791 |
- CHAR8 *next_loader = NULL;
|
|
|
00e791 |
+ CHAR8 next_loader[sizeof DEFAULT_LOADER_CHAR];
|
|
|
00e791 |
CHAR8 *next_uri = NULL;
|
|
|
00e791 |
CHAR8 *hostname = NULL;
|
|
|
00e791 |
|
|
|
00e791 |
if (!uri)
|
|
|
00e791 |
return EFI_NOT_READY;
|
|
|
00e791 |
|
|
|
00e791 |
- next_loader = translate_slashes(DEFAULT_LOADER_CHAR);
|
|
|
00e791 |
+ translate_slashes(next_loader, DEFAULT_LOADER_CHAR);
|
|
|
00e791 |
|
|
|
00e791 |
/* Create the URI for the next loader based on the original URI */
|
|
|
00e791 |
efi_status = generate_next_uri(uri, next_loader, &next_uri);
|
|
|
00e791 |
diff --git a/netboot.c b/netboot.c
|
|
|
00e791 |
index 58babfb4d2e..4922ef284b1 100644
|
|
|
00e791 |
--- a/netboot.c
|
|
|
00e791 |
+++ b/netboot.c
|
|
|
00e791 |
@@ -189,7 +189,9 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
|
|
|
00e791 |
CHAR8 *start, *end;
|
|
|
00e791 |
CHAR8 ip6str[40];
|
|
|
00e791 |
CHAR8 ip6inv[16];
|
|
|
00e791 |
- CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR);
|
|
|
00e791 |
+ CHAR8 template[sizeof DEFAULT_LOADER_CHAR];
|
|
|
00e791 |
+
|
|
|
00e791 |
+ translate_slashes(template, DEFAULT_LOADER_CHAR);
|
|
|
00e791 |
|
|
|
00e791 |
// to check against str2ip6() errors
|
|
|
00e791 |
memset(ip6inv, 0, sizeof(ip6inv));
|
|
|
00e791 |
@@ -254,10 +256,14 @@ static EFI_STATUS parseDhcp6()
|
|
|
00e791 |
|
|
|
00e791 |
static EFI_STATUS parseDhcp4()
|
|
|
00e791 |
{
|
|
|
00e791 |
- CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR);
|
|
|
00e791 |
- INTN template_len = strlen(template) + 1;
|
|
|
00e791 |
+ CHAR8 template[sizeof DEFAULT_LOADER_CHAR];
|
|
|
00e791 |
+ INTN template_len;
|
|
|
00e791 |
+ UINTN template_ofs = 0;
|
|
|
00e791 |
EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4;
|
|
|
00e791 |
|
|
|
00e791 |
+ translate_slashes(template, DEFAULT_LOADER_CHAR);
|
|
|
00e791 |
+ template_len = strlen(template) + 1;
|
|
|
00e791 |
+
|
|
|
00e791 |
if(pxe->Mode->ProxyOfferReceived) {
|
|
|
00e791 |
/*
|
|
|
00e791 |
* Proxy should not have precedence. Check if DhcpAck
|
|
|
00e791 |
@@ -288,8 +294,8 @@ static EFI_STATUS parseDhcp4()
|
|
|
00e791 |
full_path[dir_len-1] = '\0';
|
|
|
00e791 |
}
|
|
|
00e791 |
if (dir_len == 0 && dir[0] != '/' && template[0] == '/')
|
|
|
00e791 |
- template++;
|
|
|
00e791 |
- strcata(full_path, template);
|
|
|
00e791 |
+ template_ofs++;
|
|
|
00e791 |
+ strcata(full_path, template + template_ofs);
|
|
|
00e791 |
memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4);
|
|
|
00e791 |
|
|
|
00e791 |
return EFI_SUCCESS;
|
|
|
00e791 |
diff --git a/include/str.h b/include/str.h
|
|
|
00e791 |
index 9a748366bd1..f73c6212cd9 100644
|
|
|
00e791 |
--- a/include/str.h
|
|
|
00e791 |
+++ b/include/str.h
|
|
|
00e791 |
@@ -45,21 +45,23 @@ strcata(CHAR8 *dest, const CHAR8 *src)
|
|
|
00e791 |
static inline
|
|
|
00e791 |
__attribute__((unused))
|
|
|
00e791 |
CHAR8 *
|
|
|
00e791 |
-translate_slashes(char *str)
|
|
|
00e791 |
+translate_slashes(CHAR8 *out, const char *str)
|
|
|
00e791 |
{
|
|
|
00e791 |
int i;
|
|
|
00e791 |
int j;
|
|
|
00e791 |
- if (str == NULL)
|
|
|
00e791 |
- return (CHAR8 *)str;
|
|
|
00e791 |
+ if (str == NULL || out == NULL)
|
|
|
00e791 |
+ return NULL;
|
|
|
00e791 |
|
|
|
00e791 |
for (i = 0, j = 0; str[i] != '\0'; i++, j++) {
|
|
|
00e791 |
if (str[i] == '\\') {
|
|
|
00e791 |
- str[j] = '/';
|
|
|
00e791 |
+ out[j] = '/';
|
|
|
00e791 |
if (str[i+1] == '\\')
|
|
|
00e791 |
i++;
|
|
|
00e791 |
- }
|
|
|
00e791 |
+ } else
|
|
|
00e791 |
+ out[j] = str[i];
|
|
|
00e791 |
}
|
|
|
00e791 |
- return (CHAR8 *)str;
|
|
|
00e791 |
+ out[j] = '\0';
|
|
|
00e791 |
+ return out;
|
|
|
00e791 |
}
|
|
|
00e791 |
|
|
|
00e791 |
#endif /* SHIM_STR_H */
|
|
|
00e791 |
--
|
|
|
00e791 |
2.26.2
|
|
|
00e791 |
|