Is it possible to add missing functions to libc.so.6 via LD_PRELOAD?

Jakub Jóźwicki
1 min readMay 14, 2021

The common knowledge is that it’s not possible, because missing functions are usually covered by not present symbol versions. Example: Red Hat 8 with getrandom() function marked as GLIBC_2.25 versus Red Hat 7 with GNU Lib C 2.17. Symbol version GLIBC_2.25 is not present in libc used on Red Hat 7 and as a result Linux loader will fail early before LD_PRELOAD would be able to shadow libc.

Is there any workaround? Yes, full proxy to libc. We can start with missing functions:

user@10.0.5.120[tmp] # cat glibc_compat.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#define GRND_NONBLOCK 1
#define GRND_RANDOM 2
asm(“.symver _getrandom, getrandom@@GLIBC_2.25”);
ssize_t _getrandom(void *buf, size_t buflen, unsigned int flags) {
int fd = open(flags & GRND_RANDOM ? “/dev/random” : “/dev/urandom”,
O_CLOEXEC | (flags & GRND_NONBLOCK ? O_NONBLOCK : 0), O_RDONLY);
if (fd<0) {
return fd;
}
int res = read(fd, buf, buflen);
close(fd);
return res;
}

Later we must add a lot of proxy functions doing dlopen/dlsym on /lib64/libc.so.6.

Our proxy can be compiled with:

gcc glibc_compat.c -o glibc_compat.so -shared -fPIC -Xlinker — version-script=/tmp/glibc_compat.map -Wl,-soname,libc.so.6

We need to have a version map file:

GLIBC_2.25 {
getrandom;
};
GLIBC_2.27 {
glob;
};
GLIBC_2.0 {};

GLIBC_2.3.4 {};
GLIBC_PRIVATE {};

We can proceed step by step with the binary we want to force to run with:

LD_DEBUG=all LD_PRELOAD=/tmp/glibc_compat.so ./linpmem-v3.3-rc3.bin

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Jakub Jóźwicki
Jakub Jóźwicki

No responses yet

Write a response