- Community Home
- >
- Servers and Operating Systems
- >
- Operating Systems
- >
- Operating System - Linux
- >
- executing an mmaped area fails
Categories
Company
Local Language
Forums
Discussions
Forums
- Data Protection and Retention
- Entry Storage Systems
- Legacy
- Midrange and Enterprise Storage
- Storage Networking
- HPE Nimble Storage
Discussions
Discussions
Discussions
Forums
Forums
Discussions
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
- BladeSystem Infrastructure and Application Solutions
- Appliance Servers
- Alpha Servers
- BackOffice Products
- Internet Products
- HPE 9000 and HPE e3000 Servers
- Networking
- Netservers
- Secure OS Software for Linux
- Server Management (Insight Manager 7)
- Windows Server 2003
- Operating System - Tru64 Unix
- ProLiant Deployment and Provisioning
- Linux-Based Community / Regional
- Microsoft System Center Integration
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Community
Resources
Forums
Blogs
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 05:37 AM
тАО06-22-2008 05:37 AM
1) mmaps an area that is set to executable.
2) copy some NOP instructions into it.
3) calls the executable area
At step three it will fail with SIGILL.
It wont even execute the NOPs. Why ?
I'm expecting an SIGILL after the NOPs where BREAK (zeros) is found, but not before.
Environment: hppa2.0w-hp-hpux11.11 gcc4.1.1
compile with gcc and run (optionally under gdb):
//this code will only work on hp-ux11.11 running on parisc2.0
#include
#include
#include
#include
int main (int argc, char **argv)
{
unsigned int base;
void (*func)();
void * addr = mmap(0,0x1000,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
if(addr < 0){
fprintf(stderr, "mmap failed\n");
perror("mmap");
exit(-1);
}
base = (unsigned int) addr;
fprintf(stderr, "mmaped to %x\n", base);
*((unsigned int *) base + 0) = 0x08000240;
*((unsigned int *) base + 1) = 0x08000240;
*((unsigned int *) base + 2) = 0x08000240;
*((unsigned int *) base + 3) = 0x08000240;
*((unsigned int *) base + 4) = 0x08000240;
func = (void *) base;
fprintf(stderr, "calling %x\n", (unsigned int) func);
func();
fprintf(stderr, "done\n");
return 0;
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 07:57 AM
тАО06-22-2008 07:57 AM
Solution>At step 3) it will fail with SIGILL. It wont even execute the NOPs. Why?
Because you can't call code like that. You can't just make up a plabel out of thin air.
>I'm expecting an SIGILL after the NOPs where BREAK (zeros) is found, but not before.
How did you know where it aborted?
>if (addr < 0){
The proper error check is comparing with MAP_FAILED.
>func = (void*)base;
This is not a valid plabel.
So basically what you have to do is:
0) Read documentation and maybe give up. :-)
1) mmap an area that is set to executable.
2) copy some NOP instructions into it. And have a valid return instruction.
3) Flush ICACHE for the region.
4) Create valid plabel.
5) call the executable area
Here are some documentation links:
http://docs.hp.com/en/B2355-90654/index.html
3-7 Assembly Language Source for flush_cache Function
http://docs.hp.com/en/B2355-90654/ch03s11.html#fig-flush-cache
Unfortunately I don't see anything that talks about 4). At the time it was written, this would magically work but the magic was thrown away for performance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 10:00 AM
тАО06-22-2008 10:00 AM
Re: executing an mmaped area fails
Flushing the caches sound reasonable.
Adding following routine and calling it before calling into the mmaped area works.
from c:
call_flush_cache(base);
#define LANGUAGE_ASSEMBLY
.level 2.0
.text
.export call_flush_cache
call_flush_cache:
.proc
.callinfo entry_gr=18,save_rp
.entry
fic %r0(%r26)
fdc %r0(%r26)
sync
bv %r0(%rp)
nop
.exit
.procend
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 10:16 AM
тАО06-22-2008 10:16 AM
Re: executing an mmaped area fails
call_flush_cache(base);
This won't work in all cases. You need a start and length so you can flush the whole region. Why not use what was at that link?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 11:28 AM
тАО06-22-2008 11:28 AM
Re: executing an mmaped area fails
The question feels like a 'proof of concept' for some tricky solution.
Maybe you want to explain what the real problem is that you are trying to solve?
Generating and activating code on the fly is a cool technique, but rarely needed for 'normal' programming. It may be the right tool to generate special case sort or parse routines, to create virusses, and so on.
There may be easier and more portable solutions (state table) than hard coded instruction stream for an end-of-life-imminent (2008, end of support 2013platform.
fwiw,
Hein.
http://h40059.www4.hp.com/campaigns/golddust/downloads/transition_to_integrity.pdf
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 12:15 PM
тАО06-22-2008 12:15 PM
Re: executing an mmaped area fails
Dennis, Hein,, thanks for your input. Yes it is an proof of concept. It is an boiled down version of an runtime-loader (like sbcl/cmucl).
My previously attempt of overlapping mmap fails, I cant understand why, each mmap works by itself:
#include
#include
#include
#include
#include
int main (int argc, char **argv)
{
int fd;
void * addr = mmap((void *) 0x60000000, 0x1000000,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
if(addr == MAP_FAILED){
fprintf(stderr, "mmap failed\n");
perror("mmap anon");
exit(-1);
}
fd = open("core", O_RDONLY);
if(fd < 0){
perror("open");
exit(-1);
}
if(mmap((void *) 0x60001000, 0x0001000,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_FILE | MAP_FIXED,fd,0)
== MAP_FAILED){
perror("mmap file");
exit(-1);
}
close(fd);
return 0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 02:58 PM
тАО06-22-2008 02:58 PM
Re: executing an mmaped area fails
As in Lisp?
And I guess you already figured out that this is not something you could coerce dlopen / dlsym to do for you?
Maybe with help of the opts argument and RTLD_EXT_TEXT_ADDR and such?
Good luck!
Hein.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО06-22-2008 03:46 PM
тАО06-22-2008 03:46 PM
Re: executing an mmaped area fails
Do NOT trust any debugger to tell you that it has "perfectly good code" there.
All debuggers seem to have this problem, xdb, dde and gdb. They don't realize that the hardware is either 64 bit or 96 bit and then they truncate the address to 32 or 64 bit and point you to a location, even if it isn't the right one. (I.e. you need to compare space registers too.) The only correct debugger here is NMDEBUG on MPE/iX.
>My previously attempt of overlapping mmap fails, I cant understand why, each mmap works by itself:
mmap(2) on PA-RISC is very picky. It only wants one mapping for every page range. IPF is more forgiving.
By the way, a "better" NOP is 0x20000000.