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

Reply via email to