Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Seems like an interesting if maybe not practical protection to implement in eBPF for programs that never make a naked syscall.

Step one would be to ensure that every syscall has a wrapper. Place a uprobe at the start of that wrapper which, when hit, sets a per-thread permission bit and a per-thread-per-syscall permission bit in an eBPF map. Place a corresponding uretprobe that clears the per-thread-per-syscall bit. For each syscall place a kprobe which checks the per-thread table to make sure the thread is one which has enabled the feature, and which then checks to make sure the per-thread-per-syscall bit is set for that syscall. If not, sigkill.

Performance would probably suck but it seems like it would protect the syscall entrypoints enough to do some potentially interesting attack surface reduction. The question is really why you would do that there instead of by attaching to, say, the LSM hooks where you have stronger guarantees vis a vis userspace.



What’s the threat model this protects against?


"Attacker has ROP and shouldn't be able to make arbitrary syscalls".

Seems mildly useful if you have a really flexible syscall you can't forbid (ioctl, say) but which you only use for a specific narrow purpose.


If they can ROP they can jump to a syscall instruction with controlled arguments


The point of pinsyscall is that they have to jump to the single entry point for that syscall, rather than any of the ~200+ syscall instructions littering the address space. ALSR makes finding an entry point difficult, but that's easier if you only need to find any syscall instruction, rather than the specific one for the syscall you're invoking. The rationale is explained here: https://undeadly.org/cgi?action=article;sid=20230222064027


I’ve already expressed my opinion on this particular mitigation elsewhere and I’m pretty sure you’ve read it so I won’t go into it again here. I was more interested in the scheme that the other comment was constructing.


The point of what I spelled out above is that they can jump to the instruction but the kernel will kill the program if they don't go through the function up to that point. That allows you to restrict the arguments to the syscall at the point of call.


Ah, so it’s like a poor man’s BTI




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: