Segfaults if CPU's PKU/PKRU feature is enabled
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 240
- Forks
- 60
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 1
Description
Hello!
This is about a bug affecting the msys2-docker-experimental images, reported at https://github.com/msys2/msys2-docker/issues/18 . I've now found this bug and think it should be fixed in the gendef file.
I'm not sure whether this bug applies to Cygwin, too, but it's about this code in gendef:
movl \$0x0d,%eax
xorl %ecx,%ecx
cpuid # get necessary space for xsave
movq %rbx,%rcx
addq \$0x48,%rbx # 0x18 for alignment, 0x30 for additional space
subq %rbx,%rsp
movl %ebx,0x24(%rsp)
xorq %rax,%rax
shrq \$3,%rcx
leaq 0x30(%rsp),%rdi
rep stosq
xgetbv # get XCR0 (ecx is 0 after rep)
movl %eax,0x28(%rsp)
movl %edx,0x2c(%rsp)
notl %ecx # set ecx non-zero
movl %ecx,0x20(%rsp)
xsave64 0x30(%rsp)
When running in Wine, I'm seeing segfaults caused by the final xsave64 instruction. These are because if the CPU's PKU/PKRU flag is enabled by Linux (disabling it by passing nopku on the kernel command line prevents the bug), it is also enabled in wine binaries, and that will make the cpuid instruction report a value of 2440 in rbx and rcx. This value is not a multiple of 64.
This results in a misaligned stack pointer when we hit the xsave64 instruction; xsave64 requires a 64-byte aligned storage area, and in an actual run, %rsp is 0x7ffffb648. This means the store goes to 0x7ffffb678, which isn't 64-byte aligned, causing a segfault.
However, even if the xsave64 instruction were to succeed, we'd crash a bit later because the stack pointer isn't aligned to the 16-byte boundary required by the ABI.
Unfortunately, I don't know how to rebuild msys2 to fix this. I can work around it by using Wine-gdb (winedbg --gdb bash.exe -c ... is what I'm running) , though:
For me, the cpuid instruction above is at 0x18019c645, so the following instruction is at 0x18019c647. After the cpuid instruction, we inject a breakpoint which increases %rbx by 56, making it 64-byte aligned again:
b *0x18019c647
Breakpoint 1 at 0x18019c647
Wine-gdb> command 1
command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>p $rbx += 56
>c
>end
Wine-gdb> c
This allows the program to execute normally even if the CPU's PKU/PKRU feature flag is in use. This suffices to convince me the bug is as I've described; sorry if the description is a bit terse, I'm happy to answer questions!
The proposed fix is to add something to the effect of %rbx += 63; %rbx &= -64; to gendef after the cpuid instruction but before the following mov: this will increase the reported size of the xsave area to the next 64-byte multiple, which will have the same effect as the GDB script above.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in gendef at the cpuid and xsave64 sequence shown in the issue. Check how the reported XSAVE size is used for stack allocation and confirm the required 64-byte storage and 16-byte ABI alignment. Done means the PKU/PKRU case no longer misaligns the stack or segfaults when running the affected msys2-docker-experimental scenario under Wine.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100