https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=a942476236b5e39bf30c533d08df7392e326a4c6
commit a942476236b5e39bf30c533d08df7392e326a4c6 Author: Corinna Vinschen <[email protected]> AuthorDate: Wed Mar 12 17:17:31 2025 +0100 Commit: Corinna Vinschen <[email protected]> CommitDate: Wed Mar 12 17:20:49 2025 +0100 Cygwin: sigdelayed: pop return address from signal stack earlier When a signal handler is called via sigdelayed, sigdelayed pops the original address to return to from the signal stack. It only does so after the signal handler has been called and returned. If the signal handler never returns, for instance because it calls longjmp or setcontext, the address stays on the signal stack and the stack loses one slot. Given the stack has a depth of 256 entries, no signal handler will be called after 256 signal handlers long jumping out. Pop the return address from the signal stack prior to calling the signal handler and store it in a callee-saved register. This avoids filling up the signal stack in a scenario like this. Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257648.html Fixes: 61522196c715 ("* Merge in cygwin-64bit-branch.") Signed-off-by: Corinna Vinschen <[email protected]> Diff: --- winsup/cygwin/release/3.6.0 | 4 ++++ winsup/cygwin/scripts/gendef | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0 index 4c953a84dfc3..d48ee114db82 100644 --- a/winsup/cygwin/release/3.6.0 +++ b/winsup/cygwin/release/3.6.0 @@ -128,3 +128,7 @@ Fixes: Addresses: https://cygwin.com/pipermail/cygwin/2025-January/257143.html - Fix EACCES error of sched_setaffinity(2) if pid of other process is used. + +- Fix starving of auxiliary signal return address stack in case signal + handlers bail out (longjmp/setcontext). + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257648.html diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef index 521550175f98..e3bcae5b7351 100755 --- a/winsup/cygwin/scripts/gendef +++ b/winsup/cygwin/scripts/gendef @@ -161,7 +161,7 @@ _sigbe: # return here after cygwin syscall jz 2f # if so pause jmp 1b # and loop -2: movq \$-8,%r11 # now decrement aux stack +2: movq \$-8,%r11 # decrement signal stack xaddq %r11,_cygtls.stackptr(%r10) # and get pointer movq -8(%r11),%r11 # get return address from signal stack decl _cygtls.incyg(%r10) @@ -250,6 +250,16 @@ sigdelayed: movq %gs:8,%r12 # get tls movl _cygtls.saved_errno(%r12),%r15d # temporarily save saved_errno + + # We have to fetch the original return address from the signal stack + # prior to calling the signal handler. This avoids filling up the + # signal stack if the signal handler longjumps (longjmp/setcontext). + # Store the return address in a callee-saved register (r13). + movq \$-8,%r11 # decrement signal stack + xaddq %r11,_cygtls.stackptr(%r12) # and get pointer + xorq %r13,%r13 + xchgq %r13,-8(%r11) # get return address from signal stack + movq \$_cygtls.start_offset,%rcx # point to beginning of tls block addq %r12,%rcx # and store as first arg to method call _ZN7_cygtls19call_signal_handlerEv # call handler @@ -260,15 +270,13 @@ sigdelayed: jz 2f # if so pause jmp 1b # and loop + 2: testl %r15d,%r15d # was saved_errno < 0 jl 3f # yup. ignore it movq _cygtls.errno_addr(%r12),%r11 movl %r15d,(%r11) -3: movq \$-8,%r11 # now decrement aux stack - xaddq %r11,_cygtls.stackptr(%r12) # and get pointer - xorq %r10,%r10 - xchgq %r10,-8(%r11) # get return address from signal stack - xorl %r11d,%r11d + +3: xorl %r11d,%r11d movl %r11d,_cygtls.incyg(%r12) movl %r11d,_cygtls.stacklock(%r12) # release lock @@ -285,6 +293,10 @@ sigdelayed: movl 0x24(%rsp),%ebx addq %rbx,%rsp + # Before restoring callee-saved registers, move return address from + # callee-saved r13 to caller-saved r10. + movq %r13, %r10 + popq %rax popq %rbx popq %rcx
