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

Hooking a function which isn't used by the shared library causes a SEGV #3

Open
steve-lorimer opened this issue Jul 26, 2016 · 0 comments

Comments

@steve-lorimer
Copy link

Shared library does nothing:

class TestAPI
{
public:
    void work() {}
};

Here I hook the socket function in TestAPI:

#include <iostream>
#include "test_api.h"
#include "elf_hook.h"
#include <dlfcn.h>
#include <string.h>
#include <sys/socket.h>

int hook_socket(int domain, int type, int protocol)
{
    int fd = socket(domain, type, protocol);
    printf("socket: fd(%d) domain(%d) type(%d) protocol(%d)\n", fd, domain, type, protocol);
    return fd;
}

int main()
{
    TestAPI api;

    const char* filename = "/src/build/elfhook/libtest_api.so";

    void* handle = dlopen(filename, RTLD_LAZY);
    if (!handle)
        return 1;

    void* base_address = 0;
    if (get_module_base_address(filename, handle, &base_address) != 0)
        return 1;

    elf_hook(filename, base_address, "socket", (void*)hook_socket);

    api.work();

    return 0;
}

Running it seg faults:

$ ./elfhook/elfhook.bin 
Segmentation fault (core dumped)

GDB stack trace:

(gdb) where
#0  0xffff808868a96e0e in ?? ()
#1  0x00007f7797984c17 in _dl_fini () at dl-fini.c:235
#2  0x00007f7796720fe8 in __run_exit_handlers (status=0, listp=0x7f7796aaa5f8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:82
#3  0x00007f7796721035 in __GI_exit (status=<optimized out>) at exit.c:104
#4  0x00007f7796707837 in __libc_start_main (main=0x409c31 <main()>, argc=1, argv=0x7ffe2f6cd6f8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffe2f6cd6e8) at ../csu/libc-start.c:325
#5  0x0000000000409b19 in _start ()

I'm running glibc-2.23:

$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu3) stable release version 2.23, by Roland McGr

According to the glibc source

  215           /* Is there a destructor function?  */
  216           if (l->l_info[DT_FINI_ARRAY] != NULL
  217               || l->l_info[DT_FINI] != NULL)
  218             {
  219               /* When debugging print a message first.  */
  220               if (__builtin_expect (GLRO(dl_debug_mask)
  221                         & DL_DEBUG_IMPCALLS, 0))
  222             _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
  223                       DSO_FILENAME (l->l_name),
  224                       ns);
  225 
  226               /* First see whether an array is given.  */
  227               if (l->l_info[DT_FINI_ARRAY] != NULL)
  228             {
  229               ElfW(Addr) *array =
  230                 (ElfW(Addr) *) (l->l_addr
  231                         + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
  232               unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
  233                         / sizeof (ElfW(Addr)));
  234               while (i-- > 0)
  235                 ((fini_t) array[i]) ();         // this is the line that seg faults
  236             }
  237

If I change TestAPI::work to actually call socket, then it works fine

class TestAPI
{
public:
    void work() 
    {
        socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    }
};

Running now uses the hooked socket function, and no seg fault

$ ./elfhook/elfhook.bin 
socket: fd(3) domain(2) type(1) protocol(6)

Is there a way to hook functions that may not be called in the shared library, and not have the app seg fault?

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