Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is statically linking glibc discouraged?

Most of the sources online state that you can statically link glibc, but discourage from doing so; e.g. centos package repo:

The glibc-static package contains the C library static libraries for -static linking. You don't need these, unless you link statically, which is highly discouraged.

These sources rarely (or never) say why that would be a bad idea.

like image 931
pzelasko Avatar asked Aug 13 '19 11:08

pzelasko


People also ask

Which is better static linking or dynamic linking?

Statically linked program takes constant load time every time it is loaded into the memory for execution. In dynamic linking load time might be reduced if the shared library code is already present in memory. Programs that use statically-linked libraries are usually faster than those that use shared libraries.

What is static linking in system programming?

Static linking is the result of the linker copying all library routines used in the program into the executable image. This may require more disk space and memory than dynamic linking, but is both faster and more portable, since it does not require the presence of the library on the system where it is run.

Is libc always linked?

However libc has not been linked in statically, only dynamically, so it is another failed attempt.


2 Answers

The reasons given in other answers are correct, but they are not the most important reason.

The most important reason why glibc should not be statically linked, is that it makes extensive internal use of dlopen, to load NSS (Name Service Switch) modules and iconv conversions. The modules themselves refer to C library functions. If the main program is dynamically linked with the C library, that's no problem. But if the main program is statically linked with the C library, dlopen has to go load a second copy of the C library to satisfy the modules' load requirements.

This means your "statically linked" program still needs a copy of libc.so.6 to be present on the file system, plus the NSS or iconv or whatever modules themselves, plus other dynamic libraries that the modules might need, like ld-linux.so.2, libresolv.so.2, etc. This is not what people usually want when they statically link programs.

It also means the statically linked program has two copies of the C library in its address space, and they might fight over whose stdout buffer is to be used, who gets to call sbrk with a nonzero argument, that sort of thing. There is a bunch of defensive logic inside glibc to try to make this work, but it's never been guaranteed to work.

You might think your program doesn't need to worry about this because it doesn't ever call getaddrinfo or iconv, but locale support uses iconv internally, which means any stdio.h function might trigger a call to dlopen, and you don't control this, the user's environment variable settings do.

And if your program does call iconv, for example, then things get even worse, especially when a “statically linked” executable is built on one distro, and then copied to another. The iconv modules are sometimes located in different places on different distros, so an executable that was built, say, on a Red Hat distro may fail to run properly on a Debian one, which is exactly the opposite of what people want from statically linked executables.

like image 74
zwol Avatar answered Oct 19 '22 07:10

zwol


The program/glibc interface is standardized and documented by POSIX, the C and C++ standards, and others. For example, the fopen() function behaves per the C standard, and pthread_mutex_lock() per POSIX.

The glibc/kernel interface is not standardized. Does fopen() use open() under the hood? Or does it use openat()? Or something else? What will it use next year? You don't know.

If the glibc/kernel interface changes, a program that uses whatever changed but statically links glibc won't work any more.

15+ years ago, Solaris removed all static versions of libc for this very reason.

Static Linking - where did it go?

With Solaris 10 you can no longer build a static executable. It's not that ld(1) doesn't allow static linking, or using archives, it's just that libc.a, the archive version of libc.so.1, is no longer provided. This library provides the interfaces between user land and the kernel, and without this library it is rather hard to create any form of application.

We've been warning users against static linking for some time now, and linking against libc.a has been especially problematic. Every solaris release, or update (even some patches) has resulted in some application that was built against libc.a, failing. The problem is that libc is supposed to isolate an application from the user/kernel boundary, a boundary which can undergo changes from release to release.

If an application is built against libc.a, then any kernel interface it references is extracted from the archive and becomes a part of the application. Thus, this application can only run on a kernel that is in-sync with the kernel interfaces used. Should these interfaces change, the application is treading on shaky ground.

...

Edit:

There seems to be serious overestimation of the stability of the Linux kernel interface. See Linux kernel API changes/additions for details. To summarize:

enter image description here

like image 41
Andrew Henle Avatar answered Oct 19 '22 05:10

Andrew Henle