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);
}
Related
I have made a library that handle strings in c.
I've added it in another project CMakeLists. Issue is that, whenever i want to call a function from that library, it crash.
However, if i call the same function from the library itself, no crash, the function call is handled properly.
I kept thinking that i did something wrong with my CMakeLists but as far as i'm aware and the different methods i used to arrive to the same conclusion, it doesn't look like it anymore.
I tried running the test in question in gdb and this is what it returned
Starting program: C:\Users\s\Documents\Repo\C\Projet\lib\rule\build\test-create-destroy.exe
gdb: unknown target exception 0xc0000135 at 0x7ffdfa70cf40
gdb: unknown target exception 0xc0000135 at 0x7ffdfa70cf40
Program received signal ?, Unknown signal.
0x00007ffdfa70cf40 in ntdll!RtlRaiseStatus () from C:\Windows\SYSTEM32\ntdll.dll
I've read that it could be an issue related to memory allocation errors, but if this was the case, why would i be able to call the function without any error directly from my library?
replit of fairly simple example: https://replit.com/#Mrcubix-Mrcubix/EmbellishedOldfashionedBaitware#lib/rule/src/test-create-destroy.c
Here is the function called in the library in question, to keep it simple:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct _String
{
unsigned int size;
char *string;
} String;
String *create_string(char *chr)
{
String *str = malloc(sizeof(String));
str->size = strlen(chr);
str->string = malloc(str->size + 1);
memcpy(str->string, chr, str->size);
str->string[str->size] = '\0';
return str;
}
void destroy_string(String *str)
{
free(str);
}
Here the second library i'm calling a function from which work as it's part of the same project:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string-struct.h>
typedef struct _rule
{
String *premise;
String *conclusion;
} rule;
rule *create_rule(String *premise, String *conclusion)
{
rule *r = calloc(1, 16);
r->premise = premise;
r->conclusion = conclusion;
return r;
}
void destroy_rule(rule *r)
{
free(r);
}
here is the CMakeLists used by Rulestruct:
cmake_minimum_required(VERSION 3.0)
project("Rulestruct")
find_package(Stringstruct)
include_directories(${STRINGSTRUCT_INCLUDE_DIRS})
link_directories(${STRINGSTRUCT_LIB_DIRS})
add_library(rulestruct SHARED "${CMAKE_CURRENT_SOURCE_DIR}/src/rule-struct.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/rule-struct.h")
target_link_libraries(rulestruct ${STRINGSTRUCT_LIBRARIES})
add_executable(test-create-destroy "${CMAKE_CURRENT_SOURCE_DIR}/src/test-create-destroy.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/rule-struct.h")
add_dependencies(test-create-destroy rulestruct)
target_link_libraries(test-create-destroy rulestruct)
and finally, here is where i call the function from (test-create-destroy.c)
#include <assert.h>
#include <string-struct.h>
#include "rule-struct.h"
#include "rules-struct.inc"
int main(void)
{
String *premise = create_string("1 2"); // location of crash
String *conclusion = create_string("3"); // location of crash
/*rule *rule_A = create_rule(premise, conclusion);
assert(string_char_equal(rule_A->premise, "1 2"));
assert(!string_char_equal(rule_A->premise, "3"));
assert(string_char_equal(rule_A->conclusion, "3"));
assert(!string_char_equal(rule_A->conclusion, "1 2"));
destroy_rule(rule_A);*/
destroy_string(premise);
destroy_string(conclusion);
}
Here are screenshots of bin, lib and cmake-gui: https://imgur.com/a/3OdrC2D
I could probably fix it on every project provided i know what i did wrong and why,
So if anyone could provide further explanation then i'll glad to read it.
I will also take tips about issues or potential issues related to my CMakeLists as i have a hard time understanding any of it, needing to mix multiple examples and the documentation to have a very small bit of understanding of why something is done this or that way.
TLDR: Function called elsewhere than inside the library = crash, accept tips about other parts of the presented data (CMakeLists).
Gladly accept further explanation of the core of the issue.
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;
}
i have a question:
exists any system call for generate a core dump?
I know which a core dump could be generated by a signal, but i want know if it's possible generated from system call
void createdump(void)
{
if(!fork()) { //child process
// Crash the app
abort() || (*((void*)0) = 42);
}
}
What ever place you wan't to dump call the function. This will create a child and crash it. So you can get dump even without exiting your program
You can also raise the SIGABRT signal to get the core dump.
raise(SIGABRT);
*this is equivalent to calling abort() directly.
Same idea as code hacker's answer, but compilable, with error handling, and without the zombie:
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int
coredump(void)
{
pid_t p,r;
if(0>(p=fork()))
return -1;
if(0==p)
abort() /*child*/;
/*reap zombie*/
do r=waitpid(p,0,0); while(0>r && EINTR==errno);
if(0>r) {
perror("waitpid shouldn't have failed");
abort();
}
return 0;
}
This still has the rather obvious deficiency in that that it won't work with multithreaded processes.
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
This is sample program from "Beginning Linux Programming" book:
#include <stdio.h>
#include <term.h>
#include <curses.h>
#include <stdlib.h>
int main()
{
setupterm("unlisted", fileno(stdout), (int *)0);
printf("Done.\n");
exit(0);
}
Running it, I have this result:
./badterm
'unlisted': unknown terminal type.
According to setupterm function definition, it must return 0: "No matching entry in terminfo database". Instead of this, program terminates. Why?
It looks like you asked it to do so. From man setupterm on my machine:
If errret is null, setupterm prints an error message upon finding an
error and exits. Thus, the simplest call is:
setupterm((char *)0, 1, (int *)0);
which uses all the defaults and sends the output to stdout.
Presumably, if you want to handle any error return yourself, you must supply a non-NULL pointer value for the errret (third) parameter.