diff --git a/AK/Types.h b/AK/Types.h index 12f65115e35..89a459a0638 100644 --- a/AK/Types.h +++ b/AK/Types.h @@ -53,3 +53,13 @@ constexpr unsigned GB = KB * KB * KB; namespace std { typedef decltype(nullptr) nullptr_t; } + +static constexpr dword explode_byte(byte b) +{ + return b << 24 | b << 16 | b << 8 | b; +} + +static_assert(explode_byte(0xff) == 0xffffffff); +static_assert(explode_byte(0x80) == 0x80808080); +static_assert(explode_byte(0x7f) == 0x7f7f7f7f); +static_assert(explode_byte(0) == 0); diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index d1f5beb717d..bb786607967 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -7,6 +7,7 @@ #include #include #include +#include //#define PAGE_FAULT_DEBUG @@ -254,9 +255,9 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) { ASSERT(current); - dword faultAddress; + dword fault_address; asm("movl %%cr2, %%eax" - : "=a"(faultAddress)); + : "=a"(fault_address)); dword fault_page_directory; asm("movl %%cr3, %%eax" @@ -270,22 +271,33 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) regs.exception_code & 1 ? "PV" : "NP", fault_page_directory, regs.exception_code & 2 ? "write" : "read", - faultAddress); + fault_address); #endif #ifdef PAGE_FAULT_DEBUG dump(regs); #endif - auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(faultAddress))); + auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(fault_address))); if (response == PageFaultResponse::ShouldCrash) { - kprintf("%s(%u:%u) unrecoverable page fault, %s vaddr=%p\n", + dbgprintf("\033[31;1m%s(%u:%u) Unrecoverable page fault, %s address %p\033[0m\n", current->process().name().characters(), current->pid(), current->tid(), - regs.exception_code & 2 ? "write" : "read", - faultAddress); + regs.exception_code & 2 ? "write to" : "read from", + fault_address); + + dword malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE); + dword free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE); + if ((fault_address & 0xffff0000) == (malloc_scrub_pattern & 0xffff0000)) { + dbgprintf("\033[33;1mNote: Address %p looks like it may be uninitialized malloc() memory\033[0m\n", fault_address); + } else if ((fault_address & 0xffff0000) == (free_scrub_pattern & 0xffff0000)) { + dbgprintf("\033[33;1mNote: Address %p looks like it may be recently free()'d memory\033[0m\n", fault_address); + } else if (fault_address < 4096) { + dbgprintf("\033[33;1mNote: Address %p looks like a possible nullptr dereference\033[0m\n", fault_address); + } + dump(regs); current->process().crash(SIGSEGV, regs.eip); } else if (response == PageFaultResponse::Continue) { diff --git a/LibC/malloc.cpp b/LibC/malloc.cpp index 2225ba9caac..ae3b6733e55 100644 --- a/LibC/malloc.cpp +++ b/LibC/malloc.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -12,8 +13,6 @@ //#define MALLOC_DEBUG #define RECYCLE_BIG_ALLOCATIONS -#define MALLOC_SCRUB_BYTE 0x85 -#define FREE_SCRUB_BYTE 0x82 #define MAGIC_PAGE_HEADER 0x42657274 #define MAGIC_BIGALLOC_HEADER 0x42697267 #define PAGE_ROUND_UP(x) ((((size_t)(x)) + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1))) diff --git a/LibC/mallocdefs.h b/LibC/mallocdefs.h new file mode 100644 index 00000000000..cb27bc29bef --- /dev/null +++ b/LibC/mallocdefs.h @@ -0,0 +1,5 @@ +#pragma once + +#define MALLOC_SCRUB_BYTE 0xdc +#define FREE_SCRUB_BYTE 0xed + diff --git a/Userland/crash.cpp b/Userland/crash.cpp index 207d0f1c30d..d5bd3135392 100644 --- a/Userland/crash.cpp +++ b/Userland/crash.cpp @@ -4,17 +4,22 @@ static void print_usage_and_exit() { - printf("usage: crash -[sdia]\n"); + printf("usage: crash -[sdiamfMF]\n"); exit(0); } +#pragma GCC optimize("O0") int main(int argc, char** argv) { enum Mode { SegmentationViolation, DivisionByZero, IllegalInstruction, - Abort + Abort, + WriteToUninitializedMallocMemory, + WriteToFreedMemory, + ReadFromUninitializedMallocMemory, + ReadFromFreedMemory, }; Mode mode = SegmentationViolation; @@ -29,6 +34,14 @@ int main(int argc, char** argv) mode = IllegalInstruction; else if (String(argv[1]) == "-a") mode = Abort; + else if (String(argv[1]) == "-m") + mode = ReadFromUninitializedMallocMemory; + else if (String(argv[1]) == "-f") + mode = ReadFromFreedMemory; + else if (String(argv[1]) == "-M") + mode = WriteToUninitializedMallocMemory; + else if (String(argv[1]) == "-F") + mode = WriteToFreedMemory; else print_usage_and_exit(); @@ -55,6 +68,32 @@ int main(int argc, char** argv) ASSERT_NOT_REACHED(); } + if (mode == ReadFromUninitializedMallocMemory) { + auto* uninitialized_memory = (volatile dword**)malloc(1024); + volatile auto x = uninitialized_memory[0][0]; + ASSERT_NOT_REACHED(); + } + + if (mode == ReadFromFreedMemory) { + auto* uninitialized_memory = (volatile dword**)malloc(1024); + free(uninitialized_memory); + volatile auto x = uninitialized_memory[4][0]; + ASSERT_NOT_REACHED(); + } + + if (mode == WriteToUninitializedMallocMemory) { + auto* uninitialized_memory = (volatile dword**)malloc(1024); + uninitialized_memory[4][0] = 1; + ASSERT_NOT_REACHED(); + } + + if (mode == WriteToFreedMemory) { + auto* uninitialized_memory = (volatile dword**)malloc(1024); + free(uninitialized_memory); + uninitialized_memory[4][0] = 1; + ASSERT_NOT_REACHED(); + } + ASSERT_NOT_REACHED(); return 0; }