In a 64-bit C program, using glibc, pthreads and so on (nothing exotic), is it safe to overwrite the GS register, without restoring it, on current kernel and glibc versions? I know that the FS register is used by pthreads/glibc for the thread-local storage block pointer, so messing with that will wreck anything that uses TLS, but I'm not sure about GS
If not, is safe to save the value, overwrite it, and then restore the value, as long as the userland code while it is overwritten doesn't do X (what is X)?
I don't know for sure; Jester says "Yes, but instead of doing that you will likely want arch_prctl(ARCH_SET_GS, foo);"
Or on a CPU with FSGSBASE, perhaps wrgsbase from user-space, if the kernel (such as Linux 5.9 or newer) enables that for user-space use. (CR4.FSGSBASE[bit 16] must be set or it faults with #UD).
I know that x86-64 switched to using FS for TLS (32-bit uses GS) because of how the syscall entry point uses swapgs to find the kernel stack.
I think that was that just for consistency between user and kernel for kernel TLS / per-core stuff, because 32-bit processes under a 64-bit kernel do still use GS for TLS. Except 32-bit processes can't use syscall (except on AMD CPUs). That alone doesn't rule out some code that only executes for a 64-bit process that could do something with GS, but probably there's no problem.
swapgs only swaps the GS base, not the selector. I don't know if there are any kernel entry points that would rewrite GS with some default selector value (and then reload the saved GS base). I'd guess not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With