Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

building a .so that is also an executable

So everyone probably knows that glibc's /lib/libc.so.6 can be executed in the shell like a normal executable in which cases it prints its version information and exits. This is done via defining an entry point in the .so. For some cases it could be interesting to use this for other projects too. Unfortunately, the low-level entry point you can set by ld's -e option is a bit too low-level: the dynamic loader is not available so you cannot call any proper library functions. glibc for this reason implements the write() system call via a naked system call in this entry point.

My question now is, can anyone think of a nice way how one could bootstrap a full dynamic linker from that entry point so that one could access functions from other .so's?

like image 266
user175104 Avatar asked Sep 20 '09 01:09

user175104


People also ask

Is a shared library an executable?

Shared library are the one which do some task that is commonly accessed or used by many executables. These library are loaded into the memory only once and accessed by many programs(executables) at runtime.

Is a shared object an executable?

There's no difference, aside from the fact that a compiled executable might be linked against a shared object but not against an executable.

Why are shared libraries executable?

The executable mode is a convention that gives the OS another level of access rights control. The executable loader controls that access, to ensure the user can execute it, but also to prevent errors (some scripts or programs should not be executed by some people).


1 Answers

Update 2: see Andrew G Morgan's slightly more complicated solution which does work for any GLIBC (that solution is also used in libc.so.6 itself (since forever), which is why you can run it as ./libc.so.6 (it prints version info when invoked that way)).

Update 1: this no longer works with newer GLIBC versions:

./a.out: error while loading shared libraries: ./pie.so: cannot dynamically load position-independent executable 

Original answer from 2009:

Building your shared library with -pie option appears to give you everything you want:

/* pie.c */ #include <stdio.h> int foo() {   printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);   return 42;  } int main()  {    printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);   return foo();  }   /* main.c */ #include <stdio.h>  extern int foo(void); int main()  {    printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);   return foo();  }   $ gcc -fPIC -pie -o pie.so pie.c -Wl,-E $ gcc main.c ./pie.so   $ ./pie.so in main pie.c:9 in foo pie.c:4 $ ./a.out in main main.c:6 in foo pie.c:4 $ 

P.S. glibc implements write(3) via system call because it doesn't have anywhere else to call (it is the lowest level already). This has nothing to do with being able to execute libc.so.6.

like image 184
Employed Russian Avatar answered Oct 22 '22 23:10

Employed Russian