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

syscall: if $LD_PRELOAD is set, use connect(), execve() in libc #3744

Closed
gopherbot opened this issue Jun 16, 2012 · 28 comments

Comments

Projects
None yet
7 participants
@gopherbot
Copy link

commented Jun 16, 2012

by hongruiqi:

cgoLookupHost may return nil addrs with no err report, which leads to the index out of
range in the net.hostPortToIP by indexing addrs[0].

go version weekly.2012-03-27 +5e3661048f2e
@davecheney

This comment has been minimized.

Copy link
Contributor

commented Jun 16, 2012

Comment 1:

Hi,
Can you please test this with go 1.0.2 (weekly.2012-03-27 is very old).
Can you also please update the issue with your OS, Arch and the full panic message.
Cheers
Dave

Status changed to WaitingForReply.

@gopherbot

This comment has been minimized.

Copy link
Author

commented Jun 16, 2012

Comment 2 by hongruiqi:

+5e3661048f2e is the tip version now...
Gentoo Linux 64bit
uname -a
Linux HRQ-PC 3.2.12-gentoo #16 SMP Fri Jun 8 23:08:57 CST 2012 x86_64 Intel(R) Core(TM)
i3 CPU M 350 @ 2.27GHz GenuineIntel GNU/Linux
panic message:
panic: runtime error: index out of range
goroutine 1 [running]:
net.hostPortToIP(0x6f0704, 0x3, 0xf8400f6b60, 0x15, 0x0, ...)
    /usr/lib/go/src/pkg/net/ipsock.go:127 +0x3c8
net.ResolveTCPAddr(0x6f0704, 0x3, 0xf8400f6b60, 0x70637400000015, 0xf800000000, ...)
    /usr/lib/go/src/pkg/net/tcpsock.go:31 +0x51
net.resolveNetAddr(0x6fd05c, 0x6c61696400000004, 0x6f0704, 0xf800000003, 0xf8400f6b60,
...)
    /usr/lib/go/src/pkg/net/dial.go:50 +0x504
net.Dial(0x6f0704, 0x3, 0xf8400f6b60, 0x7ff900000015, 0x0, ...)
    /usr/lib/go/src/pkg/net/dial.go:92 +0x62
net/http.(*Transport).dial(0xf8400b0840, 0x6f0704, 0x70637400000003, 0xf8400f6b60, 0x15,
...)
    /usr/lib/go/src/pkg/net/http/transport.go:299 +0xd5
net/http.(*Transport).getConn(0xf8400b0840, 0xf8400f2420, 0xf8400f2420, 0x0, 0x0, ...)
    /usr/lib/go/src/pkg/net/http/transport.go:311 +0xbe
net/http.(*Transport).RoundTrip(0xf8400b0840, 0xf8400b8000, 0x3b, 0x0, 0x0, ...)
    /usr/lib/go/src/pkg/net/http/transport.go:155 +0x2ba
net/http.send(0xf8400b8000, 0xf840083030, 0xf8400b0840, 0x0, 0x0, ...)
    /usr/lib/go/src/pkg/net/http/client.go:133 +0x3ca
net/http.(*Client).doFollowingRedirects(0x8a0a80, 0xf8400b8000, 0x0, 0x0, 0x0, ...)
    /usr/lib/go/src/pkg/net/http/client.go:227 +0x61c
----- stack segment boundary -----
net/http.(*Client).Get(0x8a0a80, 0xf8400f7e00, 0x7ff90000003b, 0x34, 0x0, ...)
    /usr/lib/go/src/pkg/net/http/client.go:176 +0xb8
net/http.Get(0xf8400f7e00, 0x7d0000003b, 0xf8400f7e00, 0x0, 0x0, ...)
    /usr/lib/go/src/pkg/net/http/client.go:158 +0x51
main.httpGET(0xf8400f7e00, 0xf80000003b, 0x0, 0x0, 0x0, ...)
    /usr/lib/go/src/cmd/go/http.go:25 +0x77
main.bitbucketVCS(0xf8400f6b00, 0xf8400f6b00, 0x7025c4, 0x6f70657200000004)
    /usr/lib/go/src/cmd/go/vcs.go:645 +0xce
main.repoRootForImportPathStatic(0xf8400f6840, 0x7ff90000001e, 0x6ee114, 0x0, 0x400, ...)
    /usr/lib/go/src/cmd/go/vcs.go:388 +0x76f
