OpenBSD may soon gain further memory protections: immutable userland mappings
marc.info
marc.info
And "This security tech usually..." is a bit too modest. Just one example - OpenBSD is the origin of OpenSSH, which has been rather widely used for a decade or two now.
Since nobody uses protocol 1 anymore, very little of the original code from Tatu Ylönen remains in operation with default settings.
ps I have had to use the SSH commercial release under VMS, and the compatibilities with OpenSSH are quite unpleasant.
As I understand it, previous ROP-gadget hardening included compiler modifications on system/function call return, trap sleds, and some other stuff that I don't remember. This is on top of the kernel and library relink at every boot (to really make ASLR more potent).
These modifications include a verification that the jump is in the stack, and not at the tail of some function (and the other thing eludes my understanding).
These are some OpenBSD references on ROP hardening:
https://undeadly.org/cgi?action=article;sid=20170622065629
https://www.openbsd.org/papers/rop.pdf
https://www.openbsd.org/papers/asiabsdcon2019-rop-paper.pdf
I think that the most notorious exploit of "Return-Oriented Programming" (ROP-gadget) flaws was Solarwinds; I understand that a ROP exploit sealed their fate. Maybe Windows is doing some of this in their kernel.
"At this point, we noticed that Serv-U.dll and RhinoNET.dll both have ASLR support disabled, making them prime locations for ROP gadgets..."
https://www.microsoft.com/security/blog/2021/09/02/a-deep-di...
Am I happy to have ROP safeguards? You bet!
These mitigations don’t really harm anything so they’re not bad, per se, but they’re definitely not particularly impactful when to comes to security so nobody else really thinks it’s worth implementing them. There’s a lot of stuff like this in OpenBSD, but to be fair a lot of other projects are also bad at making mitigations that aren’t very useful. Reading writeups on CTFtime or, heaven forbid, imagining what exploits would look like is sadly too common.
Why are these projects that are used by many large and extraordinarily profitable tech enterprises dependent on community donations?
I recommend not donating, because to do so directly supports corporate parasitism.
If a corp wants a feature improved or implemented if it doesn't exist, they will have to pay someone and then they have to decide whether they will contribute it. If they do not, then they have to maintain a fork themselves which requires ongoing resources.
At the end of the day, I don't think it really matters that much. The corps are providing a service not a software application. If they weren't using BSD, they'd be using something else.
And thus the success of BSD-style licensing is thrown into sharp relief. (Also the fact that you or I can go use it as much as we want for free and do whatever we want to it.)
Those days appear to be over.
https://www.theregister.com/2015/07/08/microsoft_donates_to_...
MS : $25k - $50k
Google , FB : $10k - $25k
For them, that's like saying "Hi". For the financial value the OpenBSD foundation is creating, that's a miniscule return.
Still, I haven't heard any recent complaint on fundraising goals.
That said, this would be great to see in OpenBSD (or any other OS).
*the new mitigation just makes user-mode memory completely immutable. You can never "upgrade" a page's permissions or change its contents after it's been marked as immutable.
And using MAP_IMMUTABLE with MAP_ANONYMOUS wouldn't seemingly be possible. I would think mprotect() would work, though. Since the new call works more like minherit() under the hood, he decided to just duplicate that mechanism for this.
Currently your only option is to pull data directly from kernel structures, which is fine, but most people aren't doing that.
And then of course there's other cool stuff like being able to 'lock' system calls to the system provided libc, which openbsd can do since they already only support their provided libc.
Unfortunately none of this is likely to get to Linux at any point because:
a) I bet some insane userland processes fuck with their stacks
b) Linux doesn't mandate any libc
edit: Seems like there's some "what is this" being asked. Here's my loose understand!
For starters, libc is the interface to the kernel. Very few programs make syscalls directly (except go programs i guess? lol) on Linux, but on openbsd it's just flat out not allowed. OpenBSD doesn't have the "GNU/Linux" dichotomy - it's all one package deal. As such, they get to mandate how userland calls into the kernel.
Of course, you don't have to listen to openbsd today, because you can just... make those system calls directly. Easy. And this is relevant for security because attackers will do something called ROP, which effectively "reuses" bits of your already-executable code to issue system calls (you can google "return to libc" or "ret2libc").
So, first thing's first, have the kernel actually ensure that the sycall is issued from the memory that libc is mapped into. Cool, solved sort of.
But what if the attacker overwrites that libc? Now you've verified that the call is coming from libc but you don't have integrity.
With immutability the kernel will now enforce that system calls come from libc and that the code can't be overwritten.
Of course, this can extend beyond libc, but I'm assuming that's the main point. This would presumably be a general system call that programs can use themselves to do all sorts of fun things.
edit: Can't respond to replies, HN rate limited me :) sorry. Sounds like I need to read up a bit more, this doesn't address the use case I'd had in mind sadly, but still very cool nonetheless.
Neither does OpenBSD. You're misunderstanding how msyscall() works. It's like Highlander. There can be only one.
The new OpenBSD `mimmutable()` call, when applied on the stack, does absolutely nothing to prevent writing or reading the stack. It prevents changing the (virtual memory/pagetable) mapping itself, i.e. mapping in something else, removing the mapping, or changing the mapping attributes (primarily RWX).
Even if some userland process requires an executable stack, that would be indicated with ELF flags and set up by the loader - and then frozen in place.
…
Actually, now that I think about it, I guess you could try to put the boundary between main() and the magic bits right on a page boundary, and then change attrs on the magic bits?
Right, yeah.
> It would probably break the ANSI C standard though if you can't modify argv and environ though.
AFAIK it would also break setproctitle(), unless my memory is off that works by just writing over the argv space.
On the plus side, on Linux /proc/<pid>/environ is a snapshot created at the time of execve() and kept by the kernel, nothing other than execve() can change it (don't quote me on this, I'm only 90% sure.)
prctl(PR_SET_MM_ENV_{START,END}) will change the contents of /proc/<pid>/environ.
From what it looks like in Linux's source code, twiddling the bits at the base of the stack will also cause the procfs file to change--it seems to read directly from the process's memory. Ditto for /cmdline and /auxv, it seems.
… but Thanks for removing a misconception of mine!
You’ve just described why system call integrity is useless without strong CFI :)
What do you mean by "insane" here? In standard C you get char** argv, and the arguments live on the stack. I believe you are allowed to modify those cli arguments through the pointers, it is not undefined behavior.
You’re forgetting statically compiled binaries, which are very important for ease of deployment and distro-agnostic execution.
Amusingly the 80286 supported execute-only segments, but this was dropped from 32-bit x86.
[0] It is possible on Intel in VM guests using EPT (Extended Page Tables), mlarkin@ experimented with protecting the host kernel in a special VM, called "Underjack". AMD SVM supports nothing like this.
[1] The custom AMD APU SoC in Sony's PS5 console supports "xotext" via NDA'd extensions, but there's no public documentation. (If _anyone_ knows details, pls share)
... btw, PROT_WRITE-only mappings are also impossible on x86 as well, so PROT_WRITE implicitly means PROT_READ. Not that I'm aware of any valid reason anyone might want this.
I'll also add a [2]:
[2] There's no way to do it in the page tables. But, if you have Protection Keys for Userspace (PKU), you can get it ... kinda. You can have a PROT_READ|PROT_EXEC mapping, assign it a pkey, then set PKEY_DISABLE_ACCESS in the PKRU register for that key. In fact, if you have a PKU CPU and you do an unadorned mmap(PROT_EXEC), the kernel will allocate you a pkey and do this under the covers FOR you. Anyone who can execute WRPKRU can easily undo this protection, but it's better than nothing.
As far as I can tell Intel PKU was only on Server-CPUs/Xeons until at least the 11th Gen (only later models?), and AMD Zen 3.
OpenBSD doesn't support protection keys, in any case.