____chkstk_darwin incorrectly probes twice the requested stack size, results in invalid memory access

Originator:arnaud.lb
Number:rdar://FB11582939 Date Originated:2022-09-24
Status:Open Resolved:
Product:macOS Product Version:12.5
Classification:Crash Reproducible:Always
 
Apple clang emits a call to ____chkstk_darwin in functions that use more than a page of stack space. This is to prevent skipping over the guard page.

When using an altstack, ____chkstk_darwin probes an unexpectedly far away location. It correctly probes a location every 0x1000 bytes from %rsp to %rsp-stack_size, but it then *incorrectly* probes a location near %rsp-stack_size*2 (which is the last probed location less stack_size).

This last probing may cause an invalid memory access. As a result, functions that use N stack space may cause the program to crash if there is less than N*2 available stack space.

How to reproduce:

- https://gist.github.com/arnaud-lb/495b5e22810e3dfe951fb42a65063e36
- cc -o test test.c
- ./test

Expected result: the program terminates normally

Actual result: zsh: bus error  ./test

The culprit seems to be that after probing every page, ___chkstk_darwin subtracts %rax (the requested stack size) from the last probed location, and probes the resulting address: https://github.com/apple-oss-distributions/libpthread/blob/e42795c13eaf5eb32ae06103b1b50caae3c01d27/src/pthread_asm.s#L99-L101

```
Lloop:
	subq   $0x1000, %rcx
	testq  %rcx, (%rcx)
	subq   $0x1000, %rax
	cmpq   $0x1000, %rax
	ja     Lloop
	popq   %rax           // %rax: requested stack size
Lend:
	subq   %rax, %rcx     // %rcx: last probed location
	testq  %rcx, (%rcx)   // invalid memory access 

	popq   %rcx
	retq
```

____chkstk_darwin is emitted by clang (Apple version only) when -fstack-check is enabled (the default).

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!