[HN Gopher] OpenBSD may soon gain further memory protections: im...
___________________________________________________________________
OpenBSD may soon gain further memory protections: immutable
userland mappings
Author : fcambus
Score : 153 points
Date : 2022-09-02 15:06 UTC (7 hours ago)
(HTM) web link (marc.info)
(TXT) w3m dump (marc.info)
| roopy wrote:
| What exploit technique is this mitigating?
| saagarjha wrote:
| That's always a good question to ask :) Seems like the claim is
| that it prevents exploits where you'd map libc executable and
| then spray code there. IMO if you have the ability to do this
| you usually have lost already but -\\_(tsu)_/-
| dang wrote:
| Url changed from
| https://undeadly.org/cgi?action=article;sid=20220902100648, which
| points to this.
| [deleted]
| rwmj wrote:
| I'm curious why Theo used a new syscall. Wouldn't it be
| sufficient to add a new MAP_IMMUTABLE flag to mmap which would
| "fix" the given range of pages' mappings and protections
| permanently? Can't call it MAP_FIXED sadly :-)
| akira2501 wrote:
| mmap explicitly is allowed to create new maps in place of
| existing mappings by just freeing the underlying mapping, in
| fact that's one use for MAP_FIXED in safely create circularly
| mapped buffers.
|
| 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.
| teknopurge wrote:
| I'm not adding insight to this thread, but I love the OpenBSD
| project. Theo and the team are goat engineers and industry
| advocates.
| jart wrote:
| Now all we need is for PROT_EXEC to not imply PROT_READ like
| Android.
| crest wrote:
| Why do you expect removing PROT_READ to provide a security gain
| when running open source software compiled using reproducible
| builds? Just the offset into an executable memory mapping is
| enough to know the executable code to be found. Sure it's a bit
| annoying, but it wouldn't prevent attackers from using it as
| ROP gadget.
| brynet wrote:
| There was some work done on XOM (eXecute-only-memory) for
| arm64, but on at least x86 there isn't a separate page table
| bit for just read permissions, so there's no way[0][1] to
| express R^X, PROT_EXEC without PROT_READ is not possible.
|
| 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.
| hansendc wrote:
| > there's no way[0][1] to express R^X, PROT_EXEC without
| PROT_READ is not possible.
|
| 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.
| brynet wrote:
| _kinda_ indeed.
|
| 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.
| saagarjha wrote:
| This breaks PAN on ARM due to various unfortunate choices in
| the spec.
| staticassertion wrote:
| I was just discussing this sort of thing with some colleagues.
| Because the stack frame for main contains a bunch of other stuff
| - environment variables, cli args, etc - it makes it unreliable
| to try to instrument Linux systems and collect that information.
| A process can change its name, args, env, at any time. That sort
| of information is really helpful for forensics.
|
| 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.
| eqvinox wrote:
| > Because the stack frame for main contains a bunch of other
| stuff - environment variables, cli args, etc - [...] > a) I bet
| some insane userland processes fuck with their stacks
|
| 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.
| jart wrote:
| Well it technically does if you make a new stack with
| mmap(MAP_STACK) (or simply round down the stack pointer by a
| page size) and remove the write access to the top of the
| original stack and mimmutable it.
| eqvinox wrote:
| Problem is that those "magic variables" are defined by ABI
| to be directly above main()'s stack frame... if you're
| throwing that out, you may equally well leave the stack
| alone and put the magic stuff in some new 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?
| jart wrote:
| You mean _start()'s stack pointer. Libc can secure them
| and it's fine. It would probably break the ANSI C
| standard though if you can't modify argv and environ
| though. So Libc would need to copy them. But that limits
| the usefulness of the original tooling proposal unless
| the operating system has something like /proc/pid/maps
| that tells you the extent of the system provided stack. I
| don't think OpenBSD has that. Please prove me wrong since
| if it does, I'd love to know how.
| eqvinox wrote:
| > You mean _start()'s stack pointer.
|
| 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.)
| 7vUYjPAG2fnx7fd wrote:
| No setproctitle on Linux. As far as I know you have to
| overwrite the argv space (and hopefully not also the
| environment space).
| jcranmer wrote:
| > 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.
| leni536 wrote:
| > a) I bet some insane userland processes fuck with their
| stacks
|
| 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.
| saagarjha wrote:
| > 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").
|
| You've just described why system call integrity is useless
| without strong CFI :)
| 10000truths wrote:
| > Very few programs make syscalls directly (except go programs
| i guess? lol) on Linux
|
| You're forgetting statically compiled binaries, which are very
| important for ease of deployment and distro-agnostic execution.
| jart wrote:
| > Linux doesn't mandate any libc
|
| Neither does OpenBSD. You're misunderstanding how msyscall()
| works. It's like Highlander. There can be only one.
| staticassertion wrote:
| Ah, interesting, I'll have to dig into it more :) I've never
| used OpenBSD so I've just had to watch on the sidelines.
| Anywhere I can read more about this?
| jart wrote:
| The msyscall() man page. The Cosmopolitan Libc source code.
| In the cosmoverse, we produce static executables that run
| on six operating systems. The only Libc we use is obviously
| our own. So when our executables get loaded on OpenBSD, we
| do the same thing OpenBSD Libc does, which is calling
| msyscall() so that only a privileged subset of the
| application is able to use SYSCALL. In our static binary
| world, that's basically any function that uses the
| `privileged` keyword. It makes things a little dicey if we
| want to dynamically link OpenBSD Libc since we have to pull
| out some aggressive hacks like Xed in that case. But
| overall it's fine.
| kyledrake wrote:
| This security tech usually ends up in other platforms too,
| strongly recommend donating to their work:
| https://www.openbsdfoundation.org/donations.html
| bell-cot wrote:
| +1...but OpenBSD's webmaster might want to update that page, so
| it doesn't link to their 2020 Fundraising Campaign. (Their
| current Campaign -
| https://www.openbsdfoundation.org/campaign2022.html )
|
| 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.
| fsckboy wrote:
| OpenBSD does great work, but for the record _OpenSSH started
| as a fork of the free SSH program developed by Tatu Ylonen;
| later versions of Ylonen 's SSH were proprietary software
| offered by SSH Communications Security._
|
| https://en.wikipedia.org/wiki/OpenSSH
| chasil wrote:
| Realistically, OpenBSD completely reimplemented protocol 2
| themselves.
|
| Since nobody uses protocol 1 anymore, very little of the
| original code from Tatu Ylonen 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.
| gigantaure wrote:
| i just read that page[1] earlier this week. this gives a
| great view on the amount of work performed by the openssh
| project after the fork of the last open source version.
|
| [1] https://www.openssh.com/history.html
| saagarjha wrote:
| This happens to already exist on macOS as VM_FLAGS_PERMANENT
| when setting up the mapping.
| hggh wrote:
| Too bad they don't accept peer-to-peer electronic cash
| 7vUYjPAG2fnx7fd wrote:
| > Bitcoin donation via BitPay: The OpenBSD Foundation can
| accept donations in BTC via BitPay
| hansendc wrote:
| There honestly isn't that much "tech" to speak of here. We were
| literally talking about "immutable" mappings last week in Linux
| land:
| https://lore.kernel.org/all/b4f0dca5-1d15-67f7-4600-9a0a91e9...
|
| That said, this would be great to see in OpenBSD (or any other
| OS).
| chasil wrote:
| The ROP-gadget stuff hasn't migrated to any other kernels that
| I have seen.
|
| 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...
| saagarjha wrote:
| This is because the ROP gadget hardening OpenBSD does is
| generally considered to be mostly useless by other kernels,
| which are moving to hardware-enforced control flow integrity
| instead.
| beachhead wrote:
| Is the ROP gadget hardening OpenBSD does mostly useless
| tho? Can you elaborate?
| Veliladon wrote:
| ARM for instance has pointer authentication built into
| its hardware since version 8.3 of the ISA. While it's not
| the same implementation as OpenBSD, it has the same
| practical effect of making sure the return address is
| valid.
| beachhead wrote:
| Right. So, how does that render OpenBSD's useless? Maybe
| I'm not being clear about what I'm asking here. I'm not
| comparing software vs hardware CFI. OpenBSD doesn't have
| support for PAC or CET (That I know of) but that doesn't
| mean they won't in the future. Should there be no
| software CFI then? Perhaps they would eventually
| complement each other?
| chasil wrote:
| I prefer to do all my financial transactions from Chromium
| on OpenBSD, on a machine where I have run me_cleaner.
|
| Am I happy to have ROP safeguards? You bet!
| na85 wrote:
| And thus the failure of BSD-style licensing is thrown into
| sharp relief:
|
| 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.
| Sunspark wrote:
| The flip side of course is that improvements also come at the
| pace of volunteerism, and there are no boardroom meetings
| where a manager tells the BSD developers that they didn't
| type enough lines of code that week.
|
| 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.
| [deleted]
| chasil wrote:
| There used to be complaint from OpenBSD that large corporate
| users of OpenSSH weren't donating anything, so I sent them
| $100.
|
| Those days appear to be over.
|
| https://www.theregister.com/2015/07/08/microsoft_donates_to_.
| ..
| iE4mHBzmoYezwbx wrote:
| Really? Their biggest donors are large and extraordinarily
| profitable tech enterprises. (Like Google, Microsoft, and
| Facebook)
|
| 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.)
| alberth wrote:
| This is beyond my knowledge but is this akin to macOS
| binary/memory protection for the base system OS?
| landr0id wrote:
| Different. These are enhanced mitigations to detect when a
| program is calling into the kernel from a weird state that
| should never happen in a well-formed program. It basically
| prevents certain types of exploits from successfully calling
| into the kernel.
|
| *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.
| geraldcombs wrote:
| As a more general question, is there a resource available that
| shows which memory protection schemes are available on various
| OSes? It'd be nice to see what the state of the art is on
| Linux, macOS, the BSDs, etc. in one place.
| pram wrote:
| Seems like the second blurb is similar to the Page Protection
| Layer+Pointer Authentication Codes in XNU.
| saagarjha wrote:
| Not really, PPL protects page tables and PAC provides CFI.
___________________________________________________________________
(page generated 2022-09-02 23:01 UTC)