5
votes

Why does the following program not crash when it is executed, but crash with a segfault in GDB? Compiled with GCC 4.5.2 on a 32-bit x86 (Athlon 64, if it should matter).

#include <stdio.h>
#include <string.h>

int modify(void)
{
        __asm__("mov $0x41414141, %edx"); // Stray value.
        __asm__("mov $0xbffff2d4, %eax"); // Addr. of ret pointer for function().
        __asm__("mov %edx, (%eax)");
}

int function(void)
{
        modify();

        return 0;
}

int main(int argc, char **argv)
{
        function();

        return 0;
}

The mov $0xbffff2d4, %eax was determined using GDB to find the address where the return pointer was stored for the "function" function. This will probably be different on a different system. ASLR was disabled for this.

When I execute the program, nothing happens. There is no report of a crash in dmesg either. However when I execute the same program in GDB:

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
=> 0x41414141:  Cannot access memory at address 0x41414141

This is what I expect should happen when I execute the program normally as well. I do indeed get segfaults as usual when other programs crash, and I can easily write a small program that crashes with a nice segfault. But why does this particular program not crash with a segfault?

1
Is 0xbffff2d4 the address of the return pointer for the function every time you run the program? Doesn't seem like it would be to me.Trevor Arjeski
Shouldn't that address be relative to some offset?user210870
The return address is stored at 0xbffff2d4, every time, according to GDB. If I enabled ASLR then that obviously would change. It will also be different on a different computer.csstudent2233
Why should the address be relative to some offset?csstudent2233

1 Answers

2
votes

Even with full ASLR disabled, you may still get randomized stack and heap. You can turn that off globally using the norandmaps kernel boot parameter or at runtime by setting /proc/sys/kernel/randomize_va_space to zero. It's also part of the process personality.

In GDB, you can tweak this using the disable-randomization setting:

(gdb) help set disable-randomization
Set disabling of debuggee's virtual address space randomization.
When this mode is on (which is the default), randomization of the virtual
address space is disabled.  Standalone programs run with the randomization
enabled by default on some platforms.

As a small test program to illustrate this, you can print the address of a local variable, such as:

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("%p\n", &argc);
    return 0;
}