From 82185a52e22179ec842d2c5fb983b307b9ebc7d2 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 27 Apr 2016 00:55:05 +0200 Subject: [PATCH] Future proofing core file format * The Haiku specific notes contain a structure size field, now. * Change the type of the count and size fields in the Haiku specific notes to uint32 also for 64 bit ELF. The size field for a note is a uint32 anyway. --- headers/os/kernel/elf.h | 36 ++++-- src/apps/debugger/elf/CoreFile.cpp | 154 ++++++++++++++++---------- src/apps/debugger/elf/CoreFile.h | 8 ++ src/system/kernel/debug/core_dump.cpp | 18 +-- 4 files changed, 141 insertions(+), 75 deletions(-) diff --git a/headers/os/kernel/elf.h b/headers/os/kernel/elf.h index f25fc8b8b1..b1ff0ca530 100644 --- a/headers/os/kernel/elf.h +++ b/headers/os/kernel/elf.h @@ -611,7 +611,7 @@ typedef struct { #define NT_IMAGES 0x696d6167 /* images */ #define NT_THREADS 0x74687264 /* threads */ -/* NT_TEAM: Elf32_Note_Team; char[] args */ +/* NT_TEAM: uint32 entrySize; Elf32_Note_Team; char[] args */ typedef struct { int32 nt_id; /* team ID */ int32 nt_uid; /* team owner ID */ @@ -620,7 +620,12 @@ typedef struct { typedef Elf32_Note_Team Elf64_Note_Team; -/* NT_AREAS: uint32 count; Elf32_Note_Area_Entry[count]; char[] names */ +/* NT_AREAS: + * uint32 count; + * uint32 entrySize; + * Elf32_Note_Area_Entry[count]; + * char[] names + */ typedef struct { int32 na_id; /* area ID */ uint32 na_lock; /* lock type (B_NO_LOCK, ...) */ @@ -630,7 +635,12 @@ typedef struct { uint32 na_ram_size; /* physical memory used */ } Elf32_Note_Area_Entry; -/* NT_AREAS: uint64 count; Elf64_Note_Area_Entry[count]; char[] names */ +/* NT_AREAS: + * uint32 count; + * uint32 entrySize; + * Elf64_Note_Area_Entry[count]; + * char[] names + */ typedef struct { int32 na_id; /* area ID */ uint32 na_lock; /* lock type (B_NO_LOCK, ...) */ @@ -641,7 +651,12 @@ typedef struct { uint64 na_ram_size; /* physical memory used */ } Elf64_Note_Area_Entry; -/* NT_IMAGES: uint32 count; Elf32_Note_Image_Entry[count]; char[] names */ +/* NT_IMAGES: + * uint32 count; + * uint32 entrySize; + * Elf32_Note_Image_Entry[count]; + * char[] names + */ typedef struct { int32 ni_id; /* image ID */ int32 ni_type; /* image type (B_APP_IMAGE, ...) */ @@ -655,7 +670,12 @@ typedef struct { uint32 ni_data_size; /* size of data segment */ } Elf32_Note_Image_Entry; -/* NT_IMAGES: uint64 count; Elf64_Note_Image_Entry[count]; char[] names */ +/* NT_IMAGES: + * uint32 count; + * uint32 entrySize; + * Elf64_Note_Image_Entry[count]; + * char[] names + */ typedef struct { int32 ni_id; /* image ID */ int32 ni_type; /* image type (B_APP_IMAGE, ...) */ @@ -672,6 +692,7 @@ typedef struct { /* NT_THREADS: * uint32 count; + * uint32 entrySize; * uint32 cpuStateSize; * {Elf32_Note_Thread_Entry, uint8[cpuStateSize] cpuState}[count]; * char[] names @@ -685,8 +706,9 @@ typedef struct { } Elf32_Note_Thread_Entry; /* NT_THREADS: - * uint64 count; - * uint64 cpuStateSize; + * uint32 count; + * uint32 entrySize; + * uint32 cpuStateSize; * {Elf64_Note_Thread_Entry, uint8[cpuStateSize] cpuState}[count]; * char[] names */ diff --git a/src/apps/debugger/elf/CoreFile.cpp b/src/apps/debugger/elf/CoreFile.cpp index dd8cf332a7..4f77ea3459 100644 --- a/src/apps/debugger/elf/CoreFile.cpp +++ b/src/apps/debugger/elf/CoreFile.cpp @@ -8,6 +8,8 @@ #include +#include + #include #include @@ -319,23 +321,34 @@ CoreFile::_ReadTeamNote(const void* data, uint32 dataSize) { typedef typename ElfClass::NoteTeam NoteTeam; - if (dataSize < sizeof(NoteTeam) + 1) { + if (dataSize < sizeof(uint32)) { WARNING("Team note too short\n"); return B_BAD_DATA; } - const NoteTeam* note = (const NoteTeam*)data; + uint32 entrySize = Get(*(const uint32*)data); + data = (const uint32*)data + 1; + dataSize -= sizeof(uint32); + + if (entrySize == 0 || dataSize == 0 || dataSize - 1 < entrySize) { + WARNING("Team note: too short or invalid entry size (%" B_PRIu32 ")\n", + entrySize); + return B_BAD_DATA; + } + + NoteTeam note = {}; + _ReadEntry(data, dataSize, note, entrySize); // check, if args are null-terminated - const char* args = (const char*)(note + 1); - size_t argsSize = dataSize - sizeof(NoteTeam); - if (argsSize == 0 || args[argsSize - 1] != '\0') { + const char* args = (const char*)data; + size_t argsSize = dataSize; + if (args[argsSize - 1] != '\0') { WARNING("Team note args not terminated\n"); return B_BAD_DATA; } - int32 id = Get(note->nt_id); - int32 uid = Get(note->nt_uid); - int32 gid = Get(note->nt_gid); + int32 id = Get(note.nt_id); + int32 uid = Get(note.nt_uid); + int32 gid = Get(note.nt_gid); BString copiedArgs(args); if (args[0] != '\0' && copiedArgs.Length() == 0) @@ -350,29 +363,29 @@ template status_t CoreFile::_ReadAreasNote(const void* data, uint32 dataSize) { - const size_t addressSize = sizeof(typename ElfClass::Size); - if (dataSize < addressSize) { + if (dataSize < 2 * sizeof(uint32)) { WARNING("Areas note too short\n"); return B_BAD_DATA; } - uint64 areaCount = Get(*(const typename ElfClass::Size*)data); + uint32 areaCount = _ReadValue(data, dataSize); + uint32 entrySize = _ReadValue(data, dataSize); typedef typename ElfClass::NoteAreaEntry Entry; - const Entry* table = (Entry*)((const uint8*)data + addressSize); - dataSize -= addressSize; if (areaCount == 0) return B_OK; - // check area count - if (areaCount > dataSize || areaCount * sizeof(Entry) >= dataSize) { - WARNING("Areas note too short for area count\n"); + // check entry size and area count + if (entrySize == 0 || dataSize == 0 || areaCount > dataSize + || dataSize - 1 < entrySize || areaCount * entrySize >= dataSize) { + WARNING("Areas note: too short or invalid entry size (%" B_PRIu32 ")\n", + entrySize); return B_BAD_DATA; } // check, if strings are null-terminated - const char* strings = (const char*)(table + areaCount); - size_t stringsSize = dataSize - areaCount * sizeof(Entry); + const char* strings = (const char*)data + areaCount * entrySize; + size_t stringsSize = dataSize - areaCount * entrySize; if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { WARNING("Areas note strings not terminated\n"); return B_BAD_DATA; @@ -380,8 +393,8 @@ CoreFile::_ReadAreasNote(const void* data, uint32 dataSize) for (uint64 i = 0; i < areaCount; i++) { // get entry values - Entry entry; - memcpy(&entry, table, sizeof(entry)); + Entry entry = {}; + _ReadEntry(data, dataSize, entry, entrySize); int32 id = Get(entry.na_id); uint64 baseAddress = Get(entry.na_base); @@ -413,8 +426,6 @@ CoreFile::_ReadAreasNote(const void* data, uint32 dataSize) delete area; return B_NO_MEMORY; } - - table++; } return B_OK; @@ -425,29 +436,29 @@ template status_t CoreFile::_ReadImagesNote(const void* data, uint32 dataSize) { - const size_t addressSize = sizeof(typename ElfClass::Size); - if (dataSize < addressSize) { + if (dataSize < 2 * sizeof(uint32)) { WARNING("Images note too short\n"); return B_BAD_DATA; } - uint64 imageCount = Get(*(const typename ElfClass::Size*)data); + uint32 imageCount = _ReadValue(data, dataSize); + uint32 entrySize = _ReadValue(data, dataSize); typedef typename ElfClass::NoteImageEntry Entry; - const Entry* table = (Entry*)((const uint8*)data + addressSize); - dataSize -= addressSize; if (imageCount == 0) return B_OK; - // check image count - if (imageCount > dataSize || imageCount * sizeof(Entry) >= dataSize) { - WARNING("Images note too short for image count\n"); + // check entry size and image count + if (entrySize == 0 || dataSize == 0 || imageCount > dataSize + || dataSize - 1 < entrySize || imageCount * entrySize >= dataSize) { + WARNING("Images note: too short or invalid entry size (%" B_PRIu32 + ")\n", entrySize); return B_BAD_DATA; } // check, if strings are null-terminated - const char* strings = (const char*)(table + imageCount); - size_t stringsSize = dataSize - imageCount * sizeof(Entry); + const char* strings = (const char*)data + imageCount * entrySize; + size_t stringsSize = dataSize - imageCount * entrySize; if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { WARNING("Images note strings not terminated\n"); return B_BAD_DATA; @@ -455,8 +466,8 @@ CoreFile::_ReadImagesNote(const void* data, uint32 dataSize) for (uint64 i = 0; i < imageCount; i++) { // get entry values - Entry entry; - memcpy(&entry, table, sizeof(entry)); + Entry entry = {}; + _ReadEntry(data, dataSize, entry, entrySize); int32 id = Get(entry.ni_id); int32 type = Get(entry.ni_type); @@ -494,8 +505,6 @@ CoreFile::_ReadImagesNote(const void* data, uint32 dataSize) delete image; return B_NO_MEMORY; } - - table++; } return B_OK; @@ -506,40 +515,39 @@ template status_t CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize) { - const size_t addressSize = sizeof(typename ElfClass::Size); - if (dataSize < 2 * addressSize) { + if (dataSize < 3 * sizeof(uint32)) { WARNING("Threads note too short\n"); return B_BAD_DATA; } - - const typename ElfClass::Size* header - = (const typename ElfClass::Size*)data; - uint64 threadCount = Get(header[0]); - uint64 cpuStateSize = Get(header[1]); + uint32 threadCount = _ReadValue(data, dataSize); + uint32 entrySize = _ReadValue(data, dataSize); + uint32 cpuStateSize = _ReadValue(data, dataSize); if (cpuStateSize > 1024 * 1024) { - WARNING("Threads note: unreasonable CPU state size: %" B_PRIu64 "\n", + WARNING("Threads note: unreasonable CPU state size: %" B_PRIu32 "\n", cpuStateSize); return B_BAD_DATA; } typedef typename ElfClass::NoteThreadEntry Entry; - const uint8* table = (const uint8*)(header + 2); - dataSize -= 2 * addressSize; - - size_t totalEntrySize = sizeof(Entry) + (size_t)cpuStateSize; - - // check thread count - if (threadCount > dataSize || threadCount * totalEntrySize >= dataSize) { - WARNING("Threads note too short for thread count\n"); - return B_BAD_DATA; - } if (threadCount == 0) return B_OK; + size_t totalEntrySize = entrySize + cpuStateSize; + + // check entry size and thread count + if (entrySize == 0 || dataSize == 0 || threadCount > dataSize + || entrySize > dataSize || cpuStateSize > dataSize + || dataSize - 1 < totalEntrySize + || threadCount * totalEntrySize >= dataSize) { + WARNING("Threads note: too short or invalid entry size (%" B_PRIu32 + ")\n", entrySize); + return B_BAD_DATA; + } + // check, if strings are null-terminated - const char* strings = (const char*)(table + threadCount * totalEntrySize); + const char* strings = (const char*)data + threadCount * totalEntrySize; size_t stringsSize = dataSize - threadCount * totalEntrySize; if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { WARNING("Threads note strings not terminated\n"); @@ -548,8 +556,8 @@ CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize) for (uint64 i = 0; i < threadCount; i++) { // get entry values - Entry entry; - memcpy(&entry, table, sizeof(entry)); + Entry entry = {}; + _ReadEntry(data, dataSize, entry, entrySize); int32 id = Get(entry.nth_id); int32 state = Get(entry.nth_state); @@ -581,11 +589,9 @@ CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize) } // get CPU state - const void* cpuState = table + sizeof(Entry); - if (!thread->SetCpuState(cpuState, cpuStateSize)) + if (!thread->SetCpuState(data, cpuStateSize)) return B_NO_MEMORY; - - table += totalEntrySize; + _Advance(data, dataSize, cpuStateSize); } return B_OK; @@ -622,3 +628,29 @@ CoreFile::_FindAreaSegment(uint64 address) const } +template +Type +CoreFile::_ReadValue(const void*& data, uint32& dataSize) +{ + Type value = Get(*(const Type*)data); + _Advance(data, dataSize, sizeof(Type)); + return value; +} + + +template +void +CoreFile::_ReadEntry(const void*& data, uint32& dataSize, Entry& entry, + size_t entrySize) +{ + memcpy(&entry, data, std::min(sizeof(entry), entrySize)); + _Advance(data, dataSize, entrySize); +} + + +void +CoreFile::_Advance(const void*& data, uint32& dataSize, size_t by) +{ + data = (const uint8*)data + by; + dataSize -= by; +} diff --git a/src/apps/debugger/elf/CoreFile.h b/src/apps/debugger/elf/CoreFile.h index b20b134391..0cb067c53a 100644 --- a/src/apps/debugger/elf/CoreFile.h +++ b/src/apps/debugger/elf/CoreFile.h @@ -179,6 +179,14 @@ private: CoreFileAreaInfo* _FindArea(uint64 address) const; ElfSegment* _FindAreaSegment(uint64 address) const; + template + Type _ReadValue(const void*& data, uint32& dataSize); + template + void _ReadEntry(const void*& data, uint32& dataSize, + Entry& entry, size_t entrySize); + void _Advance(const void*& data, uint32& dataSize, + size_t by); + template Value Get(const Value& value) const { return fElfFile.Get(value); } diff --git a/src/system/kernel/debug/core_dump.cpp b/src/system/kernel/debug/core_dump.cpp index 69857dc0af..bee04aae82 100644 --- a/src/system/kernel/debug/core_dump.cpp +++ b/src/system/kernel/debug/core_dump.cpp @@ -1134,7 +1134,8 @@ private: note.nt_id = fTeamInfo.team; note.nt_uid = fTeamInfo.uid; note.nt_gid = fTeamInfo.gid; - writer.Write(¬e, sizeof(note)); + writer.Write((uint32)sizeof(note)); + writer.Write(note); // write args const char* args = fTeamInfo.args; @@ -1214,7 +1215,8 @@ private: void _WriteAreasNote(Writer& writer) { // area count - writer.Write(fAreaCount); + writer.Write((uint32)fAreaCount); + writer.Write((uint32)sizeof(elf_note_area_entry)); // write table for (AreaInfoList::Iterator it = fAreaInfos.GetIterator(); @@ -1227,7 +1229,7 @@ private: entry.na_base = areaInfo->Base(); entry.na_size = areaInfo->Size(); entry.na_ram_size = areaInfo->RamSize(); - writer.Write(&entry, sizeof(entry)); + writer.Write(entry); } // write strings @@ -1261,7 +1263,8 @@ private: void _WriteImagesNote(Writer& writer) { // image count - writer.Write(fImageCount); + writer.Write((uint32)fImageCount); + writer.Write((uint32)sizeof(elf_note_image_entry)); // write table for (ImageInfoList::Iterator it = fImageInfos.GetIterator(); @@ -1278,7 +1281,7 @@ private: entry.ni_text_size = imageInfo->TextSize(); entry.ni_data_base = imageInfo->DataBase(); entry.ni_data_size = imageInfo->DataSize(); - writer.Write(&entry, sizeof(entry)); + writer.Write(entry); } // write strings @@ -1312,8 +1315,9 @@ private: void _WriteThreadsNote(Writer& writer) { // thread count and size of CPU state - writer.Write(fThreadCount); - writer.Write(sizeof(debug_cpu_state)); + writer.Write((uint32)fThreadCount); + writer.Write((uint32)sizeof(elf_note_thread_entry)); + writer.Write((uint32)sizeof(debug_cpu_state)); // write table for (ThreadStateList::Iterator it = fThreadStates.GetIterator();