From 08b6b61214062da92aafcc179e222122c5ef4f74 Mon Sep 17 00:00:00 2001 From: John van Groningen Date: Fri, 11 Jul 2003 11:59:28 +0000 Subject: added stack overflow detection using virtual memory and exceptions --- Worksheet | 44 +++++-- macho/pprofile.a | 2 + macho/pstartup.a | 22 +++- macho/ptrace.a | 2 + mcon.c | 382 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- pprofile.a | 4 +- pstartup.a | 112 +++++++++++++++- ptrace.a | 2 + 8 files changed, 548 insertions(+), 22 deletions(-) diff --git a/Worksheet b/Worksheet index 5ddf528..bc3cdcb 100644 --- a/Worksheet +++ b/Worksheet @@ -4,25 +4,47 @@ Set -e CIncludes 'Programs:Metrowerks CodeWarrior 6.0:Metrowerks CodeWarrior:Car mrc -w off -sym off -d POWER -d G_POWER -d WRITE_HEAP mcon.c -o mcon.c.x mrc -sym off -d POWER -d G_POWER mwrite_heap.c -o mwrite_heap.c.x ppcasm -sym off -d PROFILE=0 -d LINUX=0 -typecheck pstartup.a -o pstartup.a.o -PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pstartup.a.o -o _startup.o -setfile -t CgOb -c 3PRM _startup.o +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pstartup.a.o -o _startup.xo +setfile -t CgOb -c 3PRM _startup.xo mrc -w off -sym off -d POWER -d G_POWER -d WRITE_HEAP -d TIME_PROFILE -d LINUX=0 mcon.c -o mcon.c.x ppcasm -sym off -d PROFILE=1 -d LINUX=0 -typecheck pstartup.a -o pstartup.a.o ppcasm -d POWER601=0 -d LINUX=0 -sym off -typecheck pprofile.a -o pprofile.a.o -PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pprofile.a.o pstartup.a.o -o _startupProfile.o -setfile -t CgOb -c 3PRM _startupProfile.o +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pprofile.a.o pstartup.a.o -o _startupProfile.xo +setfile -t CgOb -c 3PRM _startupProfile.xo + +ppcasm -sym off -typecheck ptrace.a -o ptrace.a.o +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x ptrace.a.o pstartup.a.o -o _startupTrace.xo +setfile -t CgOb -c 3PRM _startupTrace.xo + +mrc -typecheck relaxed -w off -sym off -d POWER -d G_POWER mfileIO3.c +ppcasm -sym off -typecheck pfileIO3.a -o pfileIO3.a.o +PPCLink -sym off -xm library pfileIO3.a.o mfileIO3.c.o -o _library.xo +setfile -t CgOb -c 3PRM _library.xo + +Set -e CIncludes 'Programs:Metrowerks CodeWarrior 6.0:Metrowerks CodeWarrior:Carbon Support:Universal Interfaces:CIncludes,Programs:MPW:Interfaces:CIncludes' + +mrc -w off -sym off -d POWER -d G_POWER -d WRITE_HEAP mcon.c -o mcon.c.x +mrc -sym off -d POWER -d G_POWER mwrite_heap.c -o mwrite_heap.c.x +ppcasm -sym off -d PROFILE=0 -d LINUX=0 -typecheck pstartup.a -o pstartup.a.o +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pstartup.a.o -o _startup.cxo +setfile -t CgOb -c 3PRM _startup.cxo + +mrc -w off -sym off -d POWER -d G_POWER -d WRITE_HEAP -d TIME_PROFILE -d LINUX=0 mcon.c -o mcon.c.x +ppcasm -sym off -d PROFILE=1 -d LINUX=0 -typecheck pstartup.a -o pstartup.a.o +ppcasm -d POWER601=0 -d LINUX=0 -sym off -typecheck pprofile.a -o pprofile.a.o +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pprofile.a.o pstartup.a.o -o _startupProfile.cxo +setfile -t CgOb -c 3PRM _startupProfile.cxo ppcasm -d POWER601=1 -sym off -typecheck pprofile.a -o pprofile.a.o -PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pprofile.a.o pstartup.a.o -o _startupProfile601.o -setfile -t CgOb -c 3PRM _startupProfile601.o +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x pprofile.a.o pstartup.a.o -o _startupProfile601.cxo +setfile -t CgOb -c 3PRM _startupProfile601.cxo ppcasm -sym off -typecheck ptrace.a -o ptrace.a.o -PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x ptrace.a.o pstartup.a.o -o _startupTrace.o -setfile -t CgOb -c 3PRM _startupTrace.o - +PPCLink -sym off -xm library mcon.c.x mwrite_heap.c.x ptrace.a.o pstartup.a.o -o _startupTrace.cxo +setfile -t CgOb -c 3PRM _startupTrace.cxo mrc -typecheck relaxed -w off -sym off -d POWER -d G_POWER mfileIO3.c ppcasm -sym off -typecheck pfileIO3.a -o pfileIO3.a.o -PPCLink -sym off -xm library pfileIO3.a.o mfileIO3.c.o -o _library.o -setfile -t CgOb -c 3PRM _library.o +PPCLink -sym off -xm library pfileIO3.a.o mfileIO3.c.o -o _library.cxo +setfile -t CgOb -c 3PRM _library.cxo diff --git a/macho/pprofile.a b/macho/pprofile.a index 84d2022..0146418 100644 --- a/macho/pprofile.a +++ b/macho/pprofile.a @@ -1185,6 +1185,8 @@ init_profiler: .if 1 lea_ r3,_stack_size lwz r3,0(r3) + addi r3,r3,4095 + rlwinm r3,r3,0,0,31-12 .else li r3, (512*1024) % 65536 addis r3,r3,(512*1024) / 65536 diff --git a/macho/pstartup.a b/macho/pstartup.a index 8079ede..9fa7b44 100644 --- a/macho/pstartup.a +++ b/macho/pstartup.a @@ -155,7 +155,8 @@ ZERO_ARITY_DESCRIPTOR_OFFSET = (-12) .comm end_a_stack,4 .comm end_b_stack,4 .endif - .comm halt_sp,4 + .comm _halt_sp,4 + .globl _halt_sp # comment number of long words requested from the garbage collector .comm alloc_size,4 .comm basic_only,4 @@ -431,6 +432,7 @@ entier_constants_and_buffers: .globl _IO_error .globl print_error .globl stack_overflow + .globl _stack_overflow .globl out_of_memory_4 @@ -617,7 +619,11 @@ _abc_main: lwz o0,0(o0) stwu sp,-64(sp) + .if 1 + bl _allocate_a_stack + .else bl L_NewPtr$stub + .endif addi sp,sp,64 cmpwi 0,o0,0 @@ -786,7 +792,7 @@ no_mark2: add d0,a6,d0 stw d0,0(o0) - lea o0,halt_sp + lea o0,_halt_sp stw sp,0(o0) .if EXCEPTIONS @@ -2494,7 +2500,7 @@ collect: lwz a0,0(o0) sub o0,a4,a0 .if MACOSX - lea o1,halt_sp + lea o1,_halt_sp lwz d0,0(o1) .else lea o1,_stack_size @@ -3392,7 +3398,11 @@ no_copy_garbage_collection: add d0,d0,d1 b end_garbage_collect +_stack_overflow: stack_overflow: + lea o0,_halt_sp + lwz sp,0(o0) + bl _add_execute_time lea o0,stack_overflow_string @@ -3455,8 +3465,12 @@ print_error: .else baddi sp,64 .endif + halt: + lea o0,_halt_sp + lwz sp,0(o0) + .if PROFILE mflr r0 stwu r0,-4(sp) @@ -3471,8 +3485,6 @@ halt: bne e__Exceptions__sraise__exception .endif - lea o0,halt_sp - lwz sp,0(o0) .if 0 lea o0,_flags lwz d0,0(o0) diff --git a/macho/ptrace.a b/macho/ptrace.a index 05de0e3..4cb6588 100644 --- a/macho/ptrace.a +++ b/macho/ptrace.a @@ -484,6 +484,8 @@ init_profiler: .if 1 lea_ r3,_stack_size lwz r3,0(r3) + addi r3,r3,4095 + rlwinm r3,r3,0,0,31-12 .else li r3, (512*1024) % 65536 addis r3,r3,(512*1024) / 65536 diff --git a/mcon.c b/mcon.c index add8c69..594c6a6 100644 --- a/mcon.c +++ b/mcon.c @@ -7,6 +7,7 @@ #define NEW_HEADERS #define G_POWER #define FLUSH_PORT_BUFFER +#define STACK_OVERFLOW_EXCEPTION_HANDLER #ifdef MACHO # define NEWLINE_CHAR '\r' @@ -45,6 +46,170 @@ extern void sprintf (char *,...); #ifndef NEW_HEADERS # include #endif +#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER +# ifdef MACHO +# include +# else +# include +# include +# include +# include +# include +# define SIGBUS 10 +# define SIGSEGV 11 +# define SIG_DFL (void (*)())0 +# define SIG_IGN (void (*)())1 + struct sigaction { + void (*sa_handler)(); + unsigned int sa_mask; + int sa_flags; + }; + struct sigaltstack { + char *ss_sp; + int ss_size; + int ss_flags; + }; + struct sigcontext { + int sc_onstack; + int sc_mask; + int sc_ir; + int sc_psw; + int sc_sp; + void *sc_regs; + }; + struct vm_region_basic_info { + int protection; + int max_protection; + unsigned int inheritance; + int shared; + int reserved; + int offset; + int behavior; + unsigned short user_wired_count; + }; + + static CFBundleRef systemBundle=NULL; + + static int initSystemBundle (void) + { + FSRefParam fileRefParam; + FSRef fileRef; + OSErr error; + CFURLRef url; + + { + int i; + char *p; + + p=(char*)&fileRefParam; + for (i=0; isc_ir); + registers = &((int *)scp->sc_regs)[2]; + + switch (instruction>>26){ + case 36: /* stw */ case 37: /* stwu */ + case 38: /* stb */ case 39: /* stbu */ + case 44: /* sth */ case 45: /* sthu */ + case 47: /* stmw */ + case 54: /* stfd */ case 55: /* stfdu */ + { + int reg_a,a_aligned_4k; + + reg_a=(instruction>>16) & 31; + a=(short)instruction; + if (reg_a) + a+=registers[reg_a]; + + a_aligned_4k = (int)a & -4096; + + if (a_aligned_4k==(int)b_stack_guard_page || a_aligned_4k==(int)a_stack_guard_page){ + scp->sc_ir = (int)&stack_overflow; + registers[1]=(int)halt_sp; + return; + } + } + } + + old_sa_p = sig==SIGBUS ? &old_BUS_sa : &old_SEGV_sa; + + if (old_sa_p->sa_handler==SIG_DFL || old_sa_p->sa_handler==SIG_IGN) + sigaction (sig,old_sa_p,NULL); + else +# ifdef MACHO + old_sa_p->sa_handler (sig,sip,scp); +# else + call_function_3 (sig,sip,scp,old_sa_p->sa_handler); +# endif +} + +# ifndef MACHO +extern int *get_TOC (void); +# endif + +static void install_clean_exception_handler (void) +{ + { + struct vm_region_basic_info vm_region_info; +# ifdef MACHO + vm_address_t vm_address,previous_address; + mach_msg_type_number_t info_count; + memory_object_name_t object_name; + vm_size_t vm_size; +# else + int vm_address,previous_address; + int info_count; + int object_name; + int vm_size; + int *stack_top; +# endif + int r,var_on_stack; + + vm_address=(int)&var_on_stack; + + info_count=sizeof (vm_region_info); +# ifdef MACHO + r=vm_region (mach_task_self(),&vm_address,&vm_size,VM_REGION_BASIC_INFO,(vm_region_info_t)&vm_region_info,&info_count,&object_name); +# else + r=vm_region (mach_task_self(),&vm_address,&vm_size,10,(void*)&vm_region_info,&info_count,&object_name); +# endif + if (r!=0) + return; + +#ifndef MACHO + stack_top=(int*)(vm_address+vm_size); +#endif + + do { + previous_address=vm_address; + vm_address=vm_address-1; + + info_count=sizeof (vm_region_info); +# ifdef MACHO + r=vm_region (mach_task_self(),&vm_address,&vm_size,VM_REGION_BASIC_INFO,(vm_region_info_t)&vm_region_info,&info_count,&object_name); +# else + r=vm_region (mach_task_self(),&vm_address,&vm_size,10,(void*)&vm_region_info,&info_count,&object_name); +# endif + } while (vm_address!=previous_address && r==0); + + b_stack_guard_page=(int*)((int)previous_address-4096); + +#ifndef MACHO + { + int stack_size_aligned_4k; + + stack_size_aligned_4k = (stack_size+4095) & -4096; + if ((unsigned int)b_stack_guard_page < (unsigned int)((int)stack_top-stack_size_aligned_4k-4096)){ + b_stack_guard_page=(int*)((int)stack_top-stack_size_aligned_4k-4096); + vm_protect (mach_task_self(),(int)b_stack_guard_page,4096,0,0); + } + } +#endif + } + + { + struct sigaltstack sa_stack; + void *signal_stack; + struct sigaction sa; + +# ifdef MACHO + signal_stack=(int*)malloc (MINSIGSTKSZ); +# else + signal_stack=(int*)NewPtr (8192); +# endif + if (signal_stack!=NULL){ +# ifndef MACHO + int *handler_trampoline; +# endif + + sa_stack.ss_sp=signal_stack; +# ifdef MACHO + sa_stack.ss_size=MINSIGSTKSZ; +# else + sa_stack.ss_size=8192; +# endif + sa_stack.ss_flags=0; + + sigaltstack (&sa_stack,NULL); + +# ifdef MACHO + sa.sa_handler=&clean_exception_handler; + sigemptyset (&sa.sa_mask); + sa.sa_flags=SA_ONSTACK;//SA_SIGINFO; +# else + handler_trampoline = (int*) NewPtr (24); + if (handler_trampoline!=NULL){ + int *handler_address,*toc_register; + + handler_address=*(int**)&clean_exception_handler; + toc_register=get_TOC(); + +# define i_dai_i(i,rd,ra,si)((i<<26)|((rd)<<21)|((ra)<<16)|((unsigned short)(si))) +# define addis_i(rd,ra,si) i_dai_i (15,rd,ra,si) +# define addi_i(rd,ra,si) i_dai_i (14,rd,ra,si) +# define lis_i(rd,si) addis_i (rd,0,si) +# define bctr_i() ((19<<26)|(20<<21)|(528<<1)) +# define mtspr_i(spr,rs) ((31<<26)|((rs)<<21)|(spr<<16)|(467<<1)) +# define mtctr_i(rs) mtspr_i (9,rs) + + handler_trampoline[0]=lis_i (6,((int)handler_address-(short)handler_address)>>16); + handler_trampoline[1]=addi_i (6,6,(short)handler_address); + handler_trampoline[2]=mtctr_i (6); + handler_trampoline[3]=lis_i (2,((int)toc_register-(short)toc_register)>>16); + handler_trampoline[4]=addi_i (2,2,(short)toc_register); + handler_trampoline[5]=bctr_i(); + + __icbi (handler_trampoline,0); + __icbi (handler_trampoline,20); + + sa.sa_handler=(void(*)())handler_trampoline; + sa.sa_mask=0; + sa.sa_flags=1; + } +# endif + sigaction (SIGSEGV,&sa,&old_SEGV_sa); + sigaction (SIGBUS,&sa,&old_BUS_sa); + } + } +} +#endif + int main (void) { Handle stack_handle,font_handle; @@ -1452,6 +1825,10 @@ int main (void) heap_size=(stack_p[2]+7) & ~7; flags=stack_p[3]; +#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER + install_clean_exception_handler(); +#endif + #ifdef SIMULATE n_processors=stack_p[1]; if (n_processors<1) @@ -1484,6 +1861,7 @@ int main (void) #endif font_id=-1; + font_handle=GetResource ('Font',128); if (font_handle!=NULL){ @@ -1503,8 +1881,6 @@ int main (void) if (!init_terminal()) return 1; -/* srand (TickCount()); */ - #ifdef G_POWER wait_next_event_available=1; #else @@ -1587,7 +1963,7 @@ int main (void) return 0; } -#ifdef TIME_PROFILE +#if defined (TIME_PROFILE) || defined (MACHO) void create_profile_file_name (unsigned char *profile_file_name) { unsigned char *cur_ap_name,*end_profile_file_name; diff --git a/pprofile.a b/pprofile.a index 7adc9f2..34079c0 100644 --- a/pprofile.a +++ b/pprofile.a @@ -340,7 +340,7 @@ profile_l: lwz r12,Globals.end_profile_stack(r5) endif stw r6,Globals.stack_pointer(r5) - if CHECK_STACK_OVERFLOWS + if CHECK_STACK_OVERFLOWS cmpw r6,r12 bge profile_stack_overflow endif @@ -1166,6 +1166,8 @@ init_profiler: if 1 lea r3,stack_size lwz r3,0(r3) + addi r3,r3,4095 + rlwinm r3,r3,0,0,31-12 else li r3, (512*1024) % 65536 addis r3,r3,(512*1024) / 65536 diff --git a/pstartup.a b/pstartup.a index 4182bfb..95972d3 100644 --- a/pstartup.a +++ b/pstartup.a @@ -75,6 +75,7 @@ MACOSX set 1 SHARE_CHAR_INT set 1 MY_ITOS set 1 FINALIZERS set 1 +STACK_OVERFLOW_EXCEPTION_HANDLER set 1 MEASURE_GC set 0 COPIED_VECTOR set 1 @@ -327,6 +328,9 @@ entier_constants_and_buffers: export free_finalizer_list comm free_finalizer_list,4 endif + if STACK_OVERFLOW_EXCEPTION_HANDLER + import .allocate_a_stack + endif align 1 @@ -618,7 +622,11 @@ abc_main: ori sp,sp,28 stwu g0,-(64+28)(sp) + if STACK_OVERFLOW_EXCEPTION_HANDLER + bl .allocate_a_stack + else bl .NewPtr + endif nop lwz sp,0(sp) @@ -3483,6 +3491,9 @@ no_copy_garbage_collection: b end_garbage_collect stack_overflow: + lea o0,halt_sp + lwz sp,0(o0) + bl .add_execute_time lea o0,stack_overflow_string @@ -3546,7 +3557,6 @@ print_error: addi sp,sp,64 endif halt: - if PROFILE mflr r0 stwu r0,-4(sp) @@ -3561,8 +3571,9 @@ halt: bne e__Exceptions__sraise__exception endif - lea o0,halt_sp + lea o0,halt_sp lwz sp,0(o0) + if 0 lea o0,flags lwz d0,0(o0) @@ -5965,6 +5976,103 @@ entier_real_2: bctr + if MACOSX + export .call_function_0{PR} + csect .call_function_0{PR} + mflr r0 + stw r0,8(sp) + subi sp,sp,64 + + stw RTOC,20(sp) + lwz RTOC,4(r3) + lwz r3,0(r3) + mtctr r3 + bctrl + lwz RTOC,20(sp) + + lwz r0,64+8(sp) + addi sp,sp,64 + mtlr r0 + blr + + export .call_function_2{PR} + csect .call_function_2{PR} + mflr r0 + stw r0,8(sp) + subi sp,sp,64 + + stw RTOC,20(sp) + lwz RTOC,4(r5) + lwz r5,0(r5) + mtctr r5 + bctrl + lwz RTOC,20(sp) + + lwz r0,64+8(sp) + addi sp,sp,64 + mtlr r0 + blr + + export .call_function_3{PR} + csect .call_function_3{PR} + mflr r0 + stw r0,8(sp) + subi sp,sp,64 + + stw RTOC,20(sp) + lwz RTOC,4(r6) + lwz r6,0(r6) + mtctr r6 + bctrl + lwz RTOC,20(sp) + + lwz r0,64+8(sp) + addi sp,sp,64 + mtlr r0 + blr + + export .call_function_5{PR} + csect .call_function_5{PR} + mflr r0 + stw r0,8(sp) + subi sp,sp,64 + + stw RTOC,20(sp) + lwz RTOC,4(r8) + lwz r8,0(r8) + mtctr r8 + bctrl + lwz RTOC,20(sp) + + lwz r0,64+8(sp) + addi sp,sp,64 + mtlr r0 + blr + + export .call_function_7{PR} + csect .call_function_7{PR} + mflr r0 + stw r0,8(sp) + subi sp,sp,64 + + stw RTOC,20(sp) + lwz RTOC,4(r10) + lwz r10,0(r10) + mtctr r10 + bctrl + lwz RTOC,20(sp) + + lwz r0,64+8(sp) + addi sp,sp,64 + mtlr r0 + blr + + export .get_TOC{PR} + csect .get_TOC{PR} + mr r3,RTOC + blr + endif + macro te &address tc &address{TC},&address diff --git a/ptrace.a b/ptrace.a index e7f5e63..3e18751 100644 --- a/ptrace.a +++ b/ptrace.a @@ -469,6 +469,8 @@ init_profiler: if 1 lea r3,stack_size lwz r3,0(r3) + addi r3,r3,4095 + rlwinm r3,r3,0,0,31-12 else li r3, (512*1024) % 65536 addis r3,r3,(512*1024) / 65536 -- cgit v1.2.3