0

I am working on a project which requires wrapping libc system calls particularly file i/o calls like open, read, write, close etc. I am intending to use this as a monitoring service for the file operations.

I have successfully wrapped all the calls and the wrapper works perfectly fine when I try to open a text file with gedit. But, the problem is I am not able to start google chrome and few other applications when the wrapper is preloaded. Google chrome in particular goes to an infinite nanosleep loop. You can see the strace below.

After debugging I found out that it's the read and close system calls which are causing the issue. When I remove the wrapper functions for read and close everything works fine. One thing I can do is disable the wrapper for google chrome but I am curious to know if anyone has faced the same issue and found any work arounds or solutions. I have seen other wrapper implementations and tried them as well, it runs into the same problem. Am I missing something very trivial here?

set_tid_address(0x7f140cddad50)         = 23827
set_robust_list(0x7f140cddad60, 24)     = 0
rt_sigaction(SIGRTMIN, {0x7f140c867b50, [], SA_RESTORER|SA_SIGINFO, 0x7f140c873390}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {0x7f140c867be0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7f140c873390}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
open("/dev/urandom", O_RDONLY)          = 3
futex(0x7f140c8610a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0
nanosleep({0, 2000001}, NULL)           = 0

Here's my wrapper function for read():

ssize_t read(int fd, void *buf, size_t count) {
    ssize_t (*libc_read) (int df, void* buf, size_t count);

    dlerror();

    libc_read = (ssize_t (*) (int df, void* buf, size_t count)) 
    dlsym(RTLD_NEXT, "read");

    // If a dynamic link error occurred
    if (dlerror() || (libc_read == NULL)) {
        return EOF;
    }

    // Call the system function
    size_t bytes_read = libc_read(fd, buf, count);

    return bytes_read;
}
jww
  • 97,681
  • 90
  • 411
  • 885
  • In general I believe intercepting kernel functions like `open` and `read` does not work. Or at least that is what the kernel folks say. Also see [Query regarding kernel modules intercepting system call](https://lists.kernelnewbies.org/pipermail/kernelnewbies/2017-July/018091.html) on the kernel-newbies mailing list and [Multiple kernel modules intercepting same system call and crash during unload](https://stackoverflow.com/q/44983399/608639) on Stack Overflow. And see [System call interception in linux-kernel module](https://stackoverflow.com/q/13876369/608639) for folks who say it is possible – jww May 28 '18 at 02:56
  • @jww this isn't intercepting the actual syscall, like any of those examples; just the wrapper function for it in libc. – hobbs May 28 '18 at 03:15
  • Don't call dlsym at every `read`; instead write a function that perform `dlsym` for every functions, and call that function _exactly once._ – Lorinczy Zsigmond May 28 '18 at 10:09
  • thanks jww for your response. But, as @hobbs said i am not intercepting the actual syscall. – HARIHARA VARMA INDUKURI May 28 '18 at 15:44
  • @LorinczyZsigmond yes, that might be a problem. – hobbs May 28 '18 at 17:25
  • Thanks @LorinczyZsigmond. I will try that. – HARIHARA VARMA INDUKURI May 29 '18 at 17:17

0 Answers0