[PATCH] Cygwin: signal: Clear direction flag in sigdeleyed

Christian Franke Christian.Franke@t-online.de
Mon Mar 24 10:59:58 GMT 2025


Takashi Yano wrote:
> x86_64 ABI requires the direction flag in CPU flags register cleared.
> https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions
> However, currently that flag is not maintained in signal handler.
> Therefore, if the signal handler is called when that flag is set, it
> destroys the data and may crash if rep instruction is used in the
> signal handler. With this patch, the direction flag is cleared in
> sigdelayed() by adding cld instruction.
>
> Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257704.html
> Fixes: 1fd5e000ace5 ("import winsup-2000-02-17 snapshot")
> Reported-by: Christian Franke <Christian.Franke@t-online.de>
> Reviewed-by:
> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
> ---
>   winsup/cygwin/scripts/gendef | 1 +
>   1 file changed, 1 insertion(+)
>
> diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef
> index a2f0392bc..861a2405b 100755
> --- a/winsup/cygwin/scripts/gendef
> +++ b/winsup/cygwin/scripts/gendef
> @@ -179,6 +179,7 @@ sigdelayed:
>   	movq	%rsp,%rbp
>   	pushf
>   	.seh_pushreg %rax			# fake, there's no .seh_pushreg for the flags
> +	cld					# x86_64 ABI requires direction flag cleared
>   	# stack is aligned or unaligned on entry!
>   	# make sure it is aligned from here on
>   	# We could be called from an interrupted thread which doesn't know

Works as expected:
- the testcase no longer aborts.

- a version with modified main loop does not detect DF modification by 
the signal:

   while ((cnt = sigcnt) < 1000) {
     if (!(__builtin_ia32_readeflags_u64() & 0x0400) != !std)
       return 13;
     if ((cnt & 1) && !std) {
       asm volatile ("std");
       std = 1;
     }
     else if (!(cnt & 1) && std) {
       asm volatile ("cld");
       std = 0;
     }
   }

- The related stress-ng testcases no longer report segfaults:

$ n=0
$ while
   stress-ng --parallel 2 --with memcpy,tree --memcpy-method libc 
--tree-method btree -t 2;
do echo OK $((++n)); done
...
OK 500
...


-- 
Thanks,
Christian



More information about the Cygwin-patches mailing list