arrfab / rpms / shim

Forked from rpms/shim 4 years ago
Clone

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

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