Blame SOURCES/0023-additional-bounds-checking-on-section-sizes.patch

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