I am running a simple C Application which will get PID Of an process continuously.
This is running on an custom ARM Board.
pid_t GetStreamerPID()
{
pid_t pid = 0;
int ret = 0;
char line[100];
char command[50] = "pidof -s gst-launch-0.10";
memset(line, '\0', 100);
FILE *cmd = popen(command, "r");
if ( cmd == NULL )
{
perror("Popen\n");
exit(0);
}
ret = fread(line, sizeof(char), 20, cmd);
pclose(cmd);
pid = atoi(line);
return pid;
}
Randomly, the code is throwing segmentation Fault at pclose.. I am debugging this from past week and I am unable to find out the cause of the issue.
Attaching gdb backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x76e3a588 in free () from /lib/libc.so.6
(gdb) bt full
#0 0x76e3a588 in free () from /lib/libc.so.6
No symbol table info available.
#1 0x76e25c20 in fclose##GLIBC_2.4 () from /lib/libc.so.6
No symbol table info available.
#2 0x000109b4 in GetStreamerPID () at getPid.c:111
pid = 0
ret = 0
line = '\000' <repeats 99 times>
command = "pidof -s gst-launch-0.10", '\000' <repeats 25 times>
cmd = 0x136c008
#3 0x00010a50 in startStreamer () at getPid.c:147
command = '\000' <repeats 255 times>
pid = 0
#4 0x0001087c in CheckVideoState () at getPid.c:81
iVideoOn = 1
#5 0x00010a20 in MainLoop () at getPid.c:137
No locals.
#6 0x00010b74 in main () at getPid.c:183
No locals.
Also, one more wierd observation is , after I close gdb and run "reboot" command it throws segmentation fault. Again this is random, it can be any command..
I can provide you as much as information you want. Please help me in debugging this wierd issue...
Your crash is happening inside free.
Any such crash is a 99.99% sign that you have heap corruption elsewhere, and very likely has absolutely nothing to do with the code you've shown, or with pclose.
Tools such as Valgrind, Address Sanitizer, or GLIBC mcheck are your best bet.
Related
I am working on the book "HACKING Art Of Exploitation " exercise Convert2.c page 61.
Here's my code. Below is my question.
#include <stdio.h>
void usage(char *program_name) {
printf("Usage: %s <message> <# of times to repeat>\n", program_name);
exit(1);
}
int main(int argc, char *argv[]) {
int i, count;
// if(argc < 3) //if fewer than 3 arguments is used
// usage(argv[0]); // display usage message and exit
count = atoi(argv[2]); //convert the second arg into an interger
printf("Repeating %d times\n", count);
for(i=0; i < count; i++)
printf("%3d - %s\n", i, argv[1]); // print the first arg
}
GDB OUTPUT...
➜ git:(master) ✗ 👽 gdb -q a.out
Reading symbols from a.out...done.
(gdb) run test
Starting program: /home/fruitdealer/clones/C_zombie/hacking/a.out test
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0,
loc=0x7ffff7dd0560 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: No such file or directory.
(gdb) break main
Breakpoint 1 at 0x555555554707: file convert.c, line 14.
(gdb) where
#0 __GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0,
loc=0x7ffff7dd0560 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
#1 0x00007ffff7a29122 in __strtol (nptr=<optimized out>, endptr=endptr#entry=0x0, base=base#entry=10)
at ../stdlib/strtol.c:106
#2 0x00007ffff7a24690 in atoi (nptr=<optimized out>) at atoi.c:27
#3 0x000055555555471f in main (argc=2, argv=0x7fffffffdeb8) at convert.c:14
(gdb) run test
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/fruitdealer/clones/C_zombie/hacking/a.out test
Breakpoint 1, main (argc=2, argv=0x7fffffffdeb8) at convert.c:14
14 count = atoi(argv[2]); //convert the second arg into an interger
(gdb) cont
Continuing.
Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=endptr#entry=0x0, base=base#entry=10, group=group#entry=0,
loc=0x7ffff7dd0560 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: No such file or directory.
(gdb) x/3xw 0x7fffffffdeb8
0x7fffffffdeb8: 0xffffe220 0x00007fff 0xffffe250
(gdb) x/s 0xffffe220
0xffffe220: <error: Cannot access memory at address 0xffffe220>
(gdb) x/s 0xffffe250
0xffffe250: <error: Cannot access memory at address 0xffffe250>
(gdb) x/sw 0xffffe250
0xffffe250: <error: Cannot access memory at address 0xffffe250>
(gdb)
I posted all of gdb output because i wasn't sure how much of it you would need. My problem lies at the bottom of my GDB output when i run "x/s" on gdb and get the <error: Cannot access memory at address 0xffffe250> error.
On the book Jon Erickson is able to access 0xffffe220 and 0x00007fff and then he has an error on 0xffffe250 this part of memory.
What am i missing?
Why can't i access any of the three addresses in 0x7fffffffdeb8?
The first half of the address is cut off. If you notice, it takes 8 bytes to store the addresses because you are on a 64 bit machine, not 32. You are trying to access a truncated address.
Rather than three addresses at 0x7fffffffdeb8, you are looking at one and a half. Try accessing a byte that starts with 0x00007fff...
I have this simple script written in C:
#include <stdio.h>
void usage(char *program_name) {
printf("Usage: %s <message> <# of times to repeat>\n", program_name);
exit(1);
}
int main(int argc, char *argv[]) {
int i, count;
// if(argc < 3) // If less than 3 arguments are used,
// usage(argv[0]); // display usage message and exit.
count = atoi(argv[2]); // convert the 2nd arg into an integer
printf("Repeating %d times..\n", count);
for(i=0; i < count; i++)
printf("%3d - %s\n", i, argv[1]); // print the 1st arg
}
And I'm making some test with GDB.
I did this:
(gdb) run test
Starting program: /home/user/Desktop/booksrc/convert2 test
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
Obviusly it goes in segmentation fault because to work the program needs three argv. And I commented the lines that do the control. So it goes in error.
(gdb) where
#0 0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
#1 0x00007ffff7a53a80 in atoi () from /usr/lib/libc.so.6
#2 0x00005555555546ea in main (argc=2, argv=0x7fffffffe958) at convert2.c:14
(gdb) break main
Breakpoint 1 at 0x5555555546d2: file convert2.c, line 14.
(gdb) run test
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/user/Desktop/booksrc/convert2 test
Breakpoint 1, main (argc=2, argv=0x7fffffffe958) at convert2.c:14
14 count = atoi(argv[2]); // convert the 2nd arg into an integer
(gdb) cont
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
(gdb) x/3xw 0x7fffffffe958 // this is memory of the "argv" some line before
0x7fffffffe958: 0xffffebfe 0x00007fff 0xffffec22
(gdb) x/s 0xffffebfe
0xffffebfe: <error: Cannot access memory at address 0xffffebfe>
(gdb) x/s 0x00007fff
0x7fff: <error: Cannot access memory at address 0x7fff>
(gdb) x/s 0xffffec22
0xffffec22: <error: Cannot access memory at address 0xffffec22>
In theory, with "x/s" I should have seen the commandline in the first address and "test" in the second address and the null in the third. But nothing. If I copy paste that address to a ascii to string converter, it gives me data without any sense. What am I doing wrong?
Your platform uses 64bit pointers, so try :
(gdb) x/3xg 0x7fffffffe958
to display the 64bit pointers in the argv array, and then :
(gdb) x/s 0x00007fffffffebfe
or just :
(gdb) p argv[0]
First of all always check if the command line is correct
Uncomment the check from your code.
Then in the gdb set the arguments (before running it)
(gdb) set args "hello world" 12
So here's the code containing the printf (with line numbers, this is from think.c):
30: char *think = getRandomMemory();
31: printf("\33[2K\r");
32: if(think == NULL)
33: think = "NULL";
34: printf("I have an idea: %s\n", think);
35: parse(think);
36: freeMemory(think);
37: printf("> ");
And the code from getRandomMemory() which makes sure the returned pointer points to heap allocated space:
char *getRandomMemory()
{
char *ret;
// --SNIP--
size_t l = strlen(ret) + 1;
char *rret = getMemory(sizeof(char) * l);
for(int i = 0; i < l; i++)
rret[i] = ret[i];
printf("--- %s ---\n", rret);
return rret;
}
And finally this is what gdb gives me when running this. Please note that the "--- test ---" comes from " printf("--- %s ---\n", rret)" above:
(gdb) run
Starting program: /home/v10lator/Private/projekte/KI/Lizzy
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Loading Lizzy 0.1... Done!
> --- test ---
[New Thread 0x7ffff781f700 (LWP 32359)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff781f700 (LWP 32359)]
0x00007ffff7869490 in _IO_vfprintf_internal (s=<optimized out>, format=<optimized out>,
ap=ap#entry=0x7ffff781ee68) at vfprintf.c:1642
1642 vfprintf.c: Datei oder Verzeichnis nicht gefunden.
(gdb) bt
#0 0x00007ffff7869490 in _IO_vfprintf_internal (s=<optimized out>, format=<optimized out>,
ap=ap#entry=0x7ffff781ee68) at vfprintf.c:1642
#1 0x00007ffff7919235 in ___printf_chk (flag=1, format=<optimized out>) at printf_chk.c:35
#2 0x00000000004016bc in printf () at /usr/include/bits/stdio2.h:104
#3 run (first=<optimized out>) at think.c:34
#4 0x00007ffff7bc64c6 in start_thread (arg=0x7ffff781f700) at pthread_create.c:333
#5 0x00007ffff790a86d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
I really don't know what's wrong here, so hopefully someone sees the mistake.
//EDIT: Forgot the getMemory/freeMemory functions:
/*
* This allocates memory.
* The difference between usig malloc directly is that this function will
* print an error and exit the program in case something bad happens.
*/
char *getMemory(size_t size)
{
char *mem = malloc(size);
if(mem == NULL)
crashWithMsg("Internal error (malloc failed)!");
return mem;
}
/*
* This deallocates memory.
* The difference between using free directly is that this function will
* set the pointer to NULL afterwards.
*/
void freeMemory(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
The problem is your call to freeMemory:
freeMemory(think);
You've coded that function to take the address of the pointer to the memory to be freed, rather than the pointer itself. So you need to call it with:
freeMemory(&think);
[Deleted misstated assertion]
Why not use strcpy()?
Sorry, I'm new to c programming
As the title says, The code runs perfectly till the end of main where it returns 0. It then gives a seg fault with no reason why. Some answers said that maybe I wasnt freeing all that I malloced but I did. So I tried using gdb to figure out why. This was the first time I've ever used it.
This is the output:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7644f1d in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007ffff7644f1d in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff76450aa in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff760365b in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00007ffff76036f5 in exit () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x00007ffff75eaecc in __libc_start_main ()
from /lib/x86_64-linux-gnu/libc.so.6
#5 0x0000000000400bc9 in _start ()
My main:
int main(int argc, char *argv[]) {
if(argv[1] == NULL)
{
printf("Please enter the path to the map generating file as an argument.\n");
exit(0);
}
run(getName(), argv[1]);
return 0;
}
My program is a ncurses program, which i can (I believe I am) succesfully create the screen and then close it. I've checked that all the malloced variables have been freed as well.
Run is in a diffrent c file where I draw the ncurses board.
Any help would be appreciated.
It's not sure that gdb will give you the exact location when the corruption really happens. (the backtrace suggests it's a stack-related one)
For this kind of errors, the best tool is Valgrind, run your app with it.
(In my experience memory corruption errors could be tracked down and eliminated within minutes with Valgrind)
This is the code:
void i_log_ (int error, const char * file, int line, const char * fmt, ...)
{
/* Get error description */
char * str_err = get_str_error (errno);
remove_trailing_newl (str_err);
/* Format string and parameters */
char message [1024];
va_list ap;
va_start (ap, fmt);
vsprintf (message, fmt, ap);
va_end (ap);
/* Get time */
time_t t = time (NULL);
char stime [64];
char * temp = ctime (&t);
strncpy (stime, temp, sizeof stime - 1);
remove_trailing_newl (stime);
FILE * log;
#ifdef __WIN32__
#else
# ifdef P_LISTENER
log = fopen (I_LOG_FILE, "a+b");
flock (fileno (log), LOCK_EX);
# else /* shared file descriptor of log, lock before opening */
pthread_mutex_lock (& mutex);
log = fopen (I_LOG_FILE, "a+b");
# endif
#endif
if (log) {
if (error)
fprintf (log, ERR_FORMAT, stime, file, line, str_err, message);
else
fprintf (log, ERR_FORMAT_NO_ERRNO, stime, file, line, message);
}
#ifdef __WIN32__
free (str_err);
#else
# ifdef P_LISTENER
flock (fileno (log), LOCK_UN);
fclose (log);
# else
fclose (log);
pthread_mutex_unlock (& mutex);
# endif
#endif
return;
}
Although there is a lock mechanism, in this case the function is not called concurrently, so I think that's not the problem. However, the program receive a SIGABRT:
[...]
(gdb) c
Continuing.
Program received signal SIGHUP, Hangup. // It's OK, I sent this.
0x00dee416 in __kernel_vsyscall ()
(gdb) c
Continuing.
Program received signal SIGABRT, Aborted.
0x00dee416 in __kernel_vsyscall ()
(gdb) up
#1 0x0013ae71 in raise () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#2 0x0013e34e in abort () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#3 0x00171577 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#4 0x0017b961 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#5 0x0017d28b in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#6 0x0018041d in free () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#7 0x0019b0d2 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#8 0x0019b3c5 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#9 0x00199a9f in localtime () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#10 0x00199951 in ctime () from /lib/i386-linux-gnu/libc.so.6
(gdb) up
#11 0x08049634 in i_log_ (error=0, file=0x804b17d "src/group.c", line=53, fmt=0x804b128 "Setting up new configuration: listener type: %s, number: %d, http-log: %s, port: %d.") at src/error.c:42
42 char * temp = ctime (&t);
(gdb) print temp
$1 = 0x260000 ""
(gdb) print t
$2 = 1329935482
(gdb) print &t
$3 = (time_t *) 0xbff8a5b8
(gdb)
I haven't a clue. ctime is returning an empty string, and the man page don't mention this case. And come to think of it, I don't understand why it would return an empty string, and what's wrong with that code.
Any help is appreciated.
ctime isn't returning an empty string. It hasn't returned at all yet, because it crashed while trying to do its thing.
The crash is inside free(), so you're probably corrupting memory at some point before you called ctime(). If you're running on a supported platform, try using a tool like Valgrind to check your memory accesses.
Since the crash is happening down inside ctime() and the pointer you pass is valid, the problem is likely that you've already trampled out of bounds with memory (there's free() in the stack trace) somewhere else and the problem is only manifesting itself here.