X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f From: "Rod Pemberton" Newsgroups: comp.os.msdos.djgpp Subject: Re: protecting program memory Date: Mon, 9 Apr 2007 07:43:19 -0400 Organization: Aioe.org NNTP Server Lines: 141 Message-ID: References: <46074baf DOT sandmann AT clio DOT rice DOT edu> <1174904445 DOT 122516 DOT 65450 AT l75g2000hse DOT googlegroups DOT com> NNTP-Posting-Host: IVw7K97ih4IohxRqyKkqFw.user.aioe.org X-Complaints-To: abuse AT aioe DOT org X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 X-Priority: 3 X-Newsreader: Microsoft Outlook Express 6.00.2800.1437 X-MSMail-Priority: Normal To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com "tim" wrote in message news:1174904445 DOT 122516 DOT 65450 AT l75g2000hse DOT googlegroups DOT com... > > 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 > #include > #include > #include > #include > #include > > 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