From 270e5fe88b0666021a7a6393334db7feeb8245f8 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 12 Feb 2011 09:28:35 +0800 Subject: [PATCH] Big bugfixes from trying a Clone/fork bomb - User heap bugfixes (why was I using sbrk?) - Threads_Kill (handling non-active threads) - Proc_Clone (Error handling from MM) - MM_NewKStack (OOM handling) --- Kernel/Makefile.BuildNum.x86_64 | 2 +- Kernel/arch/x86/mm_virt.c | 20 ++++- Kernel/arch/x86/proc.c | 7 +- Kernel/binary.c | 2 +- Kernel/include/threads.h | 1 + Kernel/threads.c | 80 ++++++++++++------- Modules/Display/VESA/main.c | 17 +++- Usermode/Applications/bomb_src/main.c | 24 +++++- Usermode/Libraries/crt0.o_src/crt0.asm | 2 +- Usermode/Libraries/ld-acess.so_src/core.asm | 69 +++++++++++++++- Usermode/Libraries/ld-acess.so_src/export.c | 3 +- Usermode/Libraries/libc.so_src/heap.c | 60 ++++++++++---- .../Libraries/libspiderscript.so_src/lex.c | 2 + .../Libraries/libspiderscript.so_src/parse.c | 11 +-- 14 files changed, 238 insertions(+), 62 deletions(-) diff --git a/Kernel/Makefile.BuildNum.x86_64 b/Kernel/Makefile.BuildNum.x86_64 index 89ed6d5e..205d26c1 100644 --- a/Kernel/Makefile.BuildNum.x86_64 +++ b/Kernel/Makefile.BuildNum.x86_64 @@ -1 +1 @@ -BUILD_NUM = 224 +BUILD_NUM = 225 diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 8882f38e..a07f876d 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -660,14 +660,28 @@ tVAddr MM_NewKStack(void) Uint i; for(base = KERNEL_STACKS; base < KERNEL_STACKS_END; base += KERNEL_STACK_SIZE) { + // Check if space is free if(MM_GetPhysAddr(base) != 0) continue; - for(i = 0; i < KERNEL_STACK_SIZE; i += 0x1000) { - MM_Allocate(base+i); + // Allocate + //for(i = KERNEL_STACK_SIZE; i -= 0x1000 ; ) + for(i = 0; i < KERNEL_STACK_SIZE; i += 0x1000 ) + { + if( MM_Allocate(base+i) == 0 ) + { + // On error, print a warning and return error + Warning("MM_NewKStack - Out of memory"); + // - Clean up + //for( i += 0x1000 ; i < KERNEL_STACK_SIZE; i += 0x1000 ) + // MM_Deallocate(base+i); + return 0; + } } + // Success Log("MM_NewKStack - Allocated %p", base + KERNEL_STACK_SIZE); return base+KERNEL_STACK_SIZE; } - Warning("MM_NewKStack - No address space left\n"); + // No stacks left + Warning("MM_NewKStack - No address space left"); return 0; } diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index d3c4ab47..4812609a 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -566,6 +566,11 @@ int Proc_Clone(Uint *Err, Uint Flags) // Initialise Memory Space (New Addr space or kernel stack) if(Flags & CLONE_VM) { newThread->MemState.CR3 = MM_Clone(); + // Check for errors + if(newThread->MemState.CR3 == 0) { + Threads_Kill(newThread, -2); + return -1; + } newThread->KernelStack = cur->KernelStack; } else { Uint tmpEbp, oldEsp = esp; @@ -581,7 +586,7 @@ int Proc_Clone(Uint *Err, Uint Flags) newThread->KernelStack = MM_NewKStack(); // Check for errors if(newThread->KernelStack == 0) { - free(newThread); + Threads_Kill(newThread, -2); return -1; } diff --git a/Kernel/binary.c b/Kernel/binary.c index aa5d9547..fa49e850 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -160,7 +160,7 @@ int Proc_Execve(char *File, char **ArgV, char **EnvP) { Log_Warning("BIN", "Proc_Execve - Unable to load '%s'", Threads_GetName(-1)); LEAVE('-'); - Threads_Exit(0, 0); + Threads_Exit(0, -10); for(;;); } diff --git a/Kernel/include/threads.h b/Kernel/include/threads.h index 6fbc11fc..fc2303c9 100644 --- a/Kernel/include/threads.h +++ b/Kernel/include/threads.h @@ -113,6 +113,7 @@ extern tThread *Proc_GetCurThread(void); extern tThread *Threads_GetThread(Uint TID); extern void Threads_SetPriority(tThread *Thread, int Pri); extern int Threads_Wake(tThread *Thread); +extern void Threads_Kill(tThread *Thread, int Status); extern void Threads_AddActive(tThread *Thread); extern tThread *Threads_GetNextToRun(int CPU, tThread *Last); diff --git a/Kernel/threads.c b/Kernel/threads.c index 87001540..5d15c929 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -279,6 +279,7 @@ tThread *Threads_CloneTCB(Uint *Err, Uint Flags) SHORTLOCK( &glThreadListLock ); new->GlobalPrev = NULL; // Protect against bugs new->GlobalNext = gAllThreads; + gAllThreads->GlobalPrev = new; gAllThreads = new; SHORTREL( &glThreadListLock ); @@ -466,15 +467,15 @@ void Threads_Kill(tThread *Thread, int Status) tMsg *msg; // TODO: Kill all children - #if 0 + #if 1 { tThread *child; // TODO: I should keep a .Parent pointer, and a .Children list - for(child = gActiveThreads; + for(child = gAllThreads; child; - child = child->Next) + child = child->GlobalNext) { - if(child->PTID == Thread->TID) + if(child->Parent == Thread) Threads_Kill(child, -1); } } @@ -496,29 +497,52 @@ void Threads_Kill(tThread *Thread, int Status) // Lock thread list SHORTLOCK( &glThreadListLock ); - // Delete from active list - #if SCHEDULER_TYPE == SCHED_RR_PRI - if( !Threads_int_DelFromQueue( &gaActiveThreads[Thread->Priority], Thread ) ) - #else - if( !Threads_int_DelFromQueue( &gActiveThreads, Thread ) ) - #endif + switch(Thread->Status) { - Warning("Proc_Exit - Current thread is not on the active queue"); - SHORTREL( &glThreadListLock ); - SHORTREL( &Thread->IsLocked ); - return; - } + case THREAD_STAT_PREINIT: // Only on main list + break; - // Ensure that we are not rescheduled - Thread->Remaining = 0; // Clear Remaining Quantum - Thread->Quantum = 0; // Clear Quantum to indicate dead thread - - // Update bookkeeping - giNumActiveThreads --; - #if SCHEDULER_TYPE == SCHED_LOTTERY - if( Thread != Proc_GetCurThread() ) - giFreeTickets -= caiTICKET_COUNTS[ Thread->Priority ]; - #endif + // Currently active thread + case THREAD_STAT_ACTIVE: + #if SCHEDULER_TYPE == SCHED_RR_PRI + if( Threads_int_DelFromQueue( &gaActiveThreads[Thread->Priority], Thread ) ) + #else + if( Threads_int_DelFromQueue( &gActiveThreads, Thread ) ) + #endif + { + // Ensure that we are not rescheduled + Thread->Remaining = 0; // Clear Remaining Quantum + Thread->Quantum = 0; // Clear Quantum to indicate dead thread + + // Update bookkeeping + giNumActiveThreads --; + #if SCHEDULER_TYPE == SCHED_LOTTERY + if( Thread != Proc_GetCurThread() ) + giFreeTickets -= caiTICKET_COUNTS[ Thread->Priority ]; + #endif + } + else + { + Log_Warning("Threads", + "Threads_Kill - Thread %p(%i,%s) marked as active, but not on list", + Thread, Thread->TID, Thread->ThreadName + ); + } + break; + case THREAD_STAT_SLEEPING: + if( !Threads_int_DelFromQueue( &gSleepingThreads, Thread ) ) + { + Log_Warning("Threads", + "Threads_Kill - Thread %p(%i,%s) marked as sleeping, but not on list", + Thread, Thread->TID, Thread->ThreadName + ); + } + break; + default: + Log_Warning("Threads", "Threads_Kill - BUG Un-checked status (%i)", + Thread->Status); + break; + } // Save exit status Thread->RetStatus = Status; @@ -534,7 +558,7 @@ void Threads_Kill(tThread *Thread, int Status) Threads_Wake( Thread->Parent ); } - Log("Thread %i went *hurk* (%i)", Thread->TID, Thread->Status); + Log("Thread %i went *hurk* (%i)", Thread->TID, Status); // Release spinlocks SHORTREL( &glThreadListLock ); @@ -915,7 +939,9 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) while(gDeleteThreads) { thread = gDeleteThreads->Next; - if( IS_LOCKED(&gDeleteThreads->IsLocked) ) { // Only free if structure is unused + // Only free if structure is unused + if( !IS_LOCKED(&gDeleteThreads->IsLocked) ) + { // Set to dead gDeleteThreads->Status = THREAD_STAT_BURIED; // Free name diff --git a/Modules/Display/VESA/main.c b/Modules/Display/VESA/main.c index 479be302..1cd6a91f 100644 --- a/Modules/Display/VESA/main.c +++ b/Modules/Display/VESA/main.c @@ -2,7 +2,7 @@ * AcessOS 1 * Video BIOS Extensions (Vesa) Driver */ -#define DEBUG 1 +#define DEBUG 0 #define VERSION 0x100 #include @@ -474,10 +474,19 @@ int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data) break; } - tmp = gVesa_Modes[i].width * gVesa_Modes[i].height * gVesa_Modes[i].bpp; - tmp -= data->width * data->height * data->bpp; + tmp = gVesa_Modes[i].width * gVesa_Modes[i].height; + tmp -= data->width * data->height; tmp = tmp < 0 ? -tmp : tmp; - factor = tmp * 100 / (data->width * data->height * data->bpp); + factor = tmp * 100 / (data->width * data->height); + + if( (data->bpp == 32 || data->bpp == 24) + && (gVesa_Modes[i].bpp == 32 || gVesa_Modes[i].bpp == 24) ) + { + + } + else { + factor *= 10; + } LOG("factor = %i", factor); diff --git a/Usermode/Applications/bomb_src/main.c b/Usermode/Applications/bomb_src/main.c index d7923224..944d6c32 100644 --- a/Usermode/Applications/bomb_src/main.c +++ b/Usermode/Applications/bomb_src/main.c @@ -46,8 +46,30 @@ int main(int argc, char *argv[]) for(;;) clone(CLONE_VM, 0); } else { - for(;;) clone(0, malloc(512-16)+512-16); + for(;;) + { + const int stackSize = 512-16; + const int stackOffset = 65; + char *stack = calloc(1, stackSize); + int tid; + if( !stack ) { + printf("Outta heap space!\n"); + return 0; + } + tid = clone(0, stack+stackSize-stackOffset); + if( tid == 0 ) + { + // Sleep forever (TODO: Fix up the stack so it can nuke) + for(;;) sleep(); + } + if( tid < 0 ) { + printf("Clone failed\n"); + return 0; + } + printf("stack = %p, tid = %i\n", stack, tid); + } } + printf("RETURN!?\n"); return 0; } diff --git a/Usermode/Libraries/crt0.o_src/crt0.asm b/Usermode/Libraries/crt0.o_src/crt0.asm index b923d184..b8f52703 100644 --- a/Usermode/Libraries/crt0.o_src/crt0.asm +++ b/Usermode/Libraries/crt0.o_src/crt0.asm @@ -15,5 +15,5 @@ _start: start: call main push eax - call _exit + call _exit jmp $ ; This should never be reached diff --git a/Usermode/Libraries/ld-acess.so_src/core.asm b/Usermode/Libraries/ld-acess.so_src/core.asm index c44dc535..0bf80c12 100644 --- a/Usermode/Libraries/ld-acess.so_src/core.asm +++ b/Usermode/Libraries/ld-acess.so_src/core.asm @@ -10,9 +10,76 @@ _errno: dd 0 [section .text] -; --- Process Controll --- +; DEST +; SRC +_memcpy: + push ebp + mov ebp, esp + push edi + push esi ; DI and SI must be maintained, CX doesn't + + mov ecx, [ebp+16] + mov esi, [ebp+12] + mov edi, [ebp+8] + rep movsb + + pop esi + pop edi + pop ebp + ret + +; --- Process Control --- SYSCALL1 _exit, SYS_EXIT + +%if 0 SYSCALL2 clone, SYS_CLONE +%else +[global clone:func] +clone: + push ebp + mov ebp, esp + push ebx + + mov ebx, [ebp+12] ; Get new stack pointer + + ; Check if the new stack is being used + test ebx, ebx + jz .doCall + ; Modify it to include the calling function (and this) + %if 0 + mov eax, [ebp] ; Get old stack frame + sub eax, ebp ; Get size + sub ebx, eax ; Alter new stack pointer + push eax ; < Size + push DWORD [ebp] ; < Source + push ebx ; < Dest + call _memcpy + add esp, 4*3 ; Restore stack + ; EBX should still be the new stack pointer + mov eax, [ebp] ; Save old stack frame pointer in new stack + mov [ebx-4], eax + mov eax, [ebp-4] ; Save EBX there too + mov [ebx-8], eax + sub ebx, 8 ; Update stack pointer for system + %else + ; Quick hack, just this stack frame + mov eax, [ebp+4] + mov [ebx-4], eax ; Return + mov [ebx-8], ebx ; EBP + mov DWORD [ebx-12], 0 ; EBX + sub ebx, 12 + %endif +.doCall: + mov eax, SYS_CLONE + mov ecx, ebx ; Stack + mov ebx, [ebp+8] ; Flags + SYSCALL_OP + mov [_errno], ebx + pop ebx + pop ebp + ret +%endif + SYSCALL2 kill, SYS_KILL SYSCALL0 yield, SYS_YIELD SYSCALL0 sleep, SYS_SLEEP diff --git a/Usermode/Libraries/ld-acess.so_src/export.c b/Usermode/Libraries/ld-acess.so_src/export.c index 867e17fb..9aa47e6a 100644 --- a/Usermode/Libraries/ld-acess.so_src/export.c +++ b/Usermode/Libraries/ld-acess.so_src/export.c @@ -60,7 +60,8 @@ const struct { EXP(_SysOpenChild), EXP(_SysGetPhys), - EXP(_SysAllocate) + EXP(_SysAllocate), + EXP(_SysDebug) }; diff --git a/Usermode/Libraries/libc.so_src/heap.c b/Usermode/Libraries/libc.so_src/heap.c index d0490707..14066e9e 100644 --- a/Usermode/Libraries/libc.so_src/heap.c +++ b/Usermode/Libraries/libc.so_src/heap.c @@ -36,6 +36,7 @@ EXPORT void free(void *mem); EXPORT void *realloc(void *mem, Uint bytes); EXPORT void *sbrk(int increment); LOCAL void *extendHeap(int bytes); +static void *FindHeapBase(); LOCAL uint brk(Uint newpos); //Code @@ -68,7 +69,7 @@ EXPORT void *malloc(size_t bytes) while((Uint)curBlock < (Uint)_heap_end) { - //SysDebug(" malloc: curBlock = 0x%x, curBlock->magic = 0x%x\n", curBlock, curBlock->magic); + //_SysDebug(" malloc: curBlock = 0x%x, curBlock->magic = 0x%x\n", curBlock, curBlock->magic); if(curBlock->magic == MAGIC_FREE) { if(curBlock->size == bestSize) @@ -81,14 +82,14 @@ EXPORT void *malloc(size_t bytes) else if(curBlock->magic != MAGIC) { //Corrupt Heap - //SysDebug("malloc: Corrupt Heap\n"); + _SysDebug("malloc: Corrupt Heap\n"); return NULL; } curBlock = (heap_head*)((Uint)curBlock + curBlock->size); } if((Uint)curBlock < (Uint)_heap_start) { - //SysDebug("malloc: Heap underrun for some reason\n"); + _SysDebug("malloc: Heap underrun for some reason\n"); return NULL; } @@ -102,7 +103,7 @@ EXPORT void *malloc(size_t bytes) if(!closestMatch) { curBlock = extendHeap(bestSize); //Allocate more if(curBlock == NULL) { - //SysDebug("malloc: Out of Heap Space\n"); + _SysDebug("malloc: Out of Heap Space\n"); return NULL; } curBlock->magic = MAGIC; @@ -243,7 +244,6 @@ LOCAL void *extendHeap(int bytes) if(foot == (void*)-1) return NULL; - //Create New Block // Header head->magic = MAGIC_FREE; //Unallocated @@ -275,24 +275,52 @@ LOCAL void *extendHeap(int bytes) */ EXPORT void *sbrk(int increment) { - size_t newEnd; static size_t oldEnd = 0; static size_t curEnd = 0; - //_SysDebug("sbrk: (increment=%i)\n", increment); + //_SysDebug("sbrk: (increment=%i)", increment); - if (oldEnd == 0) curEnd = oldEnd = brk(0); + if (curEnd == 0) { + oldEnd = curEnd = (size_t)FindHeapBase(); + //_SysAllocate(curEnd); // Allocate the first page + } - //SysDebug(" sbrk: oldEnd = 0x%x\n", oldEnd); + //_SysDebug(" sbrk: oldEnd = 0x%x", oldEnd); if (increment == 0) return (void *) curEnd; - newEnd = curEnd + increment; - - if (brk(newEnd) == curEnd) return (void *) -1; oldEnd = curEnd; - curEnd = newEnd; - //SysDebug(" sbrk: newEnd = 0x%x\n", newEnd); + // Single Page + if( (curEnd & 0xFFF) && (curEnd & 0xFFF) + increment < 0x1000 ) + { + //if( curEnd & 0xFFF == 0 ) + //{ + // if( !_SysAllocate(curEnd) ) + // { + // _SysDebug("sbrk - Error allocating memory"); + // return (void*)-1; + // } + //} + curEnd += increment; + //_SysDebug("sbrk: RETURN %p (single page, no alloc)", (void *) oldEnd); + return (void *)oldEnd; + } + + increment -= curEnd & 0xFFF; + curEnd += 0xFFF; curEnd &= ~0xFFF; + while( increment > 0 ) + { + if( !_SysAllocate(curEnd) ) + { + // Error? + _SysDebug("sbrk - Error allocating memory"); + return (void*)-1; + } + increment -= 0x1000; + curEnd += 0x1000; + } + + //_SysDebug("sbrk: RETURN %p", (void *) oldEnd); return (void *) oldEnd; } @@ -364,7 +392,7 @@ LOCAL uint brk(Uint newpos) uint ret = curpos; int delta; - //_SysDebug("brk: (newpos=0x%x)", newpos); + _SysDebug("brk: (newpos=0x%x)", newpos); // Find initial position if(curpos == 0) curpos = (uint)FindHeapBase(); @@ -375,7 +403,7 @@ LOCAL uint brk(Uint newpos) if(newpos < curpos) return newpos; delta = newpos - curpos; - //_SysDebug(" brk: delta = 0x%x", delta); + _SysDebug(" brk: delta = 0x%x", delta); // Do we need to add pages if(curpos & 0xFFF && (curpos & 0xFFF) + delta < 0x1000) diff --git a/Usermode/Libraries/libspiderscript.so_src/lex.c b/Usermode/Libraries/libspiderscript.so_src/lex.c index 7121ce13..fd395e0f 100644 --- a/Usermode/Libraries/libspiderscript.so_src/lex.c +++ b/Usermode/Libraries/libspiderscript.so_src/lex.c @@ -7,6 +7,8 @@ #include #include +// Make the scope character ('.') be a symbol, otherwise it's just +// a ident character #define USE_SCOPE_CHAR 0 #define DEBUG 0 diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c index f32f876f..0b481980 100644 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ b/Usermode/Libraries/libspiderscript.so_src/parse.c @@ -201,7 +201,6 @@ tAST_Node *Parse_DoBlockLine(tParser *Parser) // Return from a method case TOK_RWD_RETURN: - //printf("return\n"); GetToken(Parser); ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser)); break; @@ -662,11 +661,11 @@ tAST_Node *Parse_GetVariable(tParser *Parser) } /** - * \brief Get an identifier (constand or function call) + * \brief Get an identifier (constant or function call) */ tAST_Node *Parse_GetIdent(tParser *Parser) { - tAST_Node *ret; + tAST_Node *ret = NULL; char *name; SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); name = strndup( Parser->TokenStr, Parser->TokenLen ); @@ -674,7 +673,9 @@ tAST_Node *Parse_GetIdent(tParser *Parser) #if 0 while( GetToken(Parser) == TOK_SCOPE ) { - ret = AST_New + ret = AST_NewScopeDereference( Parser, ret, name ); + SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); + name = strndup( Parser->TokenStr, Parser->TokenLen ); } PutBack(Parser); #endif @@ -703,7 +704,7 @@ tAST_Node *Parse_GetIdent(tParser *Parser) } } else { - // Runtime Constant + // Runtime Constant / Variable (When implemented) #if DEBUG >= 2 printf("Parse_GetIdent: Referencing '%s'\n", name); #endif -- 2.20.1