5 ms·
The description says to program to the API instead of the ABI. I'm not very familiar with low level work and exploits, but aren't syscalls the API for the kerne
by Reelin 7y ago
The description says to program to the API instead of the ABI. I'm not very familiar with low level work and exploits, but aren't syscalls the API for the kernel itself?
As far as I'm able to understand, it seems like the proposed mitigation blocks access to the kernel unless your code is either preauthorized (msyscall) or goes through a layer of indirection (libc) that undergoes randomized re-linking at boot. That seems to make sense to me, since it significantly reduces an adversary's knowledge about internals they are presumably targeting.
A few questions:
* Is it possible to authorize arbitrary code, or is access to msyscall (via libc or otherwise) restricted outside of boot?
* It seems that the kernel itself also undergoes randomized re-linking at boot (https://www.openbsd.org/innovations.html https://www.openbsd.org/innovations.html). So what does forcing everything through libc gain us?
* Is equivalent hardening likely to make it to the Linux world in the foreseeable future?
* What sort of attacks is this likely to prevent in practice?
* What have I misunderstood, and would someone mind explaining?
- mike_hock 7y agosyscall numbers are constant (part of the ABI!) regardless of the kernel's address space layout. Conversely, addresses of libc functions or any other code in the program are randomized at load time, so are unpredictable to an attacker.
- saagarjha 7y agoDoes OpenBSD stabilize the system call API?
- justincormack 7y agoNot like Linux, it is stable for a few releases but not forever in the BSDs, for openbsd I think its fairly short.
- Reelin 7y agoI don't usually think of integer constants passed as an argument to a function as an ABI, but given that they're hard coded at kernel compile time, fair enough. What I'm struggling to understand is why an additional layer of indirection is required to facilitate randomization in this case. It seems I must have a fundamental misunderstanding of how some part of the system works at this low level. I'm also wondering what (if anything) is being lost to this mitigation - the syscall(2) manpage (http://man7.org/linux/man-pages/man2/syscall.2.html http://man7.org/linux/man-pages/man2/syscall.2.html) seems to imply that not all system calls necessarily have matching wrapper functions in the platform's C library.
- ben_bai 7y agoYou are referencing a Linux manpage. But if it's also true for OpenBSD those syscalls will get deleted or a libc wrapper will be introduced.
- clarry 7y ago> What I'm struggling to understand is why an additional layer of indirection is required to facilitate randomization in this case. You can't randomize the integer constants without rebuilding the kernel and everything that depends on those constants. It would be very inconvenient, and the amount of randomization would likely be limited by the number of syscalls (because you want to pack them tight in a lookup table instead of having sparse numbers that are expensive to look up). If the number of syscalls is known, randomization can at best make you call the wrong one. By contrast, address randomization means the program will probably crash (instead of executing some random syscall) unless it can figure out the address of the function it wants. Randomizing addresses can be done on the fly in the runtime linker, without rebuilding binaries. Additional randomness can be introduced by relinking binaries with a randomizing linker, which is much simpler than running a full build. > I'm also wondering what (if anything) is being lost to this mitigation - the syscall(2) manpage (http://man7.org/linux/man-pages/man2/syscall.2.html http://man7.org/linux/man-pages/man2/syscall.2.html) seems to imply that not all system calls necessarily have matching wrapper functions in the platform's C library. syscall(2) lives in libc.
- Reelin 7y agoAfter a bit more reading, it seems I hadn't realized just how low level direct system calls actually are (https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_...). Apparently it's either a software interrupt or dedicated instruction, with the constant in a register. ASLR requires more abstraction than that (obviously), and there's no point to it if an exploit can just use the front door instead.
- mike_hock 7y agoI don't know where you draw your lines, but a syscall (on Linux and amd64, but it should work pretty much the same on BSD and other architectures) looks like mov rax, <syscall number> ; Depending on the syscall, it expects its parameters ; in various other registers syscall ; this is an actual instruction So yes, it is very much part of the ABI. It selects which function to call. The extra indirection, AFAIK, is needed because you couldn't just call a kernel function from userspace and have it run with kernel privileges. That's what the syscall instruction is for, to put the processor back in ring 0 so the syscall handler runs in kernel space. As for what's lost, well, for example, a sane language-agnostic kernel ABI is lost to a C-centric libc API. I don't know if the syscall wrapper support in libc is as incomplete on BSD as it is on Linux, but they could add the missing wrappers, of course. A cleaner approach might have been to have a separate libsyscall that only wraps syscalls and is mapped into the "blessed" address space that is allowed to issue syscalls. But then libc would have to wrap the wrappers, and they probably didn't want that extra indirection.
- saagarjha 7y ago> Is it possible to authorize arbitrary code, or is access to msyscall (via libc or otherwise) restricted outside of boot? It looks like there are restrictions if the binary is statically-linked, but I didn’t see anything else. You could probably pledge out of it. > It seems that the kernel itself also undergoes randomized re-linking at boot (https://www.openbsd.org/innovations.html https://www.openbsd.org/innovations.html). So what does forcing everything through libc gain us? This doesn’t protect against attacks on the kernel (which randomizing the kernel object files protects against); exploits at this stage are trying to spawn a shell (or similar) in userspace. Going through libc means you need to 1. find it and 2. pass whatever checks it has in place to get it to make the syscall. > Is equivalent hardening likely to make it to the Linux world in the foreseeable future? Parts of it, maybe. But turning this on by default would break applications. > What sort of attacks is this likely to prevent in practice? JIT code that has maliciously crafted to call execve(“/bin/sh”, …)
- notaplumber 7y ago> I'm not very familiar with low level work and exploits, but aren't syscalls the API for the kernel itself? No. The kernel doesn't call syscalls itself. It provides them for applications. Just to clarify a potential misunderstanding. The kernel and userspace run at different "hardware" privilege levels (ring0<=>ring3). Userspace applications cannot simply call the kernel API directly, they must "trap" into the kernel to perform some pre-defined service request, aka. System calls. There are usually a few hundred or more of these, like e.g. read(2)/write(2). They are also generally exposed via libc wrappers (but not always) or via the indirect syscall(3) function. But it is also technically possible to directly encode the trap instruction, for example on x86 "int $0x80" or amd64 "syscall" with the desired syscall index. This is the part OpenBSD is proposing to lock down. The low-level syscall ABI has always been unstable, meaning it can be changed incompatibility, and libc is the more-stable interface applications should be using. With that out of the way.. > Is it possible to authorize arbitrary code, or is access to msyscall (via libc or otherwise) restricted outside of boot? msyscall(2) can only be called /once/ per-process, e.g. by the ld.so dynamic linker. This is used to indicate where libc is mapped (libraries are mapped randomly) to the kernel so it can permit that area to make syscalls.