Mail Archives: djgpp/2007/03/26/05:30:54
On Mar 26, 5:27 am, Charles Sandmann <sandm DOT DOT DOT AT clio DOT rice DOT edu> 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 <sys/mman.h> 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 <stdio.h>
#include <string.h>
#include <pc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <keys.h>
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);
}
- Raw text -