(I noticed this because OpenBSD keeps adding ELF related
*_OPENBSD_* flags/types to llvm-* tools.)
I don’t have any insight or use OpenBSD, but want to check how others think about the feature. Some links:
lib/libc/sys/mimmutable.2 says “mmap(2), mprotect(2), and munmap(2) to pages marked immutable will return with error EPERM”. It’s likely incompatible with dlclose. This model is likely incompatible with Android Zygote.
My understanding of the currently implemented things on OpenBSD:
There is an update from Theo which explains the whole design and its benefits in great detail: https://marc.info/?l=openbsd-tech&m=166874067828564&w=2
Implementing this sort of thing on Linux might prove difficult in practice if someone ends up wanting to do that in the future, since glibc uses mmap in malloc for large allocations (https://www.gnu.org/software/libc/manual/html_node/The-GNU-Allocator.html)
On a system like OpenBSD where libc and the kernel live in the same project, it’s a neat sounding feature!
It doesn’t make all mmap regions immutable, only specified ones. The heap would, obviously, not set this flag. It also shouldn’t be incompatible with dlclose if dll pen doesn’t set these flags, only normal library mappings do, but I’d be quite happy if they killed dlclose: there’s no real need for it on 64-bit systems, the security cost significantly outweighs the small reduction in address-space consumption.
Personally, I wish they would step back and stop adding hacks on top of mmap. The API is seriously flawed because it conflates a load of things: allocating virtual address space, permissions on that address space, and backing store. It does all of these things with no permission model. OpenBSD would be in a good position to design and ship a deconflation of these. Brooks Davis proposed a ‘cookie mmap’ a few years ago that started this, where the call to allocate address space returned a capability that then gave you the rights to change the mapping, you could only do mprotect or MAP_FIXED-like things if you had that capability. Once you have such a model, it becomes quite easy to add a richer set of permissions, including dropping the right to subsequently modify the mapping.
FWIW there’s one edge case, where you have an application that repeatedly creates and loads and unloads different .so files with dlsym, in which dlclose() not doing the thing would lead to a resource leak.
In practice though, just for stability alone, I’d recommend never doing that and spawning subprocesses to do the linking in of dynamically generated .so files instead.
You might still have bugs if you’re repeatedly opening and closing things. If your library calls any function in a global constructor that trigger thread-local objects with non-trivial destructors to be accessed, then your library will either be locked in memory, or you’ll leak things. Library unloading is difficult to do reliably and needs language support to do well, the way that it was shoehorned into POSIX is a mess.
https://isopenbsdsecu.re/mitigations/map_stack/ now describes mimmutable.