Jertype

Member of Information Superhighway

Using newer libc on old Linux distributions

Have you ever needed to run an application or load a library that requires a newer version of glibc?

If so, you may have seen an error like this:

/lib64/libc.so.6: version `GLIBC_2.14` not found

To check what version of glibc is installed use:

  1. ldd --version
  2. You’ll get a response like ldd (GNU libc) 2.12.

We were running an older version of Linux (CentOS/RHEL 6.x) and using a C library that only supported glibc 2.14 or higher.

Normally, the correct choice would be to either:

  1. Rebuild the library from source using the version of glibc on your OS
  2. Upgrade your OS to a newer version that includes the newer glibc

We could do neither, so we needed another solution.

Building glibc

If you take a look around, you’ll find that you can build a newer version of glibc. Here’s some instructions for doing a side-by-side installation of glibc 2.14 from Stack Overflow:

mkdir ~/glibc_install; cd ~/glibc_install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.gz
tar zxvf glibc-2.14.tar.gz
cd glibc-2.14
mkdir build
cd build
../configure --prefix=/opt/glibc-2.14
make -j4
sudo make install

This will install glibc into /opt/glibc-2.14 but if you run ldd --version it will still report the old version. So how do you get your application to use the new version?

Using the new glibc

You might find advice that suggests using LD_LIBRARY_PATH (ex: LD_LIBRARY_PATH=/opt/glibc-2.14/lib), but this can cause problems.

When you specify the LD_LIBRARY_PATH you are giving your system an additional path to look for libraries to dynamically load. However, the lib folder contains many other libraries that could be loaded. This can cause things like unexpected segfaults. Our application only needed to load libc.so.6.

If you use LD_PRELOAD, you can tell your application to load functions from a specific file instead of the locations it would normally load from.

If we had an executable called app, we could run it and prepending LD_PRELOAD as an environment variable:

LD_PRELOAD=/opt/glibc-2.14/lib/libc.so.6 ./app

When the application attempts to make libc function calls the LD_PRELOAD variable forces the application to use the ones stored in the new libc.so.6 file.

This allowed our application to run using the newer version of glibc.

Syncing the glibc timezone

After running our application with the new glibc the timezone was wrong.

This is because the new glibc has its own localtime file. You can resolve this by linking the system’s localtime file to the new glibc’s file:

ln -sf /etc/localtime /opt/glibc-2.14/etc/localtime

Learn more

To learn more about LD_PRELOAD, there’s a great blog post by Rafal Cieslak demonstrating how to use it to overwrite functions in C programs.

They force a binary to use a rand() function that’s injected by LD_PRELOAD.

Good luck!