Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to intercept openat syscall made by dlopen #118

Open
gohar94 opened this issue Sep 22, 2022 · 2 comments
Open

Unable to intercept openat syscall made by dlopen #118

gohar94 opened this issue Sep 22, 2022 · 2 comments

Comments

@gohar94
Copy link

gohar94 commented Sep 22, 2022

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:
image

This is the screenshot of the hotpatched instance:
image

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

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;
}
@gohar94
Copy link
Author

gohar94 commented Sep 22, 2022

I just realized this seems to be a "known" issue and someone (a long, long time ago) faced a similar problem based on this stackoverflow post.

I guess a solution would be to hotpatch all of the .text section of the binary (other than syscall_intercept and its dependencies).

@gohar94
Copy link
Author

gohar94 commented Sep 23, 2022

Running with INTERCEPT_ALL_OBJS=1 is one solution but perhaps that might be a more "loose" solution in some cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant