|
|
Subscribe / Log in / New account

OpenBSD system-call-origin verification

Benefits for LWN subscribers

The primary benefit from subscribing to LWN is helping to keep us publishing, but, beyond that, subscribers get immediate access to all site content and access to a number of extra site features. Please sign up today!

By Jake Edge
December 11, 2019

A new mechanism to help thwart return-oriented programming (ROP) and similar attacks has recently been added to the OpenBSD kernel. It will block system calls that are not made via the C library (libc) system-call wrappers. Instead of being able to string together some "gadgets" that make a system call directly, an attacker would need to be able to call the wrapper, which is normally at a randomized location.

Theo de Raadt introduced the feature in a late November posting to the OpenBSD tech mailing list. The idea is to restrict where system calls can come from to the parts of a process's address space where they are expected to come from. OpenBSD already disallows system calls (and any other code) executing from writable pages with its W^X implementation. Since OpenBSD is largely in control of its user-space applications, it can enforce restrictions that would be difficult to enact in a more loosely coupled system like Linux, however. Even so, the restrictions that have been implemented at this point are less strict than what De Raadt would like to see.

The eventual goal would be to disallow system calls from anywhere but the region mapped for libc, but the Go language port for OpenBSD currently makes system calls directly. That means the main program text segment needs to be in the list of memory regions where system calls are allowed to come from. Static binaries will also need to have their text segment included, since libc will inhabit part of that address space. In his message, he described the full list of allowed memory regions:

For static binaries, the valid regions are the base program's text segment and the signal trampoline page.

For dynamic binaries, valid regions are ld.so's text segment, the signal trampoline, and libc.so's text segment... AND the main program's text.

Switching Go to use the libc wrappers (as is already done on Solaris and macOS) is something that De Raadt would like to see. It may allow dropping the main program text segment from the list of valid regions in the future:

If go is adapted to call library-based system call stubs on OpenBSD as well, this problem will go away. There may be other environments creating raw system calls. I guess we'll need to find them as time goes by, and hope in time we can repair those also.

The kernel can mark most of the regions valid as it starts up a process, but it will not know what address space holds libc.so for a dynamic binary. Marking that region as valid is left to the ld.so dynamic linker. It has been changed to execute a new system call, msyscall(), to mark the region occupied by libc.so as one that is valid for making system calls. msyscall() can only be called once by a process, so changes or additions to the valid regions are not possible once ld.so has done so. Any process that makes a system call from a non-approved region will be killed.

Another OpenBSD security measure plays a role here as well. On boot, libc is re-linked in a random order, so that the locations of the system-call wrappers within libc are different for every running system. This change forces attackers to use those wrappers, which will be difficult to find reliably for a non-local attack.

Things move quickly in the OpenBSD world (as we saw with the kernel address-space randomized link (KARL) feature in 2017), so it was no surprise that the code for this new feature was committed to the OpenBSD tree just two days after it was first posted. It is an ABI break for the operating system, but that is no big deal for OpenBSD. De Raadt said: "we here at OpenBSD are the kings of ABI-instability". He suggested that relying on the OpenBSD ABI is fraught with peril:

Program to the API rather than the ABI. When we see benefits, we change the ABI more often than the API.

I have altered the ABI. Pray I do not alter it further.

This is an incremental security improvement; it is a hardening measure that makes it more difficult for attackers to reliably exploit a weakness that they find. There was no real dissent seen in the thread, so it would seem to be a relatively non-controversial change. But, once Go is changed and the main program text is not allowed to make system calls, that might change if there are other applications that need the raw system-call capability. For Linux, though, that kind of ABI change would never get very far.


Index entries for this article
SecurityHardening


(Log in to post comments)

OpenBSD system-call-origin verification

