Can gdb automatically attach a process on a SIGSEGV - c

I have a faulty program that when execute receive a SIGSEGV.
I can use gdb like this:
$ gdb ./prog
But I would prefer that gdb catch the SIGSEGV from prog and attach it automatically.
$ ./prog
Segmentation Fault
(gdb) ...
Is there a way to do that?
Thanks

Hmm. You can set up a signal handler to launch the debugger with the current process. That way you can inspect the whole state "live".
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
const char *prog=0;
void fn(int signum)
{
char buf[256];
snprintf(buf,255,"ddd %s %d",prog,getpid());
system(buf);
}
int main(int argc, char **argv)
{
prog=argv[0];
signal(SIGSEGV,&fn);
int *p=0;
int k=*p;
}
UPDATE: Chaged according to the suggestions of miedwar and Fanatic23. Current Ubuntu distributions are configured to disallow debugging of non-child processes. See https://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process for a fix.

Well you can always create a core file and then analyse the callstack using gdb on that core. You can check out the man page for ulimit to do so.
Check this link for more info.

To add to Mainframe's answer you can link your app with libdebugme (or simply LD_PRELOAD it) to achieve similar functionality. For example:
DEBUGME_OPTIONS=handle_signals=1 LD_PRELOAD=libdebugme.so ./app

Related

glibc: unable to get unwind information for certain sections

I am currently facing issue with the glibc v2.22 where I am not able to get the proper unwind information.
When there is SIGABRT application, it is calling abort function from glibc. It should be using unwind information which is enabled in the build. However, it is scanning the stack (as indicated by the red line below the address in the screenshot) and providing the misleading information as shown in the screenshot attached (using sentry for analyzing the dump).
Here, do_crash is called which does assert(0) which then aborts the main application. While analyzing the dump, the do_crash function calls the _fini which is never in the main application's stack.
I have enabled unwind for the glibc by using CFLAGS += "-funwind-tables". I also tried with the flags such as -rdynamic and -fno-omit-frame-pointer but it was also of no use.
Am I missing something here? How can I get the complete backtrace of the signals, particularly SIGABRT?
Thanks in advance
When there is SIGABRT application, it is calling abort function from glibc
That is not true, this is not happening, unless you explicitly registered it.
I have enabled unwind for the glibc by using CFLAGS += "-funwind-tables"
It tells the compiler to add the information, it doesn't "enable unwind". What exactly happens when compiling with -funwind-tables?
Here, do_crash is called which does assert(0) which then aborts the main application.
This is not related to receiving SIGABRT signal.
Am I missing something here?
I believe you are making wrong assumptions - that something is called on SIGABRT, that SIGABRT is sent on assert, that abort() is called on SIGABRT. Nothing is called on SIGABRT and the program is terminated when receiving SIGABRT by default (see man 7 signal), assert just terminates the program and doesn't raise SIGABRT, and abort() raises the SIGABRT signal, not receives it.
How can I get the complete backtrace of the signals, particularly SIGABRT?
Register a handler that will do that. See How to automatically generate a stacktrace when my program crashes .
#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
_Exit(1);
}
int main(int argc, char **argv) {
signal(SIGABRT, handler); // install our handler
raise(SIGABRT);
}
If you want to print stacktrace on assert() that's completely different and you would overwrite the glibc handler for assert to do that:
#include <assert.h>
#include <execinfo.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
void print_trace(void) {
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
}
// based on https://code.woboq.org/userspace/glibc/assert/assert.c.html
void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function) {
extern const char *__progname;
fprintf(stderr, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",
__progname, __progname[0] ? ": " : "",
file, line,
function ? function : "", function ? ": " : "",
assertion);
print_trace();
abort();
}
int main() {
assert(0);
}

Simple C Program Lags [Homework]

For an assignment I have we are to find vulnerabilities in a certain C program and exploit them using various buffer overflow attacks. However when I run the .out file in the terminal with it's input argument it just stalls and doesn't do anything.
Even when I run GDB, that just lags too. I'm not looking for a solution to the assignment, I'm just looking for reasons why it's not running?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void partialwin()
{
printf("Achieved 1/2!\n");
}
void fullwin(){
printf("Achieved 2/2\n");
}
void vuln(){
char buffer[36];
gets(buffer);
printf("Buffer contents are %s\n",buffer);
}
int main(int argc,char**argv){
vuln();
}
Providing your sourc file is called assignment1.c and you're using gcc this should work, $ being your command prompt (which could be different on your platform)
$ gcc assignment1.c
$ a.out
Hello
Buffer contents are Hello
$

Change real process name in C on Linux

I'm currently trying to change the process name of a process so I can read the more easily with htop, top, .... I want to LD_PRELOAD this code into another process so it gets renamed by an environemt variable.
I found a lot of stuff in the internet, but nothing works:
prctl(PR_SET_NAME, "Test");
This does not work because htop is not honoring the name.
Nginx setproctitle (Link) doesn't work as well, because it strips the parameters (which are needed by the process).
I tried everything I found and now I'm out of ideas.
Is this even possible in linux? And how?
Just run your program by shell script or your program through exec and pass desired name as argv[0]:
#/bin/bash
exec -a fancy_name a.out ...
or C/C++:
execl( "./a.out", "fancy_name", ... );
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define NEW_NAME "hello_world"
int main(int argc, char **argv) {
if(strcmp(argv[0], NEW_NAME)) {
argv[0] = NEW_NAME;
execv("/proc/self/exe", argv);
fputs("exec failed", stderr);
return 1;
}
while(1) // so it goes to the top
;
}

Return-To-Libc Function Address Probing

I'm trying to implement a return-to-libc buffer overflow attack by finding the address of system() with gdb and returning to said address with /bin/sh passed as an argument to system() on the stack. The only problem is, I can't find the address in memory where system() lives, as running print system in gdb returns "No symbol table is loaded. Use the "file" command.", which isn't especially helpful, as loading libc.so into gdb doesn't do me any good. Is there a way I can find the addresses of functions in libc which I have not included via headers?
For reference, the code I'm testing this with is below, DEP is enabled, and ASLR is disabled.
#include <stdio.h>
#include <string.h>
void foo(char *arg) {
char buf[100];
strcpy(buf, arg);
}
int main(int argc, char **argv) {
foo(argv[1]);
return 0;
}

Shared memory: segmentation fault core dumped

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
int main()
{
int shmid;
char *viraddr;
char buffer[BUFSIZ];
shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
viraddr=(char*)shmat(shmid, 0,0);
while(1)
{
puts("Enter some text:");
fgets(buffer,BUFSIZ,stdin);
strcat(viraddr,buffer);
if(strncmp(buffer,"end",3)==0)
break;
}
shmdt(viraddr);
exit(0);
}
I am learning shared memory.I want to realize the communication between two processes. When I run this program, it always indicates this error -- segmentation fault core dumped. Any help on this? Thanks.
Here both viraddr and buffer have the same size. For strcat() it is recommended dst size to be atleast a byte larger than the src size. viraddr should have enough space to hold buffer data just to avoid buffer overrun.
Perhaps, sometimes the memory allocation returns FFFFF and then throws Segmentation Fault Core Dumped. Reason being you don't have enough rights to access the Memory for your processes.
Simply use sudo to compile and run the code. For instance say you have these files
shm1.c
shm2.c
shm.h
Then your commands need to be fired as following
sudo gcc shm1.c -o s1
sudo gcc shm2.c -o s2
sudo ./s1 &
sudo ./s2
If you are willing to do it on 2 different terminals, just fire sudo ./s1 in terminal1 & sudo ./s2 in different terminal 2

Resources