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:
- 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:
- Rebuild the library from source using the version of glibc on your OS
- Upgrade your OS to a newer version that includes the newer glibc
We could do neither, so we needed another solution.
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:
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
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.