Posted Dec 11, 2019 16:51 UTC (Wed) by jhhaller (guest, #56103) [Link]

I believe Rust also has its own OS wrappers. Any compiled language which doesn't allow calling C functions would potentially have the same issue. Interpreted languages with their own system call implementation would also have the same issue. Statically linked applications (if libc is allowed to be statically linked) may have issues with this mechanism if the kernel expects to be able to randomly place libc wrappers and only accept system calls from that space.

OpenBSD system-call-origin verification

Posted Dec 11, 2019 17:22 UTC (Wed) by farnz (subscriber, #17727) [Link]

Looking at the Rust std library source, it appears that all of the important bits are implemented as wrappers around FFI to OpenBSD's libc, not as raw syscalls. So, at least for Rust, this should Just Work.

OpenBSD system-call-origin verification

Posted Dec 11, 2019 18:31 UTC (Wed) by jhhaller (guest, #56103) [Link]

I was thinking of https://gitlab.redox-os.org/redox-os/relibc with the sc crate, which also supports Linux in addition to Redox, but OpenBSD is not listed as a target. That eventually leads to https://docs.rs/sc/0.2.2/src/sc/platform/linux-x86_64/mod... which is a re-implementation of the system calls.

While I doubt there is an immediate replacement of libc based version, I wouldn't be surprised if this approach eventually gains momentum.

OpenBSD system-call-origin verification

Posted Dec 11, 2019 18:48 UTC (Wed) by ballombe (subscriber, #9523) [Link]

freepascal also has its own syscall library, iirc.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 8:35 UTC (Thu) by dvdeug (subscriber, #10998) [Link]

A compiled language wouldn't need to allow calling C functions to call C in the standard library.

And there's a non-toy compiled language implementation that doesn't allow calling C functions? I'm almost tempted to drop the "compiled" from that sentence; there are some interpreted language implementations that have a specific purpose that don't need to call native-code functions, but one of the most powerful thing any language implementation can do is permit calling native-code (C/Fortran) libraries that either (a) interact with hardware, (b) implement something complex and fiddly in tested code or (c) implement something super-fast in tested code.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 8:43 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

Programs in Go language are routinely linked completely statically, without any dependencies. In this mode they use syscalls directly.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 9:28 UTC (Thu) by mjg59 (subscriber, #23239) [Link]

Which is, unfortunately, not always entirely helpful: https://github.com/golang/go/issues/1435

OpenBSD system-call-origin verification

Posted Dec 12, 2019 10:25 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

Well, the design of setuid is kinda stupid. It should have been fixed properly in the kernel long time ago.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 11:47 UTC (Thu) by dvdeug (subscriber, #10998) [Link]

It works, though. POSIX promises a C API, not a kernel ABI or API, and the kernel changing the syscall breaks the kernel's ABI. Go can do the same thing libc does and abstract away the problem; it's always the job of high-level languages to smooth over the raw low-level details.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 22:39 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

It's trivially easy to implement the process-global setuid() in the kernel, instead of using racy signal-based implementation. Keeping around crap code like this simply adds to the technical debt and is stifling innovation (like Go is trying to do).

OpenBSD system-call-origin verification

Posted Dec 14, 2019 17:53 UTC (Sat) by luto (subscriber, #39314) [Link]

It’s not trivial. Looping over all threads is straightforward. Changing the uid of a running thread is not (that thread might be busy reading its own uid or, worse, changing its creds). Defining what happens if you run out of memory part way through is not trivial. Dealing with races against clone() is not trivial.

OpenBSD system-call-origin verification

Posted Dec 11, 2019 19:28 UTC (Wed) by josh (subscriber, #17465) [Link]

This seems like something Linux could *potentially* support, if not for the use of the VDSO. BPF could filter syscalls differently based on the syscall origin, and a program could harden itself by preventing syscalls from arbitrary locations. However, if all syscalls come from the VDSO then such hardening helps but doesn't address prevention of calls to the VDSO from arbitrary locations.

OpenBSD system-call-origin verification

Posted Dec 11, 2019 21:45 UTC (Wed) by mathstuf (subscriber, #69389) [Link]

It's not just that. Not all syscalls are in (g)libc anyways. https://people.redhat.com/dhowells/keyutils/ for one.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 4:57 UTC (Thu) by wahern (subscriber, #37304) [Link]

You should still be able to use the syscall(2) interface provided by libc. That's how C programs usually manually invoke system calls, rather than using inline assembly. It appears libkeyutils does exactly this: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/...

OpenBSD system-call-origin verification

Posted Dec 11, 2019 21:13 UTC (Wed) by mm7323 (subscriber, #87386) [Link]

I still think compilers should be modified to generate a special elf section that lists system call return addresses and the system call number. The kernel could then parse this into a lookup table to efficiently check all syscalls once the binary is running, and strongly resist compromised code.

Some smarts with dynamic library handing may enable a lookup table in the kernel per shared object and reduce memory overhead. But anything should be able to make a raw system call... iff that's how the code was compiled to run.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 8:38 UTC (Thu) by NYKevin (subscriber, #129325) [Link]

Unfortunately, I don't think there's much benefit to going that far (strict matching of individual wrappers and kernel syscalls) because any attacker who can execute arbitrary libc gadgets will just invoke syscall(2) with appropriate arguments (and you're not going to break that for compat reasons). Still, a less-strict "must be from libc" restriction would go a very long way.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 19:56 UTC (Thu) by mm7323 (subscriber, #87386) [Link]

Firstly syscall(2) use seems generally rare, especially since glibc added a gettid() wrapper :-)

Then I'd bet that in most calls to syscall(2) the first argument is a constant, or a propagated constant, and so the compiler could still generate the required ELF section entries to secure the call under such a scheme.

There will still be something out there using syscall() in imaginative ways that can't be determined at compile-time (fuzzers?) so a way to disable the check on a selective basis would still be needed, and that may allow a route to gradually deprecate syscall() for a big security boost.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 21:27 UTC (Thu) by nybble41 (subscriber, #55106) [Link]

You'd need to actually remove syscall(2) from libc to get much benefit from all this, and that would break compatibility with existing programs. As long as syscall(2) exists the kernel would only see that the system call came from the syscall(2) function in libc, which isn't enough to verify the origin of the system call number.

OpenBSD system-call-origin verification

Posted Dec 13, 2019 10:41 UTC (Fri) by mm7323 (subscriber, #87386) [Link]

I don't think you fully understood my comment above.

The first argument to syscall() is the system call number, which I surmise can commonly be determined by the compiler. For example, else where in the comments the following code is cited: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/...

The syscall() use in the above code passes constant syscall numbers from <sys/syscall.h> such as __NR_add_key. Using a gcc builtin we can check that the compiler recognises these values as a constant too and at least with gcc 8.3.1:

__builtin_constant_p(__NR_add_key) === 1

Therefore it should be possible to get at least GCC to generate a section with the true system call number and return address, at least in this common use pattern of syscall().

OpenBSD system-call-origin verification

Posted Dec 14, 2019 1:14 UTC (Sat) by nybble41 (subscriber, #55106) [Link]

No, I understood that. I just don't see what it accomplishes. In particular, you can't trust that syscall()'s return address bears any relationship to the origin of the system call number or other arguments. One relatively innocuous case is tail-call optimization: a() calls b() which calls syscall(), but the return address is in a(), not b(). Or syscall(), or something tail-calling syscall(), could be invoked through a function pointer such that the return address is not knowable at compile-time. Of course, a malicious actor could arrange for any return address they wish, including a perfectly legitimate call with the right system call number, and most likely also arrange to have that function return to their own code later on.

OpenBSD system-call-origin verification

Posted Dec 15, 2019 7:29 UTC (Sun) by mm7323 (subscriber, #87386) [Link]

So you've switched argument now, but that's still not a problem.

Tail-call optimisation is done by the compiler, so given I'm suggesting the compiler itself can generate the syscall number and return addresses, it should still be possible to get this right. At worst tail-call optimisation could be disabled if the return address (or set of return addresses) cannot be determined.

All such a scheme does is to implement Control Flow Integrity (CFI) at the system call level, and prevent a process from making new or different system calls from the time it was compiled, akin to pledge(), but automatic, complete, and dealing with libraries.

Anyway, someone else posted a link to some research which is essentially this, but parsing binaries rather than modifying the compiler stage. It goes far further than I could explain in comments, please take a look if you are interested:

https://lwn.net/Articles/807246/

OpenBSD system-call-origin verification

Posted Dec 16, 2019 16:20 UTC (Mon) by nybble41 (subscriber, #55106) [Link]

> So you've switched argument now ...

No, the argument is exactly the same. Only your understanding of it has changed.

> Tail-call optimisation is done by the compiler, so given I'm suggesting the compiler itself can generate the syscall number and return addresses, it should still be possible to get this right.

For the trivial cases yes, you could special-case calls to syscall() in the compiler and avoid tail-call optimization for these cases. That won't help with indirect calls, of course, unless you disable TCO globally. And the program could always define an alias for syscall() which the compiler won't recognize. But that isn't the real problem. The real problem is that malicious code can simulate a call to syscall() from the _expected_ return address. All it has to do is put the right return address on the stack or in the link register before branching to syscall(), a standard requirement for any ROP attack.

If all you want is an automatic equivalent of pledge() then simply recording the system call numbers, without return addresses, would make much more sense. The kernel can't enforce anything about the return address anyway, since that is easily controlled by malicious code. There would need to be a way to override it, since some programs (mainly interpreters, e.g. the syscall function in Perl) need to be able to make arbitrary system calls depending on the inputs. Though having any program that links with libc enable all system calls invoked by any function available in libc wouldn't restrict the execution environment very much. To really be effective you'd need to attach the system call numbers to specific library entry points, or link statically and get the syscalls from the individual object files within the archive.

> Anyway, someone else posted a link to some research which is essentially this, but parsing binaries rather than modifying the compiler stage.

That could work since the entire program is available, and presumably their binary parser can simply reject any program for which it can't determine the syscall bounds. However, it's incompatible with dynamic linking where the whole program isn't known until it's actually executed, and possibly not even then if the program uses dlopen() to load plugins.

OpenBSD system-call-origin verification

Posted Dec 16, 2019 20:22 UTC (Mon) by mm7323 (subscriber, #87386) [Link]

I really suggest you go and read the research papers - they written by people far clever than me and answer a lot of your questions.

Say goodbye to exec

Posted Dec 12, 2019 0:46 UTC (Thu) by jreiser (subscriber, #11027) [Link]

According to the description, this has changed the API (Application Programming Interface) for the shell. exec of a compiled binary program no longer works, because with randomized layout of shared libraries then the target's instantiation of libc is nearly always at a different address than the shell's libc.

Say goodbye to exec

Posted Dec 12, 2019 2:21 UTC (Thu) by mathstuf (subscriber, #69389) [Link]

Does it clear the state on fork then? Why not exec instead? Something has to clear the "set libc in stone" bit otherwise pid1 would have trouble making a new process too (a shell calling exec is no different than Python doing so from the kernel POV…I hope). Or are there exceptions for that kind of stuff?

OpenBSD system-call-origin verification

Posted Dec 12, 2019 18:58 UTC (Thu) by rweikusat2 (subscriber, #117920) [Link]

Better idea for a title: OpenBSD outlaws assembly programming.

OpenBSD system-call-origin verification

Posted Dec 12, 2019 22:32 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

??

You can call libc from assembly just fine.

OpenBSD system-call-origin verification

Posted Dec 13, 2019 16:21 UTC (Fri) by rweikusat2 (subscriber, #117920) [Link]

Sure. And you can also ride a bike with a sofa in tow.

The underlying message is nevertheless: From now on, it's strengstens verboten to call into the OpenBSD kernel from machine code. This is a necessary security measure because only criminals would do that, anyway.

NB: This is *not* a statement in favour of the great usefulness of machine code programming. But that's a hobby of some people who enjoy building stuff, as opposed to "make money by coming up with ever more abstruse ways of tearing it down".

OpenBSD system-call-origin verification

Posted Dec 13, 2019 18:26 UTC (Fri) by atai (subscriber, #10977) [Link]

riding a bike with a sofa in tow.

That can be a sport with regular races. Seriously.

OpenBSD system-call-origin verification

Posted Dec 13, 2019 18:28 UTC (Fri) by atai (subscriber, #10977) [Link]

OpenBSD system-call-origin verification

Posted Dec 13, 2019 18:32 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

> The underlying message is nevertheless: From now on, it's strengstens verboten to call into the OpenBSD kernel from machine code.
Dude, you have some really strange concepts of pretty much everything CS-related.

The overhead of libc functions is pretty much negligible, since you're doing syscalls.

OpenBSD system-call-origin verification

Posted Dec 13, 2019 19:42 UTC (Fri) by rweikusat2 (subscriber, #117920) [Link]

The reply text doesn't really match the quoted text ;-).

I wasn't referring to the additional runtime cost of invoking the system call through a C wrapper, although that's not necessary negligible and someone writing machine code would very likely care about it nevertheless, but about the "infrastructure overhead" of having to link with this library (including the size of the thing) and the absurdity of writing code following the C calling conventions of a particularly system so that one can interface with (compiled) C code supposed to enable other C code to use an interface defined in machine code.

For a loosely related example, people implement alternative C libraries for Linux solely because they're horrified by "glibc bloat". That's not much of a real practical concern, either, because today's "embedded systems" vastly more powerful than "high-end UNIX workstations of the mid-1990s", but some people do care about it very much nevertheless.

OpenBSD system-call-origin verification

Posted Dec 19, 2019 6:31 UTC (Thu) by marcH (subscriber, #57642) [Link]

> people implement alternative C libraries for Linux solely because they're horrified by "glibc bloat"
> That's not much of a real practical concern, either, because today's "embedded systems" vastly more powerful than "high-end UNIX workstations of the mid-1990s", but some people do care about it very much nevertheless.

Yes of course: some hobbyists have fun implementing libraries with insanely small footprints, only to be used in systems several orders of magnitude bigger. It's like a sport.

You should actually look at some of these libraries and corresponding operating systems, they tend to give examples of the sort of real hardware they target.

OpenBSD system-call-origin verification

Posted Dec 19, 2019 10:29 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

To be fair, musl libc is a full-blown replacement for glibc. And it's better in many regards.

OpenBSD system-call-origin verification

Posted Dec 19, 2019 15:46 UTC (Thu) by mathstuf (subscriber, #69389) [Link]

Eh, without NSS or PAM, some of my use cases aren't supported. I already had to drop a Go program because it wouldn't use the `mymachines` NSS plugin from `systemd-machined` to be able to get hostnames of sibling containers.

OpenBSD system-call-origin verification

Posted Dec 19, 2019 20:15 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link]

Well, would be nice to drop NSS libraries entirely.

OpenBSD system-call-origin verification

Posted Dec 20, 2019 17:06 UTC (Fri) by cortana (subscriber, #24596) [Link]

Somehow I get the feeling that many who dislike NSS won't be happy to replace it with systemd-resolved... ;)

OpenBSD system-call-origin verification

Posted Dec 20, 2019 20:31 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

It should be replaced by a simple local daemon with a simple well-defined protocol. Libraries that are loaded behind your back into the running process are just a bad idea.

OpenBSD system-call-origin verification

Posted Dec 21, 2019 13:26 UTC (Sat) by cortana (subscriber, #24596) [Link]

resolved for all then! :)

OpenBSD system-call-origin verification

Posted Dec 21, 2019 16:44 UTC (Sat) by dezgeg (subscriber, #92243) [Link]

Using nscd in non-caching configuration is already practical and done in NixOS for everything except the built-in NSS modules. IIRC not everything in NSS is supported via nscd though, but fixing nscd to have 100% feature parity should be much easier than reinventing anything new.

OpenBSD system-call-origin verification

Posted Dec 24, 2019 1:01 UTC (Tue) by mathstuf (subscriber, #69389) [Link]

This kind of approach is certainly the best, but until then, those of us who need NSS-provided functionality are stuck on glibc.

OpenBSD system-call-origin verification

Posted Dec 24, 2019 12:31 UTC (Tue) by cortana (subscriber, #24596) [Link]

I believe nscd doesn't play well with sssd (though I haven't bothered to investigate why, perhaps it's just that it's unnecessary since sssd does it's own caching anyway).

And that NSS will tell you a host's addresses but not which interface they are reachable via, or whether the query was secured by DNSSEC, dns-over-tls, etc, which resolved does provide via its D-BUS API.

(As well as being able to do nifty things like LLMNR, or split-DNS. OTOH resolved does have its own bugs and limitations that drive me up the wall a bit...)

OpenBSD system-call-origin verification

Posted Jan 8, 2020 11:20 UTC (Wed) by nix (subscriber, #2304) [Link]

AIUI this is upstream glibc's longer-term goal too -- however, it will still look like NSS from the viewpoint of both NSS modules themselves and existing users. Quite what to do is still up in the air, but it's likely that we'll end up with something like an always-on, possibly autospawned nscd which aggressively loads all modules names in nsswitch.conf at startup and on nsswitch.conf change.

This isn't to avoid libraries getting loaded behind your back into a running process so much as it is to allow removal of the incredibly convoluted and invasive statically-linked dlopen() feature, which is only really there so that statically linked programs can do name lookups. (But moving all the NSS stuff out of every process's address space into one more controllable domain is definitely a side benefit!)

(I am only an egg, but this is my understanding, anyway. My apologies if I'm mischaracterizing anything or accidentally mixing it up with my own ideas of obviously right implementations etc: human memory is a fallible thing...)

OpenBSD system-call-origin verification

Posted Jan 9, 2020 1:34 UTC (Thu) by anselm (subscriber, #2796) [Link]

Probably not, given that the uses of NSS and those of systemd-resolved only overlap slightly.

OpenBSD system-call-origin verification

Posted Dec 14, 2019 8:50 UTC (Sat) by dvdeug (subscriber, #10998) [Link]

Who cares? If you have a problem with this, there's Minix, Illumos, Linux, FreeBSD and NetBSD kernels, plus older versions of OpenBSD or versions of OpenBSD with this feature patched out. You're complaining that a niche demand (not your actual problem, but someone else's) is not being supported by a somewhat niche operating system that is following its own explicitly stated, somewhat niche, goals that conflict in this instance, when people have any number of alternatives to OpenBSD.

A hobby of many people is low-level computer hacking, wherein any Unix-type system is going to get in the way with all this "filesystem" and "virtual memory" crap. Guess what they do? They use a system that supports their needs.

OpenBSD system-call-origin verification

Posted Dec 16, 2019 20:12 UTC (Mon) by rweikusat2 (subscriber, #117920) [Link]

I'm not "complaining" about anything, I'm just pointing out that the "eternal OpenBSD quest" of "hopefully increase resilience against bugs we cannot fix by making the system more complicated to program" has meanwhile crossed the boundary of "your programming language of choice must not be one we disapprove of".

OpenBSD system-call-origin verification

Posted Dec 17, 2019 5:44 UTC (Tue) by dvdeug (subscriber, #10998) [Link]

And we're pointing, in part, that that's false. You can still engage in assembly language programming; you just have to call libc instead of directly making system calls. With a suitable assembler or binary patcher to replace direct syscalls with libc calls, you could get around even that problem.

Most code ever written won't compile or run on modern Unix systems, short of emulation, and the dialects they're written in fundamentally won't work well on Unix. You can't really use certain Forth dialects, as they implement hard drives as an array of sectors that the program has arbitrary access to. MS-DOS C dialects assume segmented pointers. VMS C has its own system calls that makes porting any non-trivial program challenging. Same thing with Windows C. Many BASICs assume you can PEEK and POKE certain memory locations for certain effects. You can't run most assembly languages or machine language; 68000 assembly written for OpenBSD won't run on any modern version, and never ran on any non-68K OpenBSD. You can run any language or program on any sufficiently large system with enough layers of indirection, but virtually all non-trivial code not written for Unix systems is going to make enough assumptions about how things work that Unix disagrees with to require serious emulation or virtualization to work without code changes.

The boundary of "your programming language of choice must not be one we disapprove of" was first willfully crossed when memory protection and filesystems were added.

And you say you're not "complaining", but you've chosen to characterize the "eternal OpenBSD quest" in a biased way that sounds a lot like a complaint; the goal is to "increase resilience against bugs", by many tactics, not just those which some rare programmers might find complicating things.

OpenBSD system-call-origin verification

Posted Jan 8, 2020 17:36 UTC (Wed) by marcH (subscriber, #57642) [Link]

According to de Raadt, OpenBSD is a "research operating system for developing security mitigations". Not exactly something anyone is forced to use.

Other systems often get these mitigations "for free" once OpenBSD paid the initial development price for them.

I really can't see anything to be unhappy about.

OpenBSD system-call-origin verification

Posted Dec 14, 2019 20:59 UTC (Sat) by flussence (subscriber, #85566) [Link]

Programs that only work on one vendor's CPU should be outlawed anyway.

OpenBSD system-call-origin verification

Posted Dec 13, 2019 11:11 UTC (Fri) by mneug (guest, #135662) [Link]

There's academic research that prototyped a similar approach [1], with the system call origin restriction being that system calls can only be invoked if there's a corresponding instruction in the binary on disk. It also enforces other properties relevant to system calls if they can be derived from the code, such as the system call number or constant arguments.
That would also work for statically linked binaries.

[1] https://www.mulliner.org/security/projects/bintegrity/

OpenBSD system-call-origin verification

Posted Dec 18, 2019 1:42 UTC (Wed) by vomlehn (guest, #45588) [Link]

This seems to assume that all system calls are implemented in your C library. In the real world, the C library generally lags behind the implementation in the kernel. It seems that rolling your own support for a new system call would break this approach.

OpenBSD system-call-origin verification

Posted Dec 18, 2019 2:08 UTC (Wed) by pizza (subscriber, #46) [Link]

In OpenBSD, the C library and kernel are developed in lock-step, tightly coupled to each other in the same source tree, so there is little point in rolling one's own OpenBSD-specific syscall wrappers.

OpenBSD system-call-origin verification

Posted Dec 19, 2019 10:17 UTC (Thu) by topimiettinen (guest, #133428) [Link]

Disallowing system calls originating from writable pages seems useful. This could be implemented with seccomp as the instruction pointer is already available to the BPF, so kernel only needs to allow calling a function to check the page of the IP for various properties from seccomp BPF.

Also alignment of the return address could be checked. Random ROP gadgets for system calls might be found at various non-aligned locations, but if compilers could be instructed to align the system call location strictly, even at specific offset to page boundary, it would decrease the chances of finding a gadget by 1/alignment (1/PAGE_SIZE for fixed page offset version). The check itself would be doable today in BPF and it would be very easy to add this to for example systemd or Firejail as a new sandboxing option.


Copyright © 2019, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds