-
Notifications
You must be signed in to change notification settings - Fork 126
Unable to intercept openat syscall made by dlopen #118
Description
I am trying to intercept all openat syscalls. This involves those made by dlopen when loading shared libraries in the program.
What I have noticed is that I am able to intercept openat if I explicitly call this function from my application. However, if I try to open a .so using dlopen which internally should still call openat (ref:) then it does not intercept and goes on to make the syscall as usual.
I inspected the disassembly and noticed that even though __open64_nocancel is being hotpatched and the syscall is replaced by jmp, this is done in the __open64_nocancel in libc.so. However, when I call dlopen, it ends up calling __open64_nocancel from ld-linux-x86-64.so.2 which does not seem to have the hotpatch.
Below is a screenshot showing the disassembly:

This is the screenshot of the hotpatched instance:

This is the screenshot showing these __open64_nocancel are in apparently two different .so files:

Is there any guess on why:
a) There are two instances of __open64_nocancel? ld.so is supposed to load these so not sure why these come up as duplicates.
b) Only one of the two instances was hotpatched?
Here is a sample application I am using:
#include <string>
#include <iostream>
#include <dlfcn.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int test_openat() {
int fd = openat(AT_FDCWD, "/home/gochaudh/.local/lib/python3.10/site-packages/pandas/io/__pycache__/parquet.cpython-310.pyc", O_RDONLY|O_CLOEXEC);
if (fd != -1) {
std::cout << "Opened file at: " << fd << std::endl;
} else {
std::cerr << "Cannot open file" << std::endl;
perror("openat");
return -1;
}
int ret = close(fd);
if (!ret) {
std::cout << "File closed" << std::endl;
} else {
std::cerr << "Cannot close file" << std::endl;
return -1;
}
return 0;
}
int test_dlopen() {
const std::string lib_path("/home/gochaudh/functions_kernel/lib/python/3.10.0/lib/libpython3.10.so.1.0");
void *lib = dlopen(lib_path.c_str(), RTLD_NOW);
if (lib) {
std::cout << "Library loaded at: " << lib << std::endl;
} else {
std::cerr << "Could not open library: " << dlerror() << std::endl;
return -1;
}
int ret = dlclose(lib);
if (!ret) {
std::cout << "Library closed" << std::endl;
} else {
std::cerr << "Cannot close library" << std::endl;
return -1;
}
return 0;
}
int main() {
test_openat();
test_dlopen();
return 0;
}