Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
proposal: don't include cgo with net on Unix by default #25670
Currently, cgo is included by default with the net package on Unix systems when not cross-compiling to allow the use of libc DNS functions. If the pure Go resolver is sufficiently improved, it should be possible to not include cgo by default (cgo can still be an option).
The net package documentation lists a few cases where the cgo resolver is needed:
If we limit the scope to Unix minus darwin and openbsd, what is the minimum feature set that we need to implement in order to feel comfortable not including the cgo resolver by default?
What's the problem with including it? It's true that most users don't use it but if it's not there, that means the 0.1% or 5% of users who need (who only need it based on data available at run time on their own machine) will fail, and they'll need to recompile.
If your goal is to get rid of all cgo and only generate static binaries by default for Linux, then I assume you also want to modify os/user to not use libc?
I guess I don't see the advantage.
That doesn't mean we can't still improve the pure Go DNS resolver to handle more cases, for at least the popular & easy things. Once it gets down to esoteric, rare, complicated stuff, I'd just punt to libc if it's already there.
The cgo DNS resolver is disabled by default most of the time and must be explicitly enabled. Moving this from a runtime option to a compile time option doesn't seem like a big change to me. In fact, I would argue that the current state makes everyone who compiles binaries on Linux for Linux that use the net package pay in exchange for making things slightly easier for the tiny portion of people with a weird config.
I am not suggesting eliminating the option or even making this change with the current state of DNS in Go. I am asking what improvements would we need to make to the Go resolver in order to feel comfortable with moving the cgo/Go resolver option to purely a compile time option.
Here are some advantages that I think will be commonly appreciated:
Portability. Go binaries that link in libc are less portable than ones that don't. For example, Go binaries dynamically linked against libc compiled on Alpine won't work on Ubuntu and vice versa. This is because Alpine uses musl and most other distros use glibc. I recently ran into this when helping someone debug why their binaries built with the Google Cloud Container Builder didn't work elsewhere.
Cross compilation. Cross-compiling should result in the same binary (when possible) as you would get if you were compiling from the target OS/architecture. This isn't true for Go Linux binaries that include the net package without cgo explicitly disabled. I don't personally do a lot of cross compilation, but given the popularity of doing development for Linux servers on macOS, I would image that it is fairly common.
Security. glibc isn't known for a great security track record. While the code in os/user probably isn't a problem security-wise, using the libc DNS resolver absolutely could be. In fact, a quick survey of glibc CVEs found lots related to DNS.
We need the cgo ability by default for all the reasons @bradfitz already listed. And the cost here is very small - if you really want static binaries it's easy to do CGO_ENABLED=0.
Note that nsswitch.conf includes the names of dynamically loaded C modules. Better to use the C library for that than somehow reinvent it ourselves.