Comment by masklinn
2 years ago
The syscall goes in a register but it does not have to appear literally right next to the `syscall` instruction in the binary. As TFA explains in the introduction, a syscall stub generally looks like
mov eax,0x5
syscall
However it doesn’t have to, `syscall` will work as long as `eax` is set no matter where it’s set, or where it’s set from. You could load it from an array or a computation for all `syscall` cares.
So as an attacker if you can get eax to a value you control (and probably a few other registries) then jump to the `syscall` instruction directly you have arbitrary syscall capabilities.
The point of this change is that the loader now records exact syscall stubs as “address X performs syscall S”, then on context switch the kernel validates if the syscall being performed matches what was recorded by the loader, and if not it aborts (I assume I didn’t actually check).
This means as long as your go binary uses a normal syscall stub it’ll be recognised by the loader and whitelisted, but if say a JIT constructs syscalls dynamically (instead of bouncing through libc or whatever) that will be rejected because the loader won’t have that (address, number) recorded.
No comments yet
Contribute on Hacker News ↗