Mail Archives: djgpp/2007/04/09/07:46:10
"tim" <tim DOT nicholson AT skyforcekent DOT com> wrote in message
news:1174904445 DOT 122516 DOT 65450 AT l75g2000hse DOT googlegroups DOT com...
<snip>
>
> 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.
>
>It does not.
I'm not seeing that. I'm using Win98SE (both Windows and v7.10 DOS) and
v2.03 of DJGPP. But, I changed your program slightly...
> Any ideas?
>
Yes.
> #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;
Casts of a function pointer to other types or objects are illegal in
standardized C. Use '-pedantic' to catch this. Change line to:
void (* ptr)(void);
>
> extern char* _text asm(".text");
> extern char* _etext asm("etext");
> static char* __my_progstart = NULL;
> static size_t __my_progsize = 0;
int status;
>
> __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);
>
I'd separate the printf() and mprotect() calls, and exit() if not a valid
status. The mprotect() goes into prior to the printf(). So, the printf()
can cause a failure depending on PROT_NONE, PROT_READ, PROT_WRITE. Change
the printf() line to:
status = mprotect(__my_progstart, __my_progsize, PROT_WRITE);
printf("%d - %d\n",status, (int) __my_progsize);
if(status==-1)
{
printf("not all pages could be locked.\n");
return(0);
}
> //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);
All is not well here... You can't legally cast function pointers in ANSI-C
(or ISO-C). A cast of a function pointer to a 'void *' or a pointer to an
object is allowed under pre-ANSI-C, though. You can legally assign function
pointer or zero to a another function pointer. Again, '-pedantic' will warn
about this. Change the memset() line to:
ptr = &a_function; /* legal in ANSI-C if ptr is a function pointer */
/* the 'void *' cast of a function pointer below isn't legal in ANSI-C
*/
/* conversion to 'void *' is valid in non-ANSI C */
memset ((unsigned char *)(((unsigned long)(void *)ptr) + 5), 0, 10);
I.e., the 'void *' is the only allowable cast for a function pointer (for
non-ANSI-C). The 'unsigned long' cast is to be able to perform arithmetic
since arithmetic isn't allowed on 'void *' types. The 'unsigned char *'
cast is to convert the resultant value to an address pointer, a byte in
size, for memset(). A standardized C byte is the minimal addressable group
of bits, not 8-bits as defined everywhere else.
> //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);
> }
>
Once, those changes are made. I get the following under DOS (v7.10 for
Win98SE, using CWSDPMI r5):
PROT_NONE causes PAGE_FAULT after mprotect()
PROT_READ causes PAGE_FAULT on memset()
PROT_WRITE causes SIG_SEGV on second call to a_function(), followed by
PAGE_FAULT
Of course, in a Win98SE command prompt (using Windows DPMI, not CWSDPMI), it
exits properly with the -1 return from mprotect() as "not all pages could be
locked."
Rod Pemberton
- Raw text -