-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/link: define ELF .note section on FreeBSD #48164
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
Comments
What do these notes do? Why would we want to add them? |
Is there any document for those? What do they mean? Thanks. |
This issue is related to #48112
I hope @emaste can share more insight on the other notes. |
Is there a reason why we would want to set any of these? |
NT_FREEBSD_ABI_TAG indicates what version of FreeBSD the binary was compiled for and does two things: (a) when there are breaking changes to kernel behaviour that can sometimes be gated behind binaries saying they were built for a version that already had that behaviour, so existing binaries don't break (b) there is a sysctl you can enable to stop you running binaries built for newer kernels than the one you are running. Most things work without it but you may see strange behaviour in edge cases if you don't put an appropriate version there. (Also an honorary mention for RISC-V: RISC-V binaries end up with NT_FREEBSD_ABI_TAG being the only FreeBSD branding for statically-linked binaries, so without that you'll get ENOEXEC for them on FreeBSD, and for dynamically-linked binaries ldd will give an error that it's not a FreeBSD binary. I go back and forth on whether the lack of EI_OSABI being ELFOSABI_FREEBSD (a field which gets abused for multiple purposes so there's an argument to be made for relying on extensible ELF notes and stopping conflating what that field means) is a good idea, but it's what happens today.) NT_FREEBSD_NOINIT_TAG tells the run-time linker (well, its presence or lack thereof, the value is unused) whether or not the CRT files call _init, .ctors and .init_array or RTLD is expected to; the old GNU-derived files called them themselves, the new from-scratch BSD-licensed replacements leave it up to RTLD to do. Whether or not you define this should be based on whether Go's runtime calls these functions or expects the run-time linker to (though if you only do static linking it's not consulted, and if you never try to make use of those various constructor-like features then whether it exists doesn't matter). NT_FREEBSD_FEATURE_CTL tells the kernel whether or not you are opting out of various security features. If it doesn't exist then you don't opt out of anything and there is no way to change that; if you add it but set it to 0 then elfctl can later change the value (e.g. a user discovers that a binary breaks with a certain hardening feature applied), but it cannot add the note if it doesn't exist in the first place. So you must define NT_FREEBSD_ABI_TAG and NT_FREEBSD_FEATURE_CTL appropriately, and whether or not you should define NT_FREEBSD_NOINIT_TAG depends on what exactly Go does and supports. Things generally work without them but sooner or later something somewhere will break as a result of playing it fast and loose. Of course, the best thing to do is use the system's CRT files rather than doing everything from scratch, as it's only a backwards-compatible interface so existing binaries work, not a stable one that we don't guarantee won't change (e.g. someone could technically add a new note tomorrow that's required for FreeBSD 14 binaries, even if it's highly unlikely). |
|
It's really only used in a handful of places: a few sysctls, mmap gained a couple of checks for nonsense arguments like len == 0, the shutdown(2) socket syscall started to return ENOTCONN when issued on a socket that wasn't connected, sigwait(2) started to return EINTR rather than looping, and whether you get a SIGBUS or SIGSEGV for page faults due to permissions, that kind of subtle thing that almost never matters until it does. My guess is the right thing to do is set the version to whatever you assume the version of FreeBSD to be, and you can dynamically detect support for newer syscalls if you want (though watch out for SIGSYS), though don't quote me on that because I don't know what we guarantee, if anything (the CRT files are supposed to be kept in sync with your system header files, so it's not normally possible to know about new syscalls that your ABI note doesn't say you should know about unless you hard-code the number in your C source).
The tag is for precisely when you don't call those functions. If those functions/tables of functions never exist then it doesn't matter, and if you're statically linked then it doesn't matter either, but not calling them is not a reason to not include the note, quite the opposite.
Yeah. This is also what the default CRT file does, and if a given binary needs something else then it's supposed to invoke elfctl during its build. It's just a placeholder to make elfctl work (without having to pick apart and reassemble the ELF file, which can be rather fraught depending on the architecture). |
This issue is still saying |
I think we might have the info required. Presumably the format is similar to the other BSDs? |
@randall77 from what I've seen in src/cmd/link/internal/ld/elf.go, i would say: yes. but, and as I'm seeing in the NetBSD section: // NetBSD Signature (as per sys/exec_elf.h)
const (
ELF_NOTE_NETBSD_NAMESZ = 7
ELF_NOTE_NETBSD_DESCSZ = 4
ELF_NOTE_NETBSD_TAG = 1
ELF_NOTE_NETBSD_VERSION = 700000000 /* NetBSD 7.0 */
) i would "simply" pull which ever version you're currently compiling on. |
We try not to make the build dependent on the build machine. That way the behavior of cross-compilation and native compilation don't diverge. Especially for this case, when we're internally linking. |
From lib/csu/common/crtbrand.S:
For example, data from /bin/ls on my laptop:
(1300136 is the value from the FreeBSD 13 branch from whenever I built kernel/world on my laptop) There is a list of sys/sys/param.h has constants that the kernel/rtld compare against:
If we add this Let me see what this will change:
So, caller must be prepared to handle
From freebsd/freebsd-src@df08823
If we're not actually using the target's headers then this isn't what we want -- we must use the version corresponding to Go's definitions of kernel data-structures and expectation of kernel behaviour. While Go claims to support FreeBSD 10.x and later I think we should use 1004500. Before too long we should bump the minimum supported version, and when doing so make sure to check and if necessary update for newly-activated osrel behaviour. If we go to FreeBSD 11.x as a minimum The former relates to invalid combination of mmap(2) flags and shouldn't be of concern, while the latter means shutdown(2) will start returning ENOTCONN if the socket is not connected. |
Change https://go.dev/cl/412494 mentions this issue: |
|
Write .note signature section when targeting FreeBSD, similar to NetBSD and OpenBSD. This allows binaries to declare the ABI version they were compiled for and opt out of ASLR when compiled with -race. Fixes golang#48164 Change-Id: Ie54dd5c70697a3f42a75fd640540350fd8a4dc71
Write .note signature section when targeting FreeBSD, similar to NetBSD and OpenBSD. This allows binaries to declare the ABI version they were compiled for and opt out of ASLR when compiled with -race. Fixes golang#48164 Change-Id: Ie54dd5c70697a3f42a75fd640540350fd8a4dc71 Reviewed-on: https://go-review.googlesource.com/c/go/+/412494 Reviewed-by: Meng Zhuo <mzh@golangcn.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Yuval Pavel Zholkover <paulzhol@gmail.com>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes (this is the latest version)
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Compile a simple program on FreeBSD 13:
What did you expect to see?
What did you see instead?
Analogous headers for OpenBSD, NetBSD and Linux already exist.
Ours are declared here: https://github.com/freebsd/freebsd-src/blob/main/sys/sys/elf_common.h#L788-L792
The text was updated successfully, but these errors were encountered: