Fix range check bugs
This is a patch hunting for fuzzing failures and adding
appropriate range checks.
Change-Id: Ieae02b7e461b9a6c5e25de6c663a768f7a0d5e10
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/sections/cper-section-ia32x64.c b/sections/cper-section-ia32x64.c
index f217612..bf7f565 100644
--- a/sections/cper-section-ia32x64.c
+++ b/sections/cper-section-ia32x64.c
@@ -21,7 +21,8 @@
cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check);
json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check);
json_object *cper_ia32x64_processor_context_info_to_ir(
- EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos);
+ EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos,
+ UINT32 *remaining_size);
json_object *
cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers);
json_object *
@@ -43,10 +44,15 @@
//////////////////
//Converts the IA32/x64 error section described in the given descriptor into intermediate format.
-json_object *cper_section_ia32x64_to_ir(const void *section)
+json_object *cper_section_ia32x64_to_ir(const UINT8 *section, UINT32 size)
{
+ if (size < sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)) {
+ return NULL;
+ }
EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record =
(EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section;
+ UINT32 remaining_size =
+ size - sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD);
json_object *record_ir = json_object_new_object();
//Validation bits.
@@ -89,16 +95,34 @@
EFI_IA32_X64_PROCESS_ERROR_INFO *current_error_info =
(EFI_IA32_X64_PROCESS_ERROR_INFO *)(record + 1);
json_object *error_info_array = json_object_new_array();
+ if (remaining_size < (processor_error_info_num *
+ sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO))) {
+ json_object_put(error_info_array);
+ json_object_put(record_ir);
+ printf("Invalid CPER file: Invalid processor error info num.\n");
+ return NULL;
+ }
+
for (int i = 0; i < processor_error_info_num; i++) {
json_object_array_add(error_info_array,
cper_ia32x64_processor_error_info_to_ir(
current_error_info));
current_error_info++;
}
+ remaining_size -= processor_error_info_num *
+ sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO);
+
json_object_object_add(record_ir, "processorErrorInfo",
error_info_array);
//Processor context information, of the amount described above.
+ if (remaining_size < (processor_context_info_num *
+ sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO))) {
+ json_object_put(error_info_array);
+ json_object_put(record_ir);
+ printf("Invalid CPER file: Invalid processor context info num.\n");
+ return NULL;
+ }
EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *current_context_info =
(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)current_error_info;
void *cur_pos = (void *)current_context_info;
@@ -106,11 +130,14 @@
for (int i = 0; i < processor_context_info_num; i++) {
json_object_array_add(context_info_array,
cper_ia32x64_processor_context_info_to_ir(
- current_context_info, &cur_pos));
+ current_context_info, &cur_pos,
+ &remaining_size));
current_context_info =
(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)cur_pos;
+
//The context array is a non-fixed size, pointer is shifted within the above function.
}
+
json_object_object_add(record_ir, "processorContextInfo",
context_info_array);
@@ -424,13 +451,18 @@
//Converts a single IA32/x64 processor context info entry into JSON IR format.
json_object *cper_ia32x64_processor_context_info_to_ir(
- EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos)
+ EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos,
+ UINT32 *remaining_size)
{
+ if (*remaining_size < sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO)) {
+ return NULL;
+ }
+ *remaining_size -= sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO);
json_object *context_info_ir = json_object_new_object();
//Register context type.
json_object *context_type = integer_to_readable_pair(
- context_info->RegisterType, 8,
+ context_info->RegisterType, IA32X64_REGISTER_CONTEXT_TYPES_SIZE,
IA32X64_REGISTER_CONTEXT_TYPES_KEYS,
IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)");
json_object_object_add(context_info_ir, "registerContextType",
@@ -449,21 +481,34 @@
//Register array.
json_object *register_array = NULL;
if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
+ if (*remaining_size < sizeof(EFI_CONTEXT_IA32_REGISTER_STATE)) {
+ json_object_put(context_info_ir);
+ return NULL;
+ }
EFI_CONTEXT_IA32_REGISTER_STATE *register_state =
(EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1);
register_array =
cper_ia32x64_register_32bit_to_ir(register_state);
*cur_pos = (void *)(register_state + 1);
+ *remaining_size -= sizeof(EFI_CONTEXT_IA32_REGISTER_STATE);
} else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) {
+ if (*remaining_size < sizeof(EFI_CONTEXT_X64_REGISTER_STATE)) {
+ json_object_put(context_info_ir);
+ return NULL;
+ }
EFI_CONTEXT_X64_REGISTER_STATE *register_state =
(EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1);
register_array =
cper_ia32x64_register_64bit_to_ir(register_state);
*cur_pos = (void *)(register_state + 1);
+ *remaining_size -= sizeof(EFI_CONTEXT_X64_REGISTER_STATE);
} else {
//No parseable data, just dump as base64 and shift the head to the next item.
*cur_pos = (void *)(context_info + 1);
-
+ if (*remaining_size < context_info->ArraySize) {
+ json_object_put(context_info_ir);
+ return NULL;
+ }
int32_t encoded_len = 0;
char *encoded = base64_encode((UINT8 *)*cur_pos,
context_info->ArraySize,
@@ -480,6 +525,7 @@
*cur_pos =
(void *)(((char *)*cur_pos) + context_info->ArraySize);
+ *remaining_size -= context_info->ArraySize;
}
json_object_object_add(context_info_ir, "registerArray",
register_array);