sgx-lkl
sgx-lkl copied to clipboard
Stack protector support
Are there currently plans to support random stack protectors in SGX-LKL code?
Currently the OE branch sets the stack protector for each ethread to the same value (0). This is because an lthread could start a function on one ethread, yield, and then be rescheduled on a different ethread. In this case, stack guard checks will fail if each ethread has a different stack guard.
I think if we bind a lthread to an ethread permanently, we lose quite flexibilities in scheduling, and would hurt the performance.
What about we set the stack protector for all ethreads to the same non-zero value? Is there value doing so?
What about we set the stack protector for all ethreads to the same non-zero value? Is there value doing so?
IMO from a security perspective, no.
My suggestion would be to track a per-lthread stack protector and set %fs:0x28 whenever the lthread gets scheduled. This does have a complication that eventually when the lthread exits you have to put back OE's stack protector on the ethread.
Isn't that should be the stack protector for the other lthread gets scheduled on the ethread?
When you (an lthread) get scheduled on an ethread you could set %fs:0x28 to some value you hold in the lthread struct. Then on context switch, the next lthread would change to it's value.
This only matters in cases where an lthread does not have it's own tls area.
Once the relayering is done (specifically the pthread work that @vtikoo is doing), we will have two different kinds of %fs regions. For threads created in userspace, libc’s pthread implementation will set a random value in %fs:28. Other threads do not need tls, but we should ensure that they have something in the FS segment that contains a random canary value.
Note that the lthread scheduler switches %fs on every context switch between lthreads, so if their thread area has a different stack canary value then this will be preserved.
If we randomised on every lthread context switch, we’d get stack protector errors as soon as a function called before a yield returned.
Note that the lthread scheduler switches %fs on every context switch between lthreads, so if their thread area has a different stack canary value then this will be preserved.
This isn't quite true though right? For lthreads without usermode threading (lthreads created before initializing libc), they do not change fs on context switch.
If we randomised on every lthread context switch, we’d get stack protector errors as soon as a function called before a yield returned.
Agreed, the random value should be computed once per lthread. See above for what my concern was.
I don’t understand what you mean by ‘lthreads without usermode threading’. Lthreads switch fs if the new thread has an itls flag set. Since none of the kernel threads use itls, we can either have them all share an FS segment (and, thus, canary value) or allocate a small itls segment for each, with a different canary value.
I meant without usermode tls.
or allocate a small itls segment for each, with a different canary value
That would be my preference. This would avoid changing the ethread's stack protector. Changing the ethread's stack protector will cause stack check failures in OE code when the application exits.
Hmm, that's a good point. That means that @vtikoo will have to make sure not to replace the stack canary value in ethread TLS value (or, rather, to copy that value from the old TLS segment).