0

Is that true that Go dynamic linked to libc in Linux and Mac is different? I am trying to evaluate the use of LD_PRELOAD (Linux) or DYLD_INSERT_LIBRARIES (macOS) to intercept the bind (listen) function. It's working on macOS but not on Linux.

On macOS:

❯ otool -tV main | grep bind
_x_cgo_bindm:
0000000100090134        bl      _syscall.bind
_syscall.bind:
0000000100090578        b       _syscall.bind
_syscall.libc_bind_trampoline.abi0:

On Linux:

# objdump -T ./main

./main:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000545a80 g    DF .text  0000000000000063  Base        crosscall2
0000000000545a40 g    DF .text  0000000000000037  Base        _cgo_panic
0000000000466ae0 g    DF .text  0000000000000019  Base        _cgo_topofstack
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) __errno_location
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) getaddrinfo
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) free
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) freeaddrinfo
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) gai_strerror
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) stderr
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) fwrite
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) vfprintf
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) fputc
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) abort
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_mutex_lock
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.3.2) pthread_cond_wait
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_mutex_unlock
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.3.2) pthread_cond_broadcast
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.34) pthread_create
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) nanosleep
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.34) pthread_detach
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) strerror
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) fprintf
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) malloc
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_attr_init
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.34) pthread_attr_getstacksize
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) pthread_attr_destroy
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigfillset
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.32) pthread_sigmask
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) mmap
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) munmap
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) setenv
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) unsetenv
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigemptyset
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigaddset
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigaction
0000000000000000      DO *UND*  0000000000000000 (GLIBC_2.2.5) sigismember

Is there anyway to force Go binary in Linux use bind/connect function as macOS?

1 Answer 1

0

On Linux:

The binary doesn't depend on the bind symbol, but that doesn't necessarily mean that you can't use LD_PRELOAD to interpose bind for that binary.

If that binary was built with gccgo, chances are it depends on libgo.so.*, which (on my system) does depend on bind and connect:

readelf -Ws /usr/lib64/libgo.so.22 | grep -E ' (bind|connect)'
    77: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND connect@GLIBC_2.2.5 (2)
   224: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND bind@GLIBC_2.2.5 (2)
140156: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND connect@GLIBC_2.2.5
163145: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND bind@GLIBC_2.2.5

Update:

curious if your building with gccgo actually get hooked by LD_PRELOAD simple bind function?

Yes, it does. I compiled this example with gccgo tcp_server.go, and compiled this code:

void bind() { abort(); }

with gcc -w -shared -fPIC -o bind.so bind.c

Finally I ran: LD_PRELOAD=./bind.so ./a.out and it produced:

SIGABRT: abort
PC=0x7f83d3965884 m=0 sigcode=18446744073709551610

goroutine 1 [syscall]:
__pthread_kill_implementation
        :0
gsignal
        :0
__GI_abort
        :0
syscall.Bind
        :0
...

Note however, that my ldd output shows dependency on libgo.so, while yours does not. Here is what I see:

ldd a.out
        linux-vdso.so.1 (0x00007ffc574f8000)
        libgo.so.22 => /lib64/libgo.so.22 (0x00007f21d5f7d000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f21d5e9c000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f21d5e78000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f21d5c9a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f21d7bb1000)
Sign up to request clarification or add additional context in comments.

4 Comments

Hi, thank for your quick responding. I think my binary dep also have that. Still LD_PRELOAD does not get hooked ``` ldd main linux-vdso.so.1 (0x00007ffe545f4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5609501000) /lib64/ld-linux-x86-64.so.2 (0x00007f56096e7000) ``` ``` readelf -Ws /lib/x86_64-linux-gnu/libc.so.6 | grep -E '(connect|bind)' 845: 000000000010a4a0 33 FUNC WEAK DEFAULT 16 bind@@GLIBC_2.2.5 2556: 000000000010a4d0 155 FUNC WEAK DEFAULT 16 connect@@GLIBC_2.2.5 ```
curious if your building with gccgo actually get hooked by LD_PRELOAD simple bind function? Or your binary actually have the bind symbol?
@user1929999 I've updated the answer. How exactly are you building your binary?
Amazing. Thanks. > On Linux: i used the standard go build main.go > On macOS (cross compiled): ❯ CC=x86_64-unknown-linux-gnu-gcc CGO_ENABLED=1 GOARCH=amd64 GOOS=linux go build -o main.linuxamd main.go Will look more into the gccgo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.