Why did apple use (mach_header 's pointer subtract `__TEXT` 's vmaddr) to calculate slide value of ASLR

220 Views Asked by At

It is really confused me a lot! When I read apple open source code of getsecbyname.c. Some code In it:

uint8_t * 
getsectiondata(
const struct mach_header *mhp,
const char *segname,
const char *sectname,
unsigned long *size) {
    slide = 0;
    sp = 0;
    sgp = (struct segment_command *)
          ((char *)mhp + sizeof(struct mach_header));
    for(i = 0; i < mhp->ncmds; i++){
        if(sgp->cmd == LC_SEGMENT){
        if(strcmp(sgp->segname, "__TEXT") == 0){
            slide = (uintptr_t)mhp - sgp->vmaddr;
        }
    ......
}

I can understand what is ASLR(Address Space Layout Random). And I also know that slide's value should be equal to loader address subtract linker address: slide = L(loader address) - A(linker address). But why slide value in here which is slide = (uintptr_t)mhp - sgp->vmaddr;. Does that mean mhp(mach_header) is the loader address? I can constrainedly recognize "__TEXT"'s vmaddr is the linker address because which is read from the load command. But why the mach_header address become the loader address in here, which should be always 0x00000000 in my opinion.

And I have roughly read the source code of xnu of Apple. I read function load_machfile and function parse_machfile consisted in xnu source earnestly. However, I'm more confused now. I really appreciate if someone can help me!

1

There are 1 best solutions below

3
Siguza On

By necessity, the Mach-O header is at file offset 0 (otherwise it wouldn't be a header). And by convention, the __TEXT segment maps the content at file offset 0. So the address of the Mach-O header and that of the __TEXT segment are one and the same.

Now you just have to get the link-time value and the runtime value of that address, subtract one from the other and you have the slide. The value in sgp->vmaddr is the link-time one, because the Mach-O header is not modified during load (and it will usually be 0x100000000 for standalone executables if you didn't pass any custom linker options). Meanwhile, mhp is a live pointer so it is the same value, but with the slide applied.