|
|
4210fa |
From 5495694c043de510aaf8ff5dcbe17b6547794083 Mon Sep 17 00:00:00 2001
|
|
|
4210fa |
From: Kees Cook <kees@outflux.net>
|
|
|
4210fa |
Date: Mon, 3 Dec 2012 15:52:48 -0800
|
|
|
4210fa |
Subject: [PATCH 23/74] additional bounds-checking on section sizes
|
|
|
4210fa |
|
|
|
4210fa |
This adds additional bounds-checking on the section sizes. Also adds
|
|
|
4210fa |
-Wsign-compare to the Makefile and replaces some signed variables with
|
|
|
4210fa |
unsigned counteparts for robustness.
|
|
|
4210fa |
|
|
|
4210fa |
Signed-off-by: Kees Cook <kees@ubuntu.com>
|
|
|
4210fa |
---
|
|
|
4210fa |
Makefile | 3 ++-
|
|
|
4210fa |
MokManager.c | 6 ++---
|
|
|
4210fa |
PasswordCrypt.c | 4 +--
|
|
|
4210fa |
fallback.c | 4 +--
|
|
|
4210fa |
shim.c | 83 +++++++++++++++++++++++++++++++++++++++------------------
|
|
|
4210fa |
5 files changed, 66 insertions(+), 34 deletions(-)
|
|
|
4210fa |
|
|
|
4210fa |
diff --git a/Makefile b/Makefile
|
|
|
4210fa |
index e65d28d..46e5ef9 100644
|
|
|
4210fa |
--- a/Makefile
|
|
|
4210fa |
+++ b/Makefile
|
|
|
4210fa |
@@ -16,7 +16,8 @@ EFI_LDS = elf_$(ARCH)_efi.lds
|
|
|
4210fa |
|
|
|
4210fa |
DEFAULT_LOADER := \\\\grub.efi
|
|
|
4210fa |
CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
|
|
|
4210fa |
- -fshort-wchar -Wall -Werror -mno-red-zone -maccumulate-outgoing-args \
|
|
|
4210fa |
+ -fshort-wchar -Wall -Wsign-compare -Werror \
|
|
|
4210fa |
+ -mno-red-zone -maccumulate-outgoing-args \
|
|
|
4210fa |
-mno-mmx -mno-sse -fno-builtin \
|
|
|
4210fa |
"-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \
|
|
|
4210fa |
"-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \
|
|
|
4210fa |
diff --git a/MokManager.c b/MokManager.c
|
|
|
4210fa |
index f5ed379..3da61f4 100644
|
|
|
4210fa |
--- a/MokManager.c
|
|
|
4210fa |
+++ b/MokManager.c
|
|
|
4210fa |
@@ -440,7 +440,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
|
|
|
4210fa |
MokListNode *keys = NULL;
|
|
|
4210fa |
INTN key_num = 0;
|
|
|
4210fa |
CHAR16 **menu_strings;
|
|
|
4210fa |
- int i;
|
|
|
4210fa |
+ unsigned int i;
|
|
|
4210fa |
|
|
|
4210fa |
if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) +
|
|
|
4210fa |
sizeof(EFI_SIGNATURE_DATA))) {
|
|
|
4210fa |
@@ -491,7 +491,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
|
|
|
4210fa |
static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show)
|
|
|
4210fa |
{
|
|
|
4210fa |
EFI_INPUT_KEY key;
|
|
|
4210fa |
- int count = 0;
|
|
|
4210fa |
+ unsigned int count = 0;
|
|
|
4210fa |
|
|
|
4210fa |
do {
|
|
|
4210fa |
key = console_get_keystroke();
|
|
|
4210fa |
@@ -640,7 +640,7 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt,
|
|
|
4210fa |
CHAR16 password[PASSWORD_MAX];
|
|
|
4210fa |
UINT32 pw_length;
|
|
|
4210fa |
UINT8 fail_count = 0;
|
|
|
4210fa |
- int i;
|
|
|
4210fa |
+ unsigned int i;
|
|
|
4210fa |
|
|
|
4210fa |
if (pw_crypt) {
|
|
|
4210fa |
auth_hash = pw_crypt->hash;
|
|
|
4210fa |
diff --git a/PasswordCrypt.c b/PasswordCrypt.c
|
|
|
4210fa |
index 8d72a82..e0a82cf 100644
|
|
|
4210fa |
--- a/PasswordCrypt.c
|
|
|
4210fa |
+++ b/PasswordCrypt.c
|
|
|
4210fa |
@@ -154,7 +154,7 @@ static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len,
|
|
|
4210fa |
CopyMem(cp, tmp_result, cnt);
|
|
|
4210fa |
|
|
|
4210fa |
SHA256_Init(&alt_ctx);
|
|
|
4210fa |
- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
|
|
|
4210fa |
+ for (cnt = 0; cnt < 16ul + alt_result[0]; ++cnt)
|
|
|
4210fa |
SHA256_Update(&alt_ctx, salt, salt_size);
|
|
|
4210fa |
SHA256_Final(tmp_result, &alt_ctx);
|
|
|
4210fa |
|
|
|
4210fa |
@@ -242,7 +242,7 @@ static EFI_STATUS sha512_crypt (const char *key, UINT32 key_len,
|
|
|
4210fa |
CopyMem(cp, tmp_result, cnt);
|
|
|
4210fa |
|
|
|
4210fa |
SHA512_Init(&alt_ctx);
|
|
|
4210fa |
- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
|
|
|
4210fa |
+ for (cnt = 0; cnt < 16ul + alt_result[0]; ++cnt)
|
|
|
4210fa |
SHA512_Update(&alt_ctx, salt, salt_size);
|
|
|
4210fa |
SHA512_Final(tmp_result, &alt_ctx);
|
|
|
4210fa |
|
|
|
4210fa |
diff --git a/fallback.c b/fallback.c
|
|
|
4210fa |
index 44638ec..bc9a3c9 100644
|
|
|
4210fa |
--- a/fallback.c
|
|
|
4210fa |
+++ b/fallback.c
|
|
|
4210fa |
@@ -229,7 +229,7 @@ EFI_STATUS
|
|
|
4210fa |
find_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label,
|
|
|
4210fa |
CHAR16 *arguments, UINT16 *optnum)
|
|
|
4210fa |
{
|
|
|
4210fa |
- int size = sizeof(UINT32) + sizeof (UINT16) +
|
|
|
4210fa |
+ unsigned int size = sizeof(UINT32) + sizeof (UINT16) +
|
|
|
4210fa |
StrLen(label)*2 + 2 + DevicePathSize(dp) +
|
|
|
4210fa |
StrLen(arguments) * 2 + 2;
|
|
|
4210fa |
|
|
|
4210fa |
@@ -768,7 +768,7 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
|
|
|
4210fa |
if (EFI_ERROR(rc)) {
|
|
|
4210fa |
CHAR16 *dps = DevicePathToStr(first_new_option);
|
|
|
4210fa |
UINTN s = DevicePathSize(first_new_option);
|
|
|
4210fa |
- int i;
|
|
|
4210fa |
+ unsigned int i;
|
|
|
4210fa |
UINT8 *dpv = (void *)first_new_option;
|
|
|
4210fa |
Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps);
|
|
|
4210fa |
for (i = 0; i < s; i++) {
|
|
|
4210fa |
diff --git a/shim.c b/shim.c
|
|
|
4210fa |
index 0e18d38..8c583a4 100644
|
|
|
4210fa |
--- a/shim.c
|
|
|
4210fa |
+++ b/shim.c
|
|
|
4210fa |
@@ -102,7 +102,7 @@ typedef struct {
|
|
|
4210fa |
/*
|
|
|
4210fa |
* Perform basic bounds checking of the intra-image pointers
|
|
|
4210fa |
*/
|
|
|
4210fa |
-static void *ImageAddress (void *image, int size, unsigned int address)
|
|
|
4210fa |
+static void *ImageAddress (void *image, unsigned int size, unsigned int address)
|
|
|
4210fa |
{
|
|
|
4210fa |
if (address > size)
|
|
|
4210fa |
return NULL;
|
|
|
4210fa |
@@ -494,18 +494,19 @@ static BOOLEAN secure_mode (void)
|
|
|
4210fa |
* Calculate the SHA1 and SHA256 hashes of a binary
|
|
|
4210fa |
*/
|
|
|
4210fa |
|
|
|
4210fa |
-static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
+static EFI_STATUS generate_hash (char *data, int datasize_in,
|
|
|
4210fa |
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
|
|
4210fa |
UINT8 *sha256hash, UINT8 *sha1hash)
|
|
|
4210fa |
|
|
|
4210fa |
{
|
|
|
4210fa |
unsigned int sha256ctxsize, sha1ctxsize;
|
|
|
4210fa |
- unsigned int size = datasize;
|
|
|
4210fa |
+ unsigned int size = datasize_in;
|
|
|
4210fa |
void *sha256ctx = NULL, *sha1ctx = NULL;
|
|
|
4210fa |
char *hashbase;
|
|
|
4210fa |
unsigned int hashsize;
|
|
|
4210fa |
unsigned int SumOfBytesHashed, SumOfSectionBytes;
|
|
|
4210fa |
unsigned int index, pos;
|
|
|
4210fa |
+ unsigned int datasize;
|
|
|
4210fa |
EFI_IMAGE_SECTION_HEADER *Section;
|
|
|
4210fa |
EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL;
|
|
|
4210fa |
EFI_IMAGE_SECTION_HEADER *SectionCache;
|
|
|
4210fa |
@@ -517,6 +518,12 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
sha1ctxsize = Sha1GetContextSize();
|
|
|
4210fa |
sha1ctx = AllocatePool(sha1ctxsize);
|
|
|
4210fa |
|
|
|
4210fa |
+ if (datasize_in < 0) {
|
|
|
4210fa |
+ Print(L"Invalid data size\n");
|
|
|
4210fa |
+ return EFI_INVALID_PARAMETER;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ size = datasize = (unsigned int)datasize_in;
|
|
|
4210fa |
+
|
|
|
4210fa |
if (!sha256ctx || !sha1ctx) {
|
|
|
4210fa |
Print(L"Unable to allocate memory for hash context\n");
|
|
|
4210fa |
return EFI_OUT_OF_RESOURCES;
|
|
|
4210fa |
@@ -577,22 +584,29 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
SumOfBytesHashed = context->PEHdr->Pe32.OptionalHeader.SizeOfHeaders;
|
|
|
4210fa |
#endif
|
|
|
4210fa |
|
|
|
4210fa |
- Section = (EFI_IMAGE_SECTION_HEADER *) (
|
|
|
4210fa |
- (char *)context->PEHdr + sizeof (UINT32) +
|
|
|
4210fa |
- sizeof (EFI_IMAGE_FILE_HEADER) +
|
|
|
4210fa |
- context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader
|
|
|
4210fa |
- );
|
|
|
4210fa |
-
|
|
|
4210fa |
- SectionCache = Section;
|
|
|
4210fa |
-
|
|
|
4210fa |
+ /* Validate section locations and sizes */
|
|
|
4210fa |
for (index = 0, SumOfSectionBytes = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++, SectionCache++) {
|
|
|
4210fa |
- SumOfSectionBytes += SectionCache->SizeOfRawData;
|
|
|
4210fa |
- }
|
|
|
4210fa |
-
|
|
|
4210fa |
- if (SumOfSectionBytes >= datasize) {
|
|
|
4210fa |
- Print(L"Malformed binary: %x %x\n", SumOfSectionBytes, size);
|
|
|
4210fa |
- status = EFI_INVALID_PARAMETER;
|
|
|
4210fa |
- goto done;
|
|
|
4210fa |
+ EFI_IMAGE_SECTION_HEADER *SectionPtr;
|
|
|
4210fa |
+
|
|
|
4210fa |
+ /* Validate SectionPtr is within image */
|
|
|
4210fa |
+ SectionPtr = ImageAddress(data, datasize,
|
|
|
4210fa |
+ sizeof (UINT32) +
|
|
|
4210fa |
+ sizeof (EFI_IMAGE_FILE_HEADER) +
|
|
|
4210fa |
+ context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader +
|
|
|
4210fa |
+ (index * sizeof(*SectionPtr)));
|
|
|
4210fa |
+ if (!SectionPtr) {
|
|
|
4210fa |
+ Print(L"Malformed section %d\n", index);
|
|
|
4210fa |
+ status = EFI_INVALID_PARAMETER;
|
|
|
4210fa |
+ goto done;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ /* Validate section size is within image. */
|
|
|
4210fa |
+ if (SectionPtr->SizeOfRawData >
|
|
|
4210fa |
+ datasize - SumOfBytesHashed - SumOfSectionBytes) {
|
|
|
4210fa |
+ Print(L"Malformed section %d size\n", index);
|
|
|
4210fa |
+ status = EFI_INVALID_PARAMETER;
|
|
|
4210fa |
+ goto done;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ SumOfSectionBytes += SectionPtr->SizeOfRawData;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections);
|
|
|
4210fa |
@@ -602,6 +616,11 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
goto done;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
+ /* Already validated above */
|
|
|
4210fa |
+ Section = ImageAddress(data, datasize, sizeof (UINT32) +
|
|
|
4210fa |
+ sizeof (EFI_IMAGE_FILE_HEADER) +
|
|
|
4210fa |
+ context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader);
|
|
|
4210fa |
+
|
|
|
4210fa |
/* Sort the section headers */
|
|
|
4210fa |
for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) {
|
|
|
4210fa |
pos = index;
|
|
|
4210fa |
@@ -620,7 +639,6 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
continue;
|
|
|
4210fa |
}
|
|
|
4210fa |
hashbase = ImageAddress(data, size, Section->PointerToRawData);
|
|
|
4210fa |
- hashsize = (unsigned int) Section->SizeOfRawData;
|
|
|
4210fa |
|
|
|
4210fa |
if (!hashbase) {
|
|
|
4210fa |
Print(L"Malformed section header\n");
|
|
|
4210fa |
@@ -628,6 +646,15 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
goto done;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
+ /* Verify hashsize within image. */
|
|
|
4210fa |
+ if (Section->SizeOfRawData >
|
|
|
4210fa |
+ datasize - Section->PointerToRawData) {
|
|
|
4210fa |
+ Print(L"Malformed section raw size %d\n", index);
|
|
|
4210fa |
+ status = EFI_INVALID_PARAMETER;
|
|
|
4210fa |
+ goto done;
|
|
|
4210fa |
+ }
|
|
|
4210fa |
+ hashsize = (unsigned int) Section->SizeOfRawData;
|
|
|
4210fa |
+
|
|
|
4210fa |
if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
|
|
|
4210fa |
!(Sha1Update(sha1ctx, hashbase, hashsize))) {
|
|
|
4210fa |
Print(L"Unable to generate hash\n");
|
|
|
4210fa |
@@ -638,10 +665,10 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
/* Hash all remaining data */
|
|
|
4210fa |
- if (size > SumOfBytesHashed) {
|
|
|
4210fa |
+ if (datasize > SumOfBytesHashed) {
|
|
|
4210fa |
hashbase = data + SumOfBytesHashed;
|
|
|
4210fa |
hashsize = (unsigned int)(
|
|
|
4210fa |
- size -
|
|
|
4210fa |
+ datasize -
|
|
|
4210fa |
#if __LP64__
|
|
|
4210fa |
context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
|
|
|
4210fa |
#else
|
|
|
4210fa |
@@ -884,7 +911,8 @@ static EFI_STATUS read_header(void *data, unsigned int datasize,
|
|
|
4210fa |
return EFI_UNSUPPORTED;
|
|
|
4210fa |
}
|
|
|
4210fa |
|
|
|
4210fa |
- if (((UINT8 *)context->SecDir - (UINT8 *)data) > (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
|
|
4210fa |
+ if ((unsigned long)((UINT8 *)context->SecDir - (UINT8 *)data) >
|
|
|
4210fa |
+ (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
|
|
4210fa |
Print(L"Invalid image\n");
|
|
|
4210fa |
return EFI_UNSUPPORTED;
|
|
|
4210fa |
}
|
|
|
4210fa |
@@ -904,7 +932,8 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize,
|
|
|
4210fa |
{
|
|
|
4210fa |
EFI_STATUS efi_status;
|
|
|
4210fa |
char *buffer;
|
|
|
4210fa |
- int i, size;
|
|
|
4210fa |
+ int i;
|
|
|
4210fa |
+ unsigned int size;
|
|
|
4210fa |
EFI_IMAGE_SECTION_HEADER *Section;
|
|
|
4210fa |
char *base, *end;
|
|
|
4210fa |
PE_COFF_LOADER_IMAGE_CONTEXT context;
|
|
|
4210fa |
@@ -1081,7 +1110,8 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath,
|
|
|
4210fa |
{
|
|
|
4210fa |
EFI_DEVICE_PATH *devpath;
|
|
|
4210fa |
EFI_HANDLE device;
|
|
|
4210fa |
- int i, j, last = -1;
|
|
|
4210fa |
+ unsigned int i;
|
|
|
4210fa |
+ int j, last = -1;
|
|
|
4210fa |
unsigned int pathlen = 0;
|
|
|
4210fa |
EFI_STATUS efi_status = EFI_SUCCESS;
|
|
|
4210fa |
CHAR16 *bootpath;
|
|
|
4210fa |
@@ -1637,9 +1667,10 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle)
|
|
|
4210fa |
EFI_STATUS status;
|
|
|
4210fa |
EFI_LOADED_IMAGE *li;
|
|
|
4210fa |
CHAR16 *start = NULL, *c;
|
|
|
4210fa |
- int i, remaining_size = 0;
|
|
|
4210fa |
+ unsigned int i;
|
|
|
4210fa |
+ int remaining_size = 0;
|
|
|
4210fa |
CHAR16 *loader_str = NULL;
|
|
|
4210fa |
- int loader_len = 0;
|
|
|
4210fa |
+ unsigned int loader_len = 0;
|
|
|
4210fa |
|
|
|
4210fa |
second_stage = DEFAULT_LOADER;
|
|
|
4210fa |
load_options = NULL;
|
|
|
4210fa |
--
|
|
|
4210fa |
1.9.3
|
|
|
4210fa |
|