Clever ARM instruction validation for Chrome Native Client
chromium.org
chromium.org
We enforce this rule by restricting the sorts of operations that
programs can use to alter sp. Programs can alter sp by adding or
subtracting an immediate, as a side-effect of a load or store:
ldr rX, [sp], #4! ; loads from stack, then adds 4 to sp
These are safe because, as we mentioned before, the largest
immediate available in a load or store is ±4095. Even after adding or
subtracting 4095, the stack pointer will still be within the sandbox or
guard regions.
I get the idea of the guard protecting against the biggest immediate offset, but what stops me doing an SP-updating LDR with a big offset multiple times, pushing SP beyond my "safe" memory segment?EDIT: I guess I might be taking:
Any other operation that alters sp must be followed by a guard
instruction.
too precisely, and you could just follow every ldr which writes back SP with a BIC too. Maybe I'm missing the point.EDIT2: Wait, wait, I get it now. Once the stack pointer is in the guard area, the CPU faults if you do another LDR. Don't mind me!
EDIT: No, you don't need to check after a stack memory access either. The farthest you can get out of the sandbox is an access-then-adjust of 4095 bytes, followed by an adjust-then-access of 4095 bytes, which means you access the very tail end (offset 8190) of the guard zone, fault, and die.
(The article does mention that the guard pages are set to no read/write/execute)
In other words, this is a lot less slow than it sounds.
The main problem I see here is significantly increased code size, which will put additional pressure on the L1 I-cache.
And the most common "frequent" accesses (stack space) don't require those checks.
As I said, not really significant unless your loop is so tight that memory latency is the big limiter anyway.