main.repoRootForImportPath(0xf8400f6840, 0x1e, 0x4, 0x30, 0xf840000438, ...)
    /usr/lib/go/src/cmd/go/vcs.go:323 +0x4e
main.downloadPackage(0xf8400faa00, 0xf8400e5180, 0xf8400f6840, 0xf80000001e)
    /usr/lib/go/src/cmd/go/get.go:242 +0x1192
main.download(0xf8400f6840, 0x10000001e, 0x7ff9118cbdb0, 0x100000001, 0x100000000, ...)
    /usr/lib/go/src/cmd/go/get.go:161 +0x7ec
main.runGet(0x89b660, 0xf840083020, 0x100000001, 0x0)
    /usr/lib/go/src/cmd/go/get.go:68 +0xc6
main.main()
    /usr/lib/go/src/cmd/go/main.go:141 +0x48e
goroutine 2 [syscall]:
created by runtime.main
    /usr/lib/go/src/pkg/runtime/proc.c:221
@gopherbot

This comment has been minimized.

Copy link
Author

commented Jun 16, 2012

Comment 3 by hongruiqi:

I use the proxychains4 to redirect the socks connection in go get, though useless in
pure go, but may be the cause lead to the error...
@minux

This comment has been minimized.

Copy link
Member

commented Jun 16, 2012

Comment 4:

yes, i think proxychains4 is the root cause.
part of go net library calls libc's dns lookup functions, which get intercepted by
proxychains4;
but other part of go use networking syscalls directly, and won't be intercepted by
proxychains4.
there is no easy solutions to this problem. transparent socks proxy for 'go get' is
not possible, iiuc.
@rsc

This comment has been minimized.

Copy link
Contributor

commented Jun 19, 2012

Comment 5:

Which system calls does a transparent socks proxy want to hook into?
@gopherbot

This comment has been minimized.

Copy link
Author

commented Jun 19, 2012

Comment 6 by hongruiqi:

$ nm libproxychains4.so 
0000000000206d60 a _DYNAMIC
0000000000206fe8 a _GLOBAL_OFFSET_TABLE_
                 w _Jv_RegisterClasses
0000000000206d50 d __DTOR_END__
0000000000207220 A __bss_start
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000207210 d __dso_handle
                 U __errno_location@@GLIBC_2.2.5
                 w __gmon_start__
0000000000207220 A _edata
00000000011843c8 A _end
0000000000005718 T _fini
0000000000001e28 T _init
                 U abort@@GLIBC_2.2.5
00000000002072a0 b addr_name
                 U atoi@@GLIBC_2.2.5
0000000000005740 r base64
00000000002092c0 b buf.5444
0000000000003819 t calc_alive
000000000000387a t chain_step
                 U close@@GLIBC_2.2.5
0000000000005116 T connect
00000000000039c7 T connect_proxy_chain
000000000000233c T dalias_hash
                 U dlerror@@GLIBC_2.2.5
                 U dlsym@@GLIBC_2.2.5
                 U dup2@@GLIBC_2.2.5
0000000000002579 t encode_base_64
                 U exit@@GLIBC_2.2.5
                 U fclose@@GLIBC_2.2.5
                 U fcntl@@GLIBC_2.2.5
                 U fflush@@GLIBC_2.2.5
                 U fgets@@GLIBC_2.2.5
                 U fopen@@GLIBC_2.2.5
                 U fprintf@@GLIBC_2.2.5
                 U fputs@@GLIBC_2.2.5
                 U free@@GLIBC_2.2.5
0000000000005481 T freeaddrinfo
                 U fwrite@@GLIBC_2.2.5
000000000000478d t get_chain_data
00000000000053f5 T getaddrinfo
                 U getenv@@GLIBC_2.2.5
00000000000055de T gethostbyaddr
00000000000053aa T gethostbyname
                 U gethostent@@GLIBC_2.2.5
                 U gethostname@@GLIBC_2.2.5
00000000000054e3 T getnameinfo
                 U getservbyname@@GLIBC_2.2.5
                 U getsockopt@@GLIBC_2.2.5
                 U gettimeofday@@GLIBC_2.2.5
00000000002092e0 b he.5447
0000000000207260 b hostent_space
                 U htons@@GLIBC_2.2.5
000000000000239f T index_from_internal_ip
                 U inet_addr@@GLIBC_2.2.5
                 U inet_aton@@GLIBC_2.2.5
                 U inet_ntop@@GLIBC_2.2.5
                 U inet_pton@@GLIBC_2.2.5
00000000002092b8 b init_l
00000000000044bc t init_lib
0000000000207240 B internal_ips
0000000000209360 B internal_ips_lock
0000000000209300 b ipv4.5445
0000000000209310 b list.5446
00000000000058ac r local_host
00000000011813c0 B localnet_addr
000000000000244b T make_internal_ip
                 U malloc@@GLIBC_2.2.5
                 U memcpy@@GLIBC_2.14
                 U memset@@GLIBC_2.2.5
                 U ntohl@@GLIBC_2.2.5
                 U ntohs@@GLIBC_2.2.5
00000000002092b0 B num_localnet_addr
                 U perror@@GLIBC_2.2.5
                 U poll@@GLIBC_2.2.5
0000000000002499 t poll_retry
0000000000004252 T proxy_getaddrinfo
0000000000003e91 T proxy_gethostbyname
00000000002093a0 B proxychains_ct
00000000002092a0 B proxychains_got_chain_data
0000000000207218 D proxychains_max_chain
00000000002093c0 B proxychains_pd
00000000002092ac B proxychains_proxy_count
00000000002092a4 B proxychains_quiet_mode
00000000002092a8 B proxychains_resolver
00000000000027cf T proxychains_write_log
                 U pthread_mutex_init@@GLIBC_2.2.5
                 U pthread_mutex_lock@@GLIBC_2.2.5
                 U pthread_mutex_unlock@@GLIBC_2.2.5
                 U rand@@GLIBC_2.2.5
                 U read@@GLIBC_2.2.5
000000000000295b t read_n_bytes
                 U realloc@@GLIBC_2.2.5
0000000000003780 t release_all
00000000000037be t release_busy
000000000020721c D remote_dns_subnet
0000000000207280 b resolved_addr
0000000000207290 b resolved_addr_p
0000000000003615 t select_proxy
                 U send@@GLIBC_2.2.5
                 U snprintf@@GLIBC_2.2.5
                 U socket@@GLIBC_2.2.5
                 U srand@@GLIBC_2.2.5
                 U sscanf@@GLIBC_2.2.5
00000000000034e3 t start_chain
                 U stderr@@GLIBC_2.2.5
                 U strcat@@GLIBC_2.2.5
                 U strchr@@GLIBC_2.2.5
                 U strcmp@@GLIBC_2.2.5
                 U strcpy@@GLIBC_2.2.5
00000000000023d9 T string_from_internal_ip
                 U strlen@@GLIBC_2.2.5
                 U strncpy@@GLIBC_2.2.5
                 U strspn@@GLIBC_2.2.5
                 U strstr@@GLIBC_2.2.5
00000000002093a4 B tcp_connect_time_out
00000000011843c0 B tcp_read_time_out
                 U time@@GLIBC_2.2.5
00000000000029f9 t timed_connect
0000000000209340 B true_connect
0000000000209330 B true_freeaddrinfo
0000000000209320 B true_getaddrinfo
0000000000209338 B true_gethostbyaddr
0000000000209348 B true_gethostbyname
0000000000209328 B true_getnameinfo
0000000000002aff t tunnel_to
                 U vsprintf@@GLIBC_2.2.5
                 U write@@GLIBC_2.2.5
00000000000028ec t write_n_bytes
@minux

This comment has been minimized.

Copy link
Member

commented Jun 19, 2012

Comment 7:

Re #5, current transparent sock proxy only uses dynamic linker tricks
to hook libc implementation of socket functions, and it won't hook any
syscall calls (if it does, then this issue won't exist anymore.)
@rsc

This comment has been minimized.

Copy link
Contributor

commented Jun 19, 2012

Comment 8:

I'm pretty reluctant, but one thing we could possibly do is say that
if $LD_PRELOAD is set, then we'll use cgo for the connect system call
too. It looks like that would be enough.
Russ
@minux

This comment has been minimized.

Copy link
Member

commented Aug 21, 2012

Comment 9:

Labels changed: added priority-later, removed priority-triage.

Status changed to Accepted.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Sep 12, 2012

Comment 10:

Labels changed: added go1.1maybe.

@minux

This comment has been minimized.

Copy link
Member

commented Nov 29, 2012

Comment 11:

From https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/3ZmHFXqiUA0:
maybe we need to also use execve from libc if LD_PRELOAD is set.
@robpike

This comment has been minimized.

Copy link
Contributor

commented Mar 7, 2013

Comment 12:

Labels changed: removed go1.1maybe.

@minux

This comment has been minimized.

Copy link
Member

commented Jun 19, 2013

Comment 13:

one complexity of this issue: syscall package couldn't rely on cgo
(or there will be circular dependencies between cmd/cgo and syscall).
of course, we can use the same bootstrap mechanism for cmd/go to solve
this problem, but i'd rather not to complicate the build mechanism for
such small feature.
any suggestions? could we move the connect hook to the net package?
but then, what about the execve hook?
@rsc

This comment has been minimized.

Copy link
Contributor

commented Jun 21, 2013

Comment 14:

This is looking more and more like a mistake.
Unless someone shows me that it's super-simple, let's not do this.
@minux

This comment has been minimized.

Copy link
Member

commented Jun 30, 2013

Comment 15:

i come up with a simple solution:
we make runtime/cgo pulls in connect and execve from libc (only on unix) privately,
and call it conditionally using 6c code in syscall.
if cgo is available, then runtime/cgo will always be there, so this will work whenever
possible.
what do you think, Russ?
@rsc

This comment has been minimized.

Copy link
Contributor

commented Jul 8, 2013

Comment 16:

It would be easier to judge if you can show me the CL.
@minux

This comment has been minimized.

Copy link
Member

commented Jul 8, 2013

Comment 17:

please take a look at https://golang.org/cl/11010043/ the preliminary version
that implements my idea.
@minux

This comment has been minimized.

Copy link
Member

commented Jul 8, 2013

Comment 18:

CL 11010043 is finished and ready for test and review.
for transparent socks proxy to work, it must support nonblocking sockets.
(for example, tsocks 1.8 doesn't, so it has to be patched with the little
patch below:
--- tsocks-1.8/tsocks.c 2002-07-16 06:50:52.000000000 +0800
+++ tsocks-1.8-hacked/tsocks.c  2013-07-09 06:01:36.540725793 +0800
@@ -326,8 +326,13 @@
       errno = ECONNREFUSED;
       return(-1);
    } else {
+      int old_flag = fcntl(__fd, F_GETFL);
+      if(old_flag & O_NONBLOCK)
+             fcntl(__fd, F_SETFL, old_flag & ~O_NONBLOCK);
       /* Now we call the main function to handle the connect. */
       rc = handle_request(newconn);
+      if(old_flag & O_NONBLOCK)
+             fcntl(__fd, F_SETFL, old_flag);
       /* If the request completed immediately it mustn't have been
        * a non blocking socket, in this case we don't need to know
        * about this socket anymore. */
)
@rsc

This comment has been minimized.

Copy link
Contributor

commented Jul 30, 2013

Comment 19:

Labels changed: added go1.2maybe.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Jul 30, 2013

Comment 20:

Labels changed: added feature.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Aug 1, 2013

Comment 21:

CL 11010043 looks okay, I guess, except that I'm still a bit creeped out by
the whole idea.
@robpike

This comment has been minimized.

Copy link
Contributor

commented Aug 16, 2013

Comment 22:

Is this "fix" going to be in 1.2?
@rsc

This comment has been minimized.

Copy link
Contributor

commented Sep 6, 2013

Comment 23:

I replied on the CL. Let's hold off on this.

Labels changed: added go1.3maybe, removed go1.2maybe.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Nov 27, 2013

Comment 24:

Labels changed: removed feature.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Dec 4, 2013

Comment 25:

Labels changed: added release-none, removed go1.3maybe.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Dec 4, 2013

Comment 26:

Labels changed: added repo-main.

@rsc rsc added this to the Unplanned milestone Apr 10, 2015

@ymmt2005

This comment has been minimized.

Copy link

commented Aug 8, 2016

FWIW, transparent proxy can be done without using LD_PRELOAD.
I have blogged one such solution using Go on Linux.
http://ymmt2005.hatenablog.com/entry/2016/03/13/Transparent_SOCKS_proxy_in_Go_to_replace_NAT

@bradfitz

This comment has been minimized.

Copy link
Member

commented Sep 9, 2016

I don't think this is ever going to happen.

We don't like calling into C from Go more than we have to, and have moved to minimize when we do so (e.g. we prefer our own DNS resolver when possible).

I agree with the page that @ymmt2005 referenced, which says: "Using iptables is far better than LD_PRELOAD for transparent proxy."

@bradfitz bradfitz closed this Sep 9, 2016

@golang golang locked and limited conversation to collaborators Sep 9, 2017

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.