Go 1.16 will make system calls through libc on OpenBSD

February 1, 2021

One of the unusual things about Go is that it started out with the approach of directly making system calls on Unix, instead of calling the standard C library functions that correspond to those system calls. There are reasonably good reasons for Go to make direct system calls and this works well on Linux, but other Unixes are different. The official API for Illumos and Solaris system calls requires you to use their C library, and OpenBSD wants you to do this as well for security reasons (for OpenBSD system call origin verification). Go has used the C library on Solaris and Illumos for a long time, but through Go 1.15 it made direct system calls on OpenBSD and so current released versions of OpenBSD had a special exemption from their system call origin verification because of it.

The news of the time interval for Go 1.16 is that this is changing. To quote from the current draft release notes (which are probably soon to be the official release notes):

On the 64-bit x86 and 64-bit ARM architectures on OpenBSD (the openbsd/amd64 and openbsd/arm64 ports), system calls are now made through libc, instead of directly using the SYSCALL/SVC instruction. This ensures forward-compatibility with future versions of OpenBSD. In particular, OpenBSD 6.9 onwards will require system calls to be made through libc for non-static Go binaries.

As far as I know, Go programs that look up host names or do a few other operations are very likely to not be statically linked. You can force static linking (and you'll normally get it if you cross-build), but it has some drawbacks for hostname lookups in some configurations and you can't do some other operations at all.

At one level everything is okay with this situation. OpenBSD 6.9 will almost certainly include Go 1.16 in its ports collection, since it will be the only version of Go that works on it, and from there you can build Go programs that will run fine on 6.9. At another level, any dynamically linked Go program you have will need to be rebuilt with Go 1.16 before you can run it on OpenBSD 6.9. Hopefully you have the source code and can still build it (in what will be a 'modular by default' world in Go 1.16). This is nothing really new for OpenBSD, which has always made it clear that they don't promise ABI or even API compatibility; you always need to be prepared to rebuild your programs for new OpenBSD versions, and perhaps to update them to more secure APIs.

(Statically linked Go programs built by Go 1.15 or earlier will likely keep working on OpenBSD 6.9, assuming that there are no other ABI changes that affect them. But you should probably plan to rebuild them with Go 1.16 just to be sure. I don't know what the situation will be if you want to create Go binaries that work across a range of OpenBSD versions.)

As the release notes say, Go 1.16 will make system calls through libc for all programs, whether they're dynamically linked or statically linked. Right now OpenBSD only requires this for dynamically linked programs (well, will require it), but always calling via libc is simpler than to maintain two sets of system call code. And someday OpenBSD may do something more elaborate so that making system calls via libc is required even for statically linked programs.

Comments on this page:

By Chris at 2021-02-02 03:14:12:

And if Go used the libc approach on Linux and macOS too, DNS would actually work for users on convoluted (read: non-home) networks too!

By cks at 2021-02-02 09:14:53:

By default, a dynamically linked Go program will use libc to look up hostnames under the right circumstances, with the intent of always working automatically. There's a good discussion of this in the net package's section on name resolution, which covers all sorts of conditions.

Statically linked programs cannot use cgo and so always use the pure Go resolver. On many systems, name resolution also requires loading dynamic (C) libraries, which sort of makes statically linked programs not really truly statically linked.

Written on 01 February 2021.
« The limitations on find's -exec option and implementation convenience
The small oddity in the Unix exec*() family »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Mon Feb 1 22:02:23 2021
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.