For an observation purpose, I wrote a program using _start(), _init(), _fini(), goal is to not to use startfiles.
the code is as follows
#include <stdio.h>
void test()
{
printf("\n%s: \n",__func__);
printf("library test routine invoked\n");
int a=3,b=2;
int sum=a+b;
printf("sum=%d\n",sum);
getchar();
_fini();
}
int _start()
{
printf("\n%s: \n",__func__);
printf("in library start routine\n");
test();
return 0;
}
int _init()
{
printf("\n%s: \n",__func__);
printf("in library init routine\n");
return 0;
}
int _fini()
{
printf("\n%s: \n",__func__);
printf("in library fini routine\n");
return 0;
}
complied with
gcc -nostartfiles test.c -o test
and the output is
_start:
in library start routine
test:
library test routine invoked
sum=5
l
_fini:
in library fini routine
Segmentation fault (core dumped)
Here I want to know why the executable gave segmentation fault?? Do I need to specify as it is end of the program?? If so, how??
What can be done to overcome the segmentation fault??
Another question is that these _start(),_init(),_fini() are only used when dealing with libraries???
Please
The _start routine cannot return. Normally, it calls __libc_start_main which calls main. Then when main returns, __libc_start_main calls exit with the return value of main.
Since you're defining _start yourself and not calling __libc_start_main, you need to explicitly call exit. You're getting a sigfault because that function is not expected to return.
See this question for more detail.
Related
The following program copied from Quora, that print "Hello world" before main() function.
#include <stdio.h>
#include <unistd.h>
int main(void)
{
return 0;
}
void _start(void)
{
printf ("hello, world\n");
int ret = main();
_exit (ret);
}
Then, I compiled above program on Ubuntu-14.04 GCC compiler using following command
gcc -nostartfiles hello.c
And ran a.out executable file, But I got Segmentation fault (core dumped)? So, Why Segmentation fault?
_start is the real entrypoint of the executable, that is normally taken by the C runtime to initialize its stuff - including stdio -, call functions marked with the constructor attribute and then call your main entrypoint. If you take it and try to use stuff from the standard library (such as printf) you are living dangerously, because you are using stuff that hasn't been initialized yet.
What you can do, however, is to bypass the C runtime completely, and print using a straight syscall, such as write.
I want to enable stack protection feature in gcc for a system i am building that run on x86 linux.
I want that if it detects stack smashing it would call a function of my own that will handle the case or it will call my own implementation of the function __stack_chk_fail , is there a way to do it?
So far i tried to undef __stack_chk_fail and __stack_chk_guard and then defining them myself but it didn't work and resulted in segmentation fault when trying exploiting buffer overflow.
Here is an example of what i did:
#undef __stack_chk_guard
#undef __stack_chk_fail
uintptr_t __stack_chk_guard = 0xdeadbeef;
void __stack_chk_fail(void)
{
printf("Stack smashing detected");
}
void foo(void)
{
char buffer[2];
strcpy(buffer, "hello, I am smashing your stack!");
}
I also tried using LD_PRELOAD but that resulted in segmentation fault when smashing the stack but it also resulted in segmentation fault.
After some research i found out i can use the linker flag --wrap to wrap __stack_chk_fail and insert my own hanlding just as i wanted.
The flag change each call of __stack_chk_fail to __wrap___stack_chk_fail and each call to __real___stack_chk_fail to __stack_chk_fail
I can even skip calling the real __stack_chk_fail if i wanted to
below is an example code in a file named test.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void __real___stack_chk_fail(void);
void __wrap___stack_chk_fail(void)
{
printf("our test");
__real___stack_chk_fail();
}
void func()
{
char buffer[2];
strcpy(buffer, "smashhhhhhhhhhhhhhhh");
}
int main(void)
{
func();
return 0;
}
To compile it execute:
gcc -fstack-protector-strong -c test.c
gcc -Wl,--wrap=__stack_chk_fail test.o
The ouput would be "our test" and then the regular behavior of __stack_chk_fail
UPDATE:
Another way to do it is to exclude libssp from the linkage process with the flag --exclude-libs,libssp and implement __stack_chk_fail and guard_setup(the function that initiate __stack_chk_guard value) on your own
I need, to write unitary tests, to wrap the abort() system call.
Here is a snippet of code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
extern void __real_abort(void);
extern void * __real_malloc(int c);
extern void __real_free(void *);
void __wrap_abort(void)
{
printf("=== Abort called !=== \n");
}
void * __wrap_malloc(int s)
{
void *p = __real_malloc(s);
printf("allocated %d bytes #%p\n",s, (void *)p);
return p;
}
void __wrap_free(void *p)
{
printf("freeing #%p\n",(void *)p);
return __real_free((void *)p);
}
int main(int ac, char **av)
{
char *p = NULL;
printf("pre malloc: p=%p\n",p);
p = malloc(40);
printf("post malloc p=%p\n",p);
printf("pre abort\n");
//abort();
printf("post abort\n");
printf("pre free\n");
free(p);
printf("post free\n");
return -1;
}
Then i compile this using the following command line :
gcc -Wl,--wrap=abort,--wrap=free,--wrap=malloc -ggdb -o test test.c
Running it give the following output:
$ ./test
pre malloc: p=(nil)
allocated 40 bytes #0xd06010
post malloc p=0xd06010
pre abort
post abort
pre free
freeing #0xd06010
post free
So everything is fine.
Now let's test the same code but with abort() call uncommented:
$ ./test
pre malloc: p=(nil)
allocated 40 bytes #0x1bf2010
post malloc p=0x1bf2010
pre abort
=== Abort called !===
Segmentation fault (core dumped)
I don't really understand why i get a segmentation fault while mocking abort() syscall...
Every advice is welcome !
I run Debian GNU/Linux 8.5 on an x86_64 kernel. Machine is a Core i7 based laptop.
In glibc (which is the libc Debian uses) the abort function (it's not a system call, it's a normal function) is declared like this:
extern void abort (void) __THROW __attribute__ ((__noreturn__));
This bit: __attribute__ ((__noreturn__)) is a gcc extension that tells it that the function can't return. Your wrapper function does return which the compiler didn't expect. Because of that it will crash or do something completely unexpected.
Your code when compiled will be using the declarations from stdlib.h for the call to abort, the flags you gave to the linker won't change that.
Noreturn functions are called differently, the compiler doesn't have to preserve registers, it can just jump to the function instead of doing a proper call, it might even just not generate any code after it because that code is by definition not reachable.
Here's a simple example:
extern void ret(void);
extern void noret(void) __attribute__((__noreturn__));
void
foo(void)
{
ret();
noret();
ret();
ret();
}
Compiled into assembler (even without optimizations):
$ cc -S foo.c
$ cat foo.s
[...]
foo:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
call ret
call noret
.cfi_endproc
.LFE0:
.size foo, .-foo
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-4)"
.section .note.GNU-stack,"",#progbits
Notice that there is a call to noret, but there isn't any code after this. The two calls to ret were not generated and there is no ret instruction. The function just ends. This means that if the function noret actually returns because of a bug (which your implementation of abort has), anything can happen. In this case we'll just continue executing whatever happens to be in the code segment after us. Maybe another function, or some strings, or just zeroes, or maybe we're lucky and the memory mapping ends just after this.
In fact, let's do something evil. Never do this in real code. If you ever think that this is a good idea you'll need to hand over the keys to your computer and slowly step away from the keyboard while keeping your hands up:
$ cat foo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void __wrap_abort(void)
{
printf("=== Abort called !=== \n");
}
int
main(int argc, char **argv)
{
abort();
return 0;
}
void
evil(void)
{
printf("evil\n");
_exit(17);
}
$ gcc -Wl,--wrap=abort -o foo foo.c && ./foo
=== Abort called !===
evil
$ echo $?
17
As I thought, the code just keeps going after whatever happened to be placed after main and in this simple example the compiler didn't think it would be a good idea to reorganize the functions.
This is a continuation of the discussion under Art's answer, and is meant purely as an experiment.
Do not do this in real code!
The problem can be averted using longjmp to restore the environment, before calling the real abort.
The following program does not display undefined behavior:
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
_Noreturn void __real_abort( void ) ;
jmp_buf env ;
_Noreturn void __wrap_abort( void )
{
printf( "%s\n" , __func__ ) ;
longjmp( env , 1 ) ;
__real_abort() ;
}
int main( void )
{
const int abnormal = setjmp( env ) ;
if( abnormal )
{
printf( "saved!\n" ) ;
}
else
{
printf( "pre abort\n" ) ;
abort() ;
printf( "post abort\n" ) ;
}
printf( "EXIT_SUCCESS\n" ) ;
return EXIT_SUCCESS ;
}
Output:
pre abort
__wrap_abort
saved!
EXIT_SUCCESS
Nice answer, above, with the assembly output. I had the same problem, again, while creating unit tests and stubbing the abort() call - the compiler sees the __noreturn__characteristic in stdlib.h, knows it CAN stop generating code after the call to a __noreturn__ function, but GCC and other compilers DO stop generating code, even with optimization suppressed. Returns after the call to the stubbed abort() just fell through to the next function, declared data, etc. I tried the --wrap approach, above, but the calling function is just missing code after the __wrap_abort() returns.
One way I found to override this behavior is to catch the abort() declaration at the preprocessor level - keep your stubbed abort() in a separate source file, and add to the CFLAGS for the file that's calling abort()
-D__noreturn__="/* __noreturn__ */"
This modifies the effect of the declaration found in stdlib.h. Check your preprocessor output via gcc -E and verify this worked. You can also check your compiler's output via objdump of the .o file.
This whole approach will have the added side effect of generating code for source that follows other abort() calls, exit() calls, and anything else that appears in stdlib.h with the __noreturn__ characteristic, but most of us don't have code that follows an exit(), and most of us just want to clean the stack and return from the abort() caller.
You can keep the linker --wrap logic in order to invoke your __wrap_abort() call, or, since you won't be calling __real_abort(), you can do something similar to the above to get to your stubbed abort():
-Dabort=my_stubbed_abort
Hope this helps.
Out of curiosity I am trying to get the libc on_exit function to work, but I have run into a problem with a segmentation fault. The difficulty I am having is finding an explanation of the proper use of this function. The function is defined in glibc as:
Function: int on_exit (void (*function)(int status, void *arg), void *arg)
This function is a somewhat more powerful variant of atexit. It accepts two arguments, a function and an arbitrary pointer arg. At normal program termination, the function is called with two arguments: the status value passed to exit, and the arg.
I created a small test, and I cannot find where the segmentation fault is generated:
#include <stdio.h>
#include <stdlib.h>
void *
exitfn (int stat, void *arg) {
printf ("exitfn has been run with status %d and *arg %s\n", stat, (char *)arg);
return NULL;
}
int
main (void)
{
static char *somearg="exit_argument";
int exit_status = 1;
on_exit (exitfn (exit_status, somearg), somearg);
exit (EXIT_SUCCESS);
}
Compiled with: gcc -Wall -o fn_on_exit fnc-on_exit.c
The result is:
$ ./fn_on_exit
exitfn has been run with status 1 and *arg exit_argument
Segmentation fault
Admittedly, this is probably readily apparent for seasoned coders, but I am not seeing it. What is the proper setup for use of the on_exit function and why in this case is a segmentation fault generated?
The line of code
on_exit (exitfn (exit_status, somearg), somearg);
Should be
on_exit (exitfn, somearg);
As you do not want to call the exitfn at this stage (that returns NULL!)
This question already has answers here:
What is the use of _start() in C?
(4 answers)
Closed 3 years ago.
Can you help me to understand how
__start
is used in C internally?
Is it the exact replica of the main function or is it the entry point to the compiled program?
Just wondering, how its getting used?
Here is a good overview of what happens during program startup before main. In particular, it shows that __start is the actual entry point to your program from OS viewpoint.
It is the very first address from which the instruction pointer will start counting in your program.
The code there invokes some C runtime library routines just to do some housekeeping, then call your main, and then bring things down and call exit with whatever exit code main returned.
A picture is worth a thousand words:
As per C/C++ standard, main() is the starting point of a program. If you're using GCC, _start function is the entry point of a C program which makes a call to main(). The main job of _start() function is to perform a few initialization tasks.
// $ gcc program_entry.c -nostartfiles
// $ ./a.out
// custom program entry
#include <stdio.h>
#include <stdlib.h>
void program_entry(void);
void
_start(void)
{
program_entry();
}
void
program_entry(void)
{
printf("custom program entry\n");
exit(0);
}
If you want, the program entry can also be compiled with -e switch in GCC.
// $ gcc program_entry.c -e __start
// $ ./a.out
// custom program entr
#include <stdio.h>
void program_entry(void);
void
_start(void)
{
program_entry();
}
void
program_entry(void)
{
printf("custom program entry\n");
}
_start is a operating system function....which is entry point for any program...as our compiler knows about main(main is not pre defined function it is user defined but all the compiler knows about them) this _start function will call main and from that point our program enters in CPU