-2

The scenario is I try to re-link the program to a directory via /proc where these directories into an elf executable.

First, I create a directory with name test

$ mkdir test

Link to an hello binary

# ln /bin/ping test
# exit

Open a file descriptor to the target binary

$ exec 3< test

You know, this descriptor should now be accessible via /proc

$ ls -l /proc/$$/fd/3
lr-x------ 1 febri febri 64 Jul 17 11:09 /proc/2930/fd/3 -> /home/febri/test

Remove the directory previously created

$ rm -rf test

The /proc link should still exist, but now will be marked deleted.

$ ls -l /proc/$$/fd/3 
lr-x------ 1 febri febri 64 Jul 17 11:09 /proc/2930/fd/3 -> /home/febri/test (deleted)

Replace the directory with example payload like :

$ cat hello.c
#include <stdio.h>

int main(int argc, char ** argv) {
printf("hello!\n");
return 0;
}
$ gcc -w -fPIC -shared -o test hello.c
$ ls -l test
-rwxrwxr-x 1 febri febri 6894 Jul 17 11:20 test
$ file test 
test: ELF 32-bit LSB  shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=361c522d3d9db35ad24de9f3162f80f8a26c9c5b, not stripped

So, I running the linked program and the output is :

$ ./test
Segmentation fault (core dumped)

My question is :

Why the program crash when executed? if anyone can explain?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

1 Answers1

0

In fact, the directories and/or symbolic links you messed around with have absolutely nothing to do with the segmentation fault you're facing. Let's look at the command line options you're using to compile hello.c:

  • -w: Suppress all warnings. This is bad practice and will be the root of each and every single one of your bugs sooner or later. I've yet to find a good reason to suppress any warning. Anyways, this doesn't matter for this situation, as compiling a hello world program yields no warnings.

  • -fPIC: Generate ]position-independent code](https://en.wikipedia.org/wiki/Position-independent_code).

  • -shared: Generate a shared library instead of an executable.

So, you're attempting to execute a shared library, which is not intended to be executed! However, GCC marks the output file with the executable bit. That makes no sense at all... until you meet HP-UX's mmap() implementation.

Seemingly, due to one of HP-UX's features (cough design flaws cough), the whole Unix(-like) family has inherited this convention of shared libraries being marked as executable, even though most of them will SIGSEGV if you actually try to execute them.

The actual cause of the segmentation fault, from the operating system's point of view, is an artifact of the way the Executable and Linkable Format was designed back in the late 1980's.

Curiously, it happens that shared libraries can indeed avoid SEGV'ing upon execution. However, black voodoo, such as the GNU C Library's, shall be performed in order to do so. The consequences of performing such a ritual are agonizing. For instance, you're left with no way to initialize the C runtime, so you have to use direct read()'s and write()'s instead of stdio. Other runtime-supported subsystems, such as malloc() and friends, are out of question as well. Also, (because of no runtime support) there's no main(). You have to define your own entry point instead, and call _exit(0) explicitly.

tl;dr: Directories and symbolic links have nothing to do with the issue. You're attempting to execute a shared library, and, as that's not the expected behavior, you are SIGSEGV'd.

Community
  • 1
  • 1
3442
  • 8,248
  • 2
  • 19
  • 41
  • You actually can [use libc functions from `_start` if you call glibc's init functions (in the right order)](http://stackoverflow.com/questions/36861903/assembling-32-bit-binaries-on-a-64-bit-system-gnu-toolchain/36901649#36901649). This happens for you if you dynamically link to libc on Linux, but not with static linking. – Peter Cordes Jul 17 '16 at 12:47
  • Thank you for answering :)) – Febriyanto Nugroho Jul 19 '16 at 08:03