I'm trying to use mprotect to change memory protections of the .text and .rodata segments of an already loaded shared library.
Code:
/* Wrapper for mprotect and VirtualProtect */
int MemoryProtect(void *addr, size_t len, unsigned long newProt, unsigned long *oldProt, char memType) {
int retVal;
#ifdef __linux__
maddress alignAddr = ((maddress)addr + pageSize - 1) & ~(pageSize - 1);
retVal = mprotect((void*)alignAddr, pageSize, newProt);
switch (memType) {
case MEMTYPE_CODE:
*oldProt = MPROT_CODE;
break;
case MEMTYPE_RODATA:
*oldProt = MPROT_RODATA;
break;
default:
*oldProt = MPROT_CODE;
break;
}
#else
retVal = VirtualProtect(addr, len, newProt, oldProt);
if (retVal == 0) {
retVal = -1;
} else {
retVal = 0;
}
#endif
MF_Log("MemoryProtect called. Return value is %d", retVal);
return retVal;
}
I'm trying to get this working on both Linux and Windows, hence the #ifdef. The Windows code works perfectly fine. But it's the Linux part that doesn't seem to be working.
So I need to take an arbitrary memory address which is supposed to be in the .text or .rodata segments, align it to a page, and then use mprotect to change permissions. maddress is a type I created using typedef. It's either a uint32 or unit64 depending on whether the machine is x86 or AMD64.
pageSize is assigned a value earlier using sysconf(_SC_PAGESIZE). So when I call my MemoryProtect function and then proceed to write to the memory address afterward I will get a segfault. Now mprotect is returning 0, meaning there are supposedly no errors in changing the protection I guess. But it's still not working. I guess the way I tried aligning the address is incorrect? I did take the alignment code from a man page somewhere on the Internet, but I did have to modify it some. Maybe that is what it wrong... And my shared library, the one I'm writing is already attached to the process, so I should have sufficient access I think... But I really don't know.
But on the other hand, does the Linux kernel have special protections against changing the protection of the .text or .rodata segments? Maybe that is the problem instead. I'm not sure about it though.
Thanks in advance.