This is good portable programming practise anyway...
This is good portable programming practise anyway...
How does this stop an attacker doing the same via ROP?
ADDED: The approach that comes to my mind is that they could have two processes. One process has the sourcecode, and pages where it can write code. The other process can execute the code. The code updates performance counters which the JITing process can read, so the JITter has feedback to know what to optimise.
However, this sounds a large architectural change, prevents programs JITting programs they generate on the fly, and causes the JIT to lack behind somewhat.
On the Mill CPU (disclaimer: I'm on the Mill team) the CPU can change processes ("turfs" in Mill terms) using a "portal" function call. This alleviates somewhat the performance concerns, as the JITted program can call into the JITer process synchronously and cheaply.
Wait, isn't that backwards? Doesn't the use of W^X necessitate the use of ROP? Right now a JIT has lots of memory that is W&X so you just need a memory exploit to inject some code and then find a way to jump to it, no need for ROP.
But if you implement W^X this won't work because now you can't inject code with just a memory exploit, you also have to set it to executable with mprotect(2). So instead you use ROP, and inject only data which includes jumps to carefully selected sections of code in libc, etc, that implements an exploit. I mean you could probably use ROP to run mprotect, but by that point it's pointless because you're already running code on the system right?