Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

32bit tls is broken on 5.9-rc1 #2642

Closed
khuey opened this issue Aug 21, 2020 · 4 comments
Closed

32bit tls is broken on 5.9-rc1 #2642

khuey opened this issue Aug 21, 2020 · 4 comments
Assignees

Comments

@khuey
Copy link
Collaborator

khuey commented Aug 21, 2020

e.g. simple_32 will segfault on a TLS access when recording under rr

bisected to https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.8&id=b745cfba44c152c34363eea9e052367b6b1d652b

@khuey
Copy link
Collaborator Author

khuey commented Aug 21, 2020

Adding nofsgsbase to the kernel boot parameters does fix it.

@khuey
Copy link
Collaborator Author

khuey commented Aug 21, 2020

@khuey
Copy link
Collaborator Author

khuey commented Aug 21, 2020

@khuey khuey self-assigned this Aug 21, 2020
@khuey
Copy link
Collaborator Author

khuey commented Aug 21, 2020

Per the discussion on LKML, as of 5.9 we need to preserve fsbase/gsbase when running on a 64 bit kernel for both 32 and 64 bit tracees (we're currently only doing that, and it was previously only required, for 64 bit tracees).

@khuey khuey closed this as completed in c3292c7 Aug 22, 2020
khuey added a commit that referenced this issue Aug 25, 2020
When the GPRs are manipulated through PTRACE_GETREGS/PTRACE_SETREGS, whether the register set is the 32 bit user_regs_struct or the 64 bit user_regs_struct depends on whether rr is a 32 bit or 64 bit program. But when they're manipulated through PTRACE_GETREGSET/PTRACE_SETREGSET with the NT_PRSTATUS regset, it depends on whether the *tracee* is a 32 bit or 64 bit program.

Starting with kernel 5.9, if a 64 bit rr PTRACE_SETREGS a 32 bit tracee the fs/gsbase values in that user_regs_struct are used. This is a problem because we don't track them and thus they're always zero, regardless of what the correct value is. See LKML "x86/cpu fsgsbase breaks TLS in 32 bit rr tracees on a 64 bit system" for more discussion.

If we use PTRACE_SETREGSET we can pass in the 32 bit version of user_regs_struct and the kernel will figure out the correct fs/gsbase as before.

It's still more convenient to use PTRACE_GETREGS rather than PTRACE_GETREGSET so we can be sure where the CS register is in memory for testing whether we have a 64/32 bit process, so that and the conversion code stick around.

Fixes #2642 (again).
bkin pushed a commit to bkin/rr that referenced this issue May 20, 2021
bkin pushed a commit to bkin/rr that referenced this issue May 20, 2021
When the GPRs are manipulated through PTRACE_GETREGS/PTRACE_SETREGS, whether the register set is the 32 bit user_regs_struct or the 64 bit user_regs_struct depends on whether rr is a 32 bit or 64 bit program. But when they're manipulated through PTRACE_GETREGSET/PTRACE_SETREGSET with the NT_PRSTATUS regset, it depends on whether the *tracee* is a 32 bit or 64 bit program.

Starting with kernel 5.9, if a 64 bit rr PTRACE_SETREGS a 32 bit tracee the fs/gsbase values in that user_regs_struct are used. This is a problem because we don't track them and thus they're always zero, regardless of what the correct value is. See LKML "x86/cpu fsgsbase breaks TLS in 32 bit rr tracees on a 64 bit system" for more discussion.

If we use PTRACE_SETREGSET we can pass in the 32 bit version of user_regs_struct and the kernel will figure out the correct fs/gsbase as before.

It's still more convenient to use PTRACE_GETREGS rather than PTRACE_GETREGSET so we can be sure where the CS register is in memory for testing whether we have a 64/32 bit process, so that and the conversion code stick around.

Fixes rr-debugger#2642 (again).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant