Ubuntu 10.04, C, gcc, x86 Intel proc:
When trying to print the address of an environmental variable using printf, the address printed is not correct in this toy program (this is a consciously backward version in which I tried to isolate the source of the problem by saving the address value on the heap, not using a pointer directly as I read it can be overwritten, and using a pointer straight up produced the same issue):
#include <stdio.h>
#include <stdlib.h>
int main(){
const char* d = getenv("TEST");
unsigned i = (unsigned*) malloc(sizeof(unsigned));
i = (unsigned*) d;
printf("%s at location 0x%8d.\n", "TEST", i);
}
EDIT: same issue with this (the original) version)
int main(){
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
return 0;
}
This question has nothing to do with how to print a pointer. Kindly read on.
If I change the program to not print TEST’s address, but TEST as a string (its value), no problem.
However, the address returned is not the address at which the environmental variable is actually located before entering the print sub-routine; and which, by the above set-up, should be printed. Using main’s disassembly and TEST’s address in the eax register, I am referred to the proper location of the TEST variable, which is a little further down than main’s stack frame at about 0xbffffiii on my system (i any hex value). The address value printed is on the order of 0xbfeiiiii.
I don’t understand. Is this a security precaution to prevent environmental variables from being overwritten (eg, to smash the stack)? If yes, does the compiler really keep track of transferring the address as I do above, and silently adjusting its value?
Or am I missing something? (probably)
Many thanks.
P.S.: To remove imaginable sources of issues, I compiled first with no options, then:
gcc -O0 -static -fno-stack-protector -g program.c
I figured it out, following a comment by R.. further above who pointed me in the direction of ASLR.
I was unfamiliar with ASLR stack protection. What I describe is due to ASLR scrambling the memory address space to prevent prediction of the location of variables relative to it. ASLR has long been default switched on in LINUX kernels it appears.
To see what I meant, get su privileges, then enter (the precise integer to send might vary based on your distro; on mine it is 0, and the default 2. Also better confirm the file only contains 1 integer by first looking at it, as it does on my system):
Then run my little program again: it will report back the address I expected (around 0xbffffiii). After, obviously, restore old protection using
Many thanks for everyone who spend some of their time trying to help.