Yes, see the section on randomize_va_space in the Linux kernel Documentation/sysctl/kernel.txt file. It describes the three possible values in /proc/sys/kernel/randomize_va_space that affect the layout randomization:
Originally Posted by oogabooga
It turns out I was mistaken in how much randomization there really is. Or actually, how little.
0 - Turn the process address space randomization off. This is the
default for architectures that do not support this feature anyways,
and kernels that are booted with the "norandmaps" parameter.
1 - Make the addresses of mmap base, stack and VDSO page randomized.
This, among other things, implies that shared libraries will be
loaded to random addresses. Also for PIE-linked binaries, the
location of code start is randomized. This is the default if the
CONFIG_COMPAT_BRK option is enabled.
2 - Additionally enable heap randomization. This is the default if
CONFIG_COMPAT_BRK is disabled.
There are a few legacy applications out there (such as some ancient
versions of libc.so.5 from 1996) that assume that brk area starts
just after the end of the code+bss. These applications break when
start of the brk area is randomized. There are however no known
non-legacy applications that would be broken this way, so for most
systems it is safe to choose full randomization.
Systems with ancient and/or broken binaries should be configured
with CONFIG_COMPAT_BRK enabled, which excludes the heap from process
address space randomization.
Consider this (a bit bastard, but illustrative) program:
When compiled normally (gcc source.c -o binary, plus optimization and/or warning flags) only local const, local, and dynamicvary. Using gcc-4.6.3, recompiling the binary does not affect the addresses. In other words, locations specified in the ELF binary for code (.text) and data (.data, .rodata, .bss -- as per objdump -t binary) do not vary; only stack (local variables) and dynamic allocations do.
static const int global_static_const = 1;
static int global_static = 2;
const int global_const = 3;
int global = 4;
static void static_func(void)
const int local_const = 5;
int local = 6;
dynamic = malloc(sizeof (1000000));
printf("global static const at %p\n", &global_static_const);
printf("global static at %p\n", &global_static);
printf("global const at %p\n", &global);
printf("local const at %p\n", &local_const);
printf("local at %p\n", &local);
printf("dynamic at %p\n", dynamic);
printf("stdin at %p\n", &stdin);
printf("global function at %p\n", &global_func);
printf("static function at %p\n", &static_func);
printf("local function at %p\n", &local_func);
printf("main() at %p\n", &main);
printf("fclose() at %p\n", &fclose);
However, if you compile with -fPIE, which tells gcc to compile a position independent executable, and/or with -fPIC, which tells gcc to compile to position independent code,
then in addition to local const, local, and dynamic, also stdin and fclose vary. This means that local variables, and variables and functions from dynamically linked libraries, will have randomized addresses. I haven't tried any benchmarking to see if and how this affects the generated code.
gcc -fPIE -W -Wall -O0 source.c -o binary
gcc -fPIC -W -Wall -O0 source.c -o binary
gcc -fPIE -fPIC -W -Wall -O0 source.c -o binary
I personally did learn something new from this: code and global variable address randomization is currently available easily only for dynamically loaded libraries, and then only if the binaries are compiled with appropriate options (-fPIC and/or -fPIE). I'm a bit embarrassed, to be honest.