Re: protecting program memory




"tim" <tim.nicholson@xxxxxxxxxxxxxxxx> wrote in message
news:1174904445.122516.65450@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
<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


.



Relevant Pages

  • Re: main return value stange question
    ... > by a mythical C99 implementation. ... > 2) There is no newline in the printf. ... to an int. ... A function pointer is passed, ...
    (comp.lang.c)
  • Re: get the address of a function??
    ... void hello ... Calling printf with no visible prototype invokes undefined behavior. ... Make it "int main". ... *But* there's no defined conversion from a function pointer to void* ...
    (comp.lang.c)
  • Function pointers to printf
    ... Can we have a function pointer to printf or any function with variable arguments? ... but could not compile. ... int main ...
    (comp.lang.cpp)
  • Function pointers to printf
    ... Can we have a function pointer to printf or any function with variable arguments? ... but could not compile. ... int main ...
    (comp.lang.c)
  • Re: function pointer tutorial may be helpful..
    ... A function pointer is a value that is the address of a function. ... static int my_function ... void young; ...
    (comp.lang.c)