I'm trying to create a static application that will not load libraries on run time. Specifically (for the proof of concept), I've written a short program that calls gethostbyname
:
#include <netdb.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
int main() {
string hostname(100, 0);
const int hostname_length = gethostname(
const_cast<char *>(hostname.data()),
hostname.capacity()
);
hostname.resize(hostname.size());
cout << "Hostname: " << hostname << endl;
const struct hostent *host_entry = gethostbyname(hostname.c_str());
cout << "Hostname 2: " << host_entry->h_name << endl;
getchar(); // Keep the program alive so I can look at /proc/#/maps
}
When compiling with the standard glibc
and -static
, this shows a warning message (shown below) and loads several libraries such as libresolv
, libnss_files
, libnss_dns
and more.
/usr/bin/ld: /tmp/cc1EWL0m.o: in function `main':
main.cpp:(.text+0xe2): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
In order to prevent this I compiled glibc
2.33 from source in the following way:
../glibc/configure --enable-static-pie --enable-static-nss --prefix=/opt/glibc --disable-nscd
make
sudo make install
Then, following the technique presented here, I compiled my program with:
g++ -o custom main.cpp -nostdlib -nostartfiles -static /opt/glibc/lib/crt1.o /opt/glibc/lib/crti.o `gcc --print-file-name=crtbegin.o` -L/opt/glibc/lib -Wl,--start-group -lstdc++ -lgcc -lgcc_eh -lc -Wl,--end-group `gcc --print-file-name=crtend.o` /opt/glibc/lib/crtn.o
Sure enough the warning about loading libraries in runtime was gone. But running cat /proc/$(pgrep custom)/maps
, I can see libraries are still getting loaded:
cat /proc/`pgrep custom`/maps
00400000-00401000 r--p 00000000 08:10 962 /home/dan/projects/l/custom_glibc/example/custom
00401000-00565000 r-xp 00001000 08:10 962 /home/dan/projects/l/custom_glibc/example/custom
00565000-005bd000 r--p 00165000 08:10 962 /home/dan/projects/l/custom_glibc/example/custom
005bd000-005c7000 r--p 001bc000 08:10 962 /home/dan/projects/l/custom_glibc/example/custom
005c7000-005ca000 rw-p 001c6000 08:10 962 /home/dan/projects/l/custom_glibc/example/custom
005ca000-005cf000 rw-p 00000000 00:00 0
019df000-01a01000 rw-p 00000000 00:00 0 [heap]
7f3e9f5cf000-7f3e9f6cf000 rw-p 00000000 00:00 0
7f3e9f6cf000-7f3e9f6d0000 r--p 00000000 08:10 337811 /opt/glibc/lib/ld-2.33.so
7f3e9f6d0000-7f3e9f6f4000 r-xp 00001000 08:10 337811 /opt/glibc/lib/ld-2.33.so
7f3e9f6f4000-7f3e9f6fd000 r--p 00025000 08:10 337811 /opt/glibc/lib/ld-2.33.so
7f3e9f6fd000-7f3e9f6fe000 ---p 0002e000 08:10 337811 /opt/glibc/lib/ld-2.33.so
7f3e9f6fe000-7f3e9f700000 r--p 0002e000 08:10 337811 /opt/glibc/lib/ld-2.33.so
7f3e9f700000-7f3e9f702000 rw-p 00030000 08:10 337811 /opt/glibc/lib/ld-2.33.so
7f3e9f702000-7f3e9f728000 r--p 00000000 08:10 330240 /opt/glibc/lib/libc-2.33.so
7f3e9f728000-7f3e9f869000 r-xp 00026000 08:10 330240 /opt/glibc/lib/libc-2.33.so
7f3e9f869000-7f3e9f8b5000 r--p 00167000 08:10 330240 /opt/glibc/lib/libc-2.33.so
7f3e9f8b5000-7f3e9f8b6000 ---p 001b3000 08:10 330240 /opt/glibc/lib/libc-2.33.so
7f3e9f8b6000-7f3e9f8b9000 r--p 001b3000 08:10 330240 /opt/glibc/lib/libc-2.33.so
7f3e9f8b9000-7f3e9f8bc000 rw-p 001b6000 08:10 330240 /opt/glibc/lib/libc-2.33.so
7f3e9f8bc000-7f3e9f8c0000 rw-p 00000000 00:00 0
7f3e9f8c0000-7f3e9f8c3000 r--p 00000000 08:10 337766 /opt/glibc/lib/libnss_files-2.33.so
7f3e9f8c3000-7f3e9f8c9000 r-xp 00003000 08:10 337766 /opt/glibc/lib/libnss_files-2.33.so
7f3e9f8c9000-7f3e9f8cb000 r--p 00009000 08:10 337766 /opt/glibc/lib/libnss_files-2.33.so
7f3e9f8cb000-7f3e9f8cc000 r--p 0000a000 08:10 337766 /opt/glibc/lib/libnss_files-2.33.so
7f3e9f8cc000-7f3e9f8cd000 rw-p 0000b000 08:10 337766 /opt/glibc/lib/libnss_files-2.33.so
7ffcb4dd2000-7ffcb4df4000 rw-p 00000000 00:00 0 [stack]
7ffcb4df9000-7ffcb4dfc000 r--p 00000000 00:00 0 [vvar]
7ffcb4dfc000-7ffcb4dfe000 r-xp 00000000 00:00 0 [vdso]
When trying to add -lnss_files
to link statically against it I found that there is no libnss_files.a
in my custom glibc
installation. I was able to find libnss_files_pic.a
where I build glibc
, but even copying it to the glibc
installation and linking against it didn't help.
I wonder if there's even a way to prevent library loading at runtime except for moving to an alternative libc
implementation...