sgx-lkl icon indicating copy to clipboard operation
sgx-lkl copied to clipboard

Stack protector support

Open jhand2 opened this issue 4 years ago • 9 comments

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.

jhand2 avatar Jun 03 '20 00:06 jhand2

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?

jxyang avatar Jun 03 '20 18:06 jxyang

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.

jhand2 avatar Jun 03 '20 18:06 jhand2

Isn't that should be the stack protector for the other lthread gets scheduled on the ethread?

jxyang avatar Jun 03 '20 18:06 jxyang

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.

jhand2 avatar Jun 03 '20 19:06 jhand2

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.

davidchisnall avatar Jun 05 '20 07:06 davidchisnall

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.

jhand2 avatar Jun 08 '20 17:06 jhand2

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.

davidchisnall avatar Jun 09 '20 07:06 davidchisnall

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.

jhand2 avatar Jun 09 '20 16:06 jhand2

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).

davidchisnall avatar Jun 09 '20 17:06 davidchisnall