Thread: Can someone please fix this poll function ?

  1. #1
    Registered User
    Join Date
    Sep 2012
    Posts
    50

    Can someone please fix this poll function ?

    I need to wrap poll()
    and this is what i am trying to use
    Code:
    #include <poll.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    
    int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
         usleep(100);
        return  __real_poll(fds,nfds,timeout);
    
    
    
    
    }
    and this is how i compile
    $gcc -fPIC -Wl,--wrap,poll -c poll.c
    $ gcc -shared -Wl,--wrap,poll -o poll.so poll.o

  2. #2
    Registered User
    Join Date
    Sep 2012
    Posts
    50
    It compiles without error but my poll is not getting called
    1. Preload works as i have tested it with removing wrap, then it gets into the function ( tested by adding a printf )

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    I thought we beat this to death in your other thread

    First off, this --wrap thing ONLY works when you have the source code, and you're linking your program with a library. Since you say in your other thread that you have a statically linked executable with NO source code (actually, you say a lot of contradictory things as well), then this wrapping just isn't going to work.

    Here is my test code.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/time.h>
    #include <poll.h>
    #include <unistd.h>
    
    void doit ( void ) {
        while ( 1 ) {
            struct pollfd   p = { 0, POLLIN, 0 };
            int result = poll(&p,1,0);
            if ( result > 0 ) {
                char buff[100];
                int n = read(0,buff,sizeof(buff));
                int ch = buff[0];
                write(1,buff,n);
                if ( ch == 'q' ) break;
                if ( ch == 'c' ) {
                    int *dummy = 0;
                    *dummy = 0;
                }
            } else {
                struct timeval  now;
                int r = gettimeofday(&now,NULL);
            }
            sleep(1);
        }
    }
               
    int main ( ) {
        doit();
        return 0;
    }
    Now run it, and strace it.
    Code:
    $ # Normal run
    $ ./a.out 
    hello
    hello
    quit
    quit
    $ strace ./a.out 
    execve("./a.out", ["./a.out"], [/* 40 vars */]) = 0
    brk(0)                                  = 0x1692000
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f07c7de1000
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=145635, ...}) = 0
    mmap(NULL, 145635, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f07c7dbd000
    close(3)                                = 0
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \24\2\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=1685816, ...}) = 0
    mmap(NULL, 3801960, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f07c7822000
    mprotect(0x7f07c79b9000, 2093056, PROT_NONE) = 0
    mmap(0x7f07c7bb8000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x196000) = 0x7f07c7bb8000
    mmap(0x7f07c7bbd000, 21352, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f07c7bbd000
    close(3)                                = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f07c7dbc000
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f07c7dba000
    arch_prctl(ARCH_SET_FS, 0x7f07c7dba720) = 0
    mprotect(0x7f07c7bb8000, 16384, PROT_READ) = 0
    mprotect(0x600000, 4096, PROT_READ)     = 0
    mprotect(0x7f07c7de3000, 4096, PROT_READ) = 0
    munmap(0x7f07c7dbd000, 145635)          = 0
    poll([{fd=0, events=POLLIN}], 1, 0)     = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 0x7fff5c3977c0)       = 0
    poll([{fd=0, events=POLLIN}], 1, 0)     = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, quit
    0x7fff5c3977c0)       = 0
    poll([{fd=0, events=POLLIN}], 1, 0)     = 1 ([{fd=0, revents=POLLIN}])
    read(0, "quit\n", 100)                  = 5
    write(1, "quit\n", 5quit
    )                   = 5
    exit_group(0)                           = ?
    Notice that the calls to poll have a zero timeout - as one would expect from looking at the code.

    Now try some .so code injection using LD_PRELOAD.
    This only works if the executable is dynamically linked, so that the dynamic link loader can patch things up as the program loads.
    Again, a normal run and a strace.
    Code:
    $ LD_PRELOAD=`pwd`/libbar.so ./a.out
    library loaded!
    Libc found - poll=0x7f4fbff03420
    trap poll called
    hetrap poll called
    llo
    hello
    trap poll called
    qutrap poll called
    it
    trap poll called
    quit
    $ strace -ELD_PRELOAD=`pwd`/libbar.so ./a.out
    execve("./a.out", ["./a.out"], [/* 41 vars */]) = 0
    brk(0)                                  = 0x9a4000
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fde35219000
    open("/home/sc/Documents/libbar.so", O_RDONLY) = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\6\0\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0775, st_size=8232, ...}) = 0
    mmap(NULL, 2101328, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fde34df9000
    mprotect(0x7fde34dfa000, 2093056, PROT_NONE) = 0
    mmap(0x7fde34ff9000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x7fde34ff9000
    close(3)                                = 0
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=145635, ...}) = 0
    mmap(NULL, 145635, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fde351f5000
    close(3)                                = 0
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \24\2\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=1685816, ...}) = 0
    mmap(NULL, 3801960, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fde34a58000
    mprotect(0x7fde34bef000, 2093056, PROT_NONE) = 0
    mmap(0x7fde34dee000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x196000) = 0x7fde34dee000
    mmap(0x7fde34df3000, 21352, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fde34df3000
    close(3)                                = 0
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    open("/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY) = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340\r\0\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0644, st_size=14768, ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fde351f4000
    mmap(NULL, 2109704, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fde34854000
    mprotect(0x7fde34856000, 2097152, PROT_NONE) = 0
    mmap(0x7fde34a56000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fde34a56000
    close(3)                                = 0
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fde351f2000
    arch_prctl(ARCH_SET_FS, 0x7fde351f2720) = 0
    mprotect(0x7fde34a56000, 4096, PROT_READ) = 0
    mprotect(0x7fde34dee000, 16384, PROT_READ) = 0
    mprotect(0x7fde34ff9000, 4096, PROT_READ) = 0
    mprotect(0x600000, 4096, PROT_READ)     = 0
    mprotect(0x7fde3521b000, 4096, PROT_READ) = 0
    munmap(0x7fde351f5000, 145635)          = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fde35218000
    write(1, "library loaded!\n", 16library loaded!
    )       = 16
    brk(0)                                  = 0x9a4000
    brk(0x9c5000)                           = 0x9c5000
    write(1, "Libc found - poll=0x7fde34b2f420"..., 33Libc found - poll=0x7fde34b2f420
    ) = 33
    write(1, "trap poll called\n", 17trap poll called
    )      = 17
    poll([{fd=0, events=POLLIN}], 1, 1000)  = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 0x7fff65ffdc10)       = 0
    write(1, "trap poll called\n", 17trap poll called
    )      = 17
    poll([{fd=0, events=POLLIN}], 1, 1000quit)  = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 
    0x7fff65ffdc10)       = 0
    write(1, "trap poll called\n", 17trap poll called
    )      = 17
    poll([{fd=0, events=POLLIN}], 1, 1000)  = 1 ([{fd=0, revents=POLLIN}])
    read(0, "quit\n", 100)                  = 5
    write(1, "quit\n", 5quit
    )                   = 5
    exit_group(0)                           = ?
    Notice this time that poll() is being called with a timeout of 1000

    Here is my patch code, and how I built it.
    Code:
    #include <poll.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <dlfcn.h>
    
    typedef int (*pfn)(struct pollfd *, nfds_t, int);
    
    static pfn realPoll = NULL;
    
    __attribute__((constructor)) void init(void) {
        printf("library loaded!\n");
        void *p = dlopen("libc.so.6",RTLD_NOW);
        if ( p ) {
            realPoll = dlsym(p,"poll");
            printf("Libc found - poll=%p\n", (void*)realPoll);
        } else {
            printf("Err=%s\n", dlerror() );
        }
    }
    
    int poll( struct pollfd *fds, nfds_t nfds, int timeout ) {
        int result = 0;
        printf("trap poll called\n");
        if ( realPoll ) {
            if ( timeout == 0 ) timeout = 1000;
            result = realPoll(fds,nfds,timeout);
        }
        return result;
    }
    
    $ gcc -fPIC -c bar.c -ldl ; gcc -shared -o libbar.so bar.o -ldl
    $ gcc foo.c -ldl
    Finally, compile the main program statically, with
    Code:
    $ gcc -static foo.c -ldl
    $ LD_PRELOAD=`pwd`/libbar.so ./a.out
    hello
    hello
    quit
    quit
    $ strace -ELD_PRELOAD=`pwd`/libbar.so ./a.out
    execve("./a.out", ["./a.out"], [/* 41 vars */]) = 0
    uname({sys="Linux", node="OAK", ...})   = 0
    brk(0)                                  = 0x1ad0000
    brk(0x1ad11a0)                          = 0x1ad11a0
    arch_prctl(ARCH_SET_FS, 0x1ad0880)      = 0
    brk(0x1af21a0)                          = 0x1af21a0
    brk(0x1af3000)                          = 0x1af3000
    poll([{fd=0, events=POLLIN}], 1, 0)     = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 0x7fff487e66f0)       = 0
    poll([{fd=0, events=POLLIN}], 1, 0)     = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, 0x7fff487e66f0)       = 0
    poll([{fd=0, events=POLLIN}], 1, 0)     = 0 (Timeout)
    rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
    rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    nanosleep({1, 0}, quit
    0x7fff487e66f0)       = 0
    poll([{fd=0, events=POLLIN}], 1, 0)     = 1 ([{fd=0, revents=POLLIN}])
    read(0, "quit\n", 100)                  = 5
    write(1, "quit\n", 5quit
    )                   = 5
    exit_group(0)                           = ?
    And we're back to where we started.
    The LD_PRELOAD has no effect, it does NOT get initialised, and poll is back to being called with ZERO timeout.

    Then there is this
    Code:
    $ file ./a.out 
    ./a.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.15, not stripped
    
    $ strip a.out
    $ file ./a.out 
    ./a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.15, stripped
    If you have a statically linked executable that has been stripped of symbols, you are basically screwed.



    C guru help needed URGENT
    --- SIGSEGV (Segmentation fault) @ 0 (0) ---
    +++ killed by SIGSEGV (core dumped) +++
    C guru help needed URGENT
    btw there is no corefile
    But as I've said already, the program is crashing because it is trying to dereference a NULL pointer - that's what the "SIGSEGV (Segmentation fault) @ 0 (0)" means. It almost certainly has nothing to do with recv or poll or any other system call. You might mess around with them (say changing timeout), and that just might sweep the problem under the carpet for a while, but it is no solution.

    I'm going to wait for you to confirm a few FACTS about the situation you're facing before trying to figure out any possible work-around.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Sep 2012
    Posts
    50
    Code:
    #include <poll.h>
    #include <unistd.h>
    #include <stdio.h>
    int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
        usleep(100);
         printf("Sleeping\n");
        return  poll(fds,nfds,timeout);
    }

    Salem ,
    I am sorry for the hassle , but i am new to this as you might have guessed

    if the program is NOT using my poll .. ( or cannot use it )
    why do i get ( not trying to be an ass , just trying to understand )
    sleeping

    repeatedly ( as i want it to print ) on the screen when i compile this code ?
    Last edited by NetworkLearning; 09-23-2012 at 12:47 PM.

  5. #5
    Registered User
    Join Date
    Sep 2012
    Posts
    50
    What i am basically doing is not wrapping poll , and calling poll from poll again , so it gets called a few hundred times before i kill the program
    so i know its getting called
    i hope i am able to convey what i want to ?

  6. #6
    Registered User
    Join Date
    Sep 2012
    Posts
    50
    Ok i re-read your whole posts .. i will give you this i am over my head ..but can you help ? what FACTS would you like me to share ? i can share my screen with you on teamviewer if that helps ?

  7. #7
    Registered User
    Join Date
    Sep 2012
    Posts
    50
    Btw i just ran
    file on the program

    ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, stripped

  8. #8
    Registered User
    Join Date
    Sep 2012
    Posts
    50
    Got the poll function working , but now it only lasts a little bit longer , still dies

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well since it is "dynamically linked", then the LD_PRELOAD should work (as you seem to have found).
    The downside is that it has been "stripped", meaning there is no symbol table to assist with debugging.

    You said there was no corefile, despite "core dumped" in some messages.

    Try
    Code:
    $ ulimit -a
    core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    <snipped>
    You might have to do
    ulimit -c unlimited
    in your shell before running the program, before running the program, in order to get a corefile.

    Whilst you can look at the crashed state of the program using gdb, you won't get very far at your level of expertise.

    Without symbols in the executable, there is little you can do to debug it.
    Without the source code, there is little you can do to fix it.

    So, where is the source code!?
    Given that everything is open source on Linux, it seems strange that you don't have any source code.

    The fact that the program runs normally as a single instance is probably just luck as much as anything else. Programs often fail when stressed in a new way, and I see no reason to think this would be any different.

    For example, it it was developed and tested on a single core machine, then any attempt to run more than one copy would have used time slicing to apportion time to each running instance. But when you run it on a true multi-core machine, both instances really are running at the same time.

    FWIW, I don't think this strategy of patching often-used functions is going to work. As you are observing, all you're doing is changing the timing of the crash. Calling poll() with a zero timeout might be poor resource utilisation, but in itself, it won't cause segfaults from dereferencing a NULL pointer.

    > btw i ran boomerang on the binary and have some code that i can share if that will help
    Is this some kind of "reverse engineering / decompiler" tool to generate some very bad 'C' code?

    > ubuntu 12.04
    Do you know which version it was compiled on and tested on?
    Is there any chance of trying to duplicate the circumstances on an older Linux version?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Poll
    By Dae in forum Windows Programming
    Replies: 9
    Last Post: 08-12-2009, 07:01 PM
  2. poll() function
    By kris.c in forum C Programming
    Replies: 2
    Last Post: 05-29-2007, 04:24 AM
  3. Poll() function
    By dark_fire in forum C Programming
    Replies: 2
    Last Post: 07-17-2005, 03:32 PM
  4. Poll!
    By funkydude9 in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-19-2003, 09:28 AM
  5. C better than C++? (POLL)
    By Lynux-Penguin in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 05-03-2002, 03:34 PM