X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f From: "tim" Newsgroups: comp.os.msdos.djgpp Subject: Re: protecting program memory Date: 26 Mar 2007 03:20:45 -0700 Organization: http://groups.google.com Lines: 130 Message-ID: <1174904445.122516.65450@l75g2000hse.googlegroups.com> References: <46074baf DOT sandmann AT clio DOT rice DOT edu> NNTP-Posting-Host: 217.155.149.201 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1174904446 1880 127.0.0.1 (26 Mar 2007 10:20:46 GMT) X-Complaints-To: groups-abuse AT google DOT com NNTP-Posting-Date: Mon, 26 Mar 2007 10:20:46 +0000 (UTC) In-Reply-To: <46074baf.sandmann@clio.rice.edu> User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20060601 Firefox/2.0.0.2 (Ubuntu-edgy),gzip(gfe),gzip(gfe) X-HTTP-Via: 1.1 localhost:8080 (squid/2.5.STABLE9) Complaints-To: groups-abuse AT google DOT com Injection-Info: l75g2000hse.googlegroups.com; posting-host=217.155.149.201; posting-account=lGMSoA0AAAAj3K6TdfxB2w_vj0YEAdck To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On Mar 26, 5:27 am, Charles Sandmann wrote: > > # Is there an easy way to protect the memory used to store the > > # program op codes from a rogue memory write from within the > > # application? I have a large (100,000+ line) DJGPP > > # application which sometimes crashes with SIGILL - It would > > # seem the program is cannibalizing itself! In order > > # to find how this is happening, I would like to protect the > > # entire block of memory that contains the application code > > # so that an exception occurs at the point the corruption occurs > > # rather than the point that the corrupted code is executed. > > # I guest I need to make the memory block read only, but I am > > # not sure how to do that. > > Not without DPMI 1.0, you can't. > > Correct. But CWSDPMI implements enough of the DPMI 1.0 specification > that you can make pages readonly. This is the same API which is used > to make the "null" page non-mapped to catch all references to null pointers. > > > You can get a pointer to the beginning of code and its size > > by applying some mild abuse of GCC and the linker map: > > extern char* _text asm(".text"); > > extern char* _etext asm("etext"); > > static char* __my_progstart = NULL; > > static size_t __my_progsize = 0; > > __my_progstart = (char*) &_text; > > __my_progsize = (&_etext - &_text) - sizeof(void*); > > There are some non-clean parts of the libc which have writeable code > sections, so you will need to identify those and keep them as writeable. > If I remember correctly they are in the exception handling code and > maybe the stub itself. > > I don't remember completely, but you should check for the > mprotect() function. > > It's been a long time, but I remember supporting a memory allocation > package which protected it's control structures and fencing it's allocated > memory using these routines. Thanks Maybe I have misunderstood something, but I tried the following and it did not do what I expected. If I understand correctly, this code should fall over with a protection fault when it attempts to execute the memset() function. It does not. It fails with a SIGSEGV when it attempts to execute the corrupted function. The mprotect() function is returning a zero suggesting that the memory was protected, but it is not preventing the write. I compile with no optimization djgpp -g test.c This is all running under normal DOS (Win 98 DOS without Windows running at all). The DPMI is provided by CWSDPMI ("CWSDPMI V0.90+ (r5) Copyright (C) 2000 CW Sandmann ABSOLUTELY NO WARRANTY") - It is called by the stub in default mode, in other words, I do not all CWSDPMI explicitly. If I run CWSDPMI with -x the mprotect() function returns -1 - Which I expected as it only uses DPMI 0.9 calls As a matter of interest, why do I need to subtract size of (void*) from the program size? I did try page aligning both the start and the size variables, but it made no difference. Any ideas? #include #include #include #include #include #include void a_function(void); int main (void) { char *ptr = (char*) a_function; extern char* _text asm(".text"); extern char* _etext asm("etext"); static char* __my_progstart = NULL; static size_t __my_progsize = 0; __my_progstart = (char*) &_text; __my_progsize = (&_etext - &_text) - sizeof(void*); //protect the application memory and print the result of the mprotect function. printf("%d - %d\n", mprotect(__my_progstart, __my_progsize, PROT_READ) , (int) __my_progsize); //wait for a key press. getkey(); //call a_function - This should work fine. a_function(); //corrupt the function, If all is well the program should crash here with a protection fault. memset ((char*) ptr + 5, 0, 10); //If the protection worked, this line should not get printed! printf ("The function is now broken!\n"); //try calling the function again, It will crash because if it corrupt a_function(); return (0); } void a_function(void) { int a = 10; int b = 20; int c = 30; int d = 40; printf ("a=%d; b=%d, c=%d, d=%d\n",a,b,c,d); }