NetBSD Problem Report #57946

From www@netbsd.org  Mon Feb 19 04:24:45 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 97E361A9239
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 19 Feb 2024 04:24:45 +0000 (UTC)
Message-Id: <20240219042444.458CA1A923A@mollari.NetBSD.org>
Date: Mon, 19 Feb 2024 04:24:44 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: longjmp fails to restore stack first before restoring signal mask on most architectures
X-Send-Pr-Version: www-1.0

>Number:         57946
>Notify-List:    uwe@NetBSD.org
>Category:       lib
>Synopsis:       longjmp fails to restore stack first before restoring signal mask on most architectures
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          analyzed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 19 04:25:01 +0000 2024
>Closed-Date:    
>Last-Modified:  Thu Apr 04 00:50:03 +0000 2024
>Originator:     Taylor R Campbell
>Release:        current, 10, 9, 8, ...
>Organization:
The NetBSD FoundaSQUIRREL
>Environment:
arm, hppa, i386, ia64, mips, sh3, sparc, sparc64, amd64
>Description:
longjmp(3) is supposed to restore various saved state, including
registers, stack pointer, and signal mask, and then come flying out of
the corresponding call to setjmp(3).

However, if a signal is already pending, and longjmp(3) restores the
signal mask first, the signal handler will be triggered before the
stack pointer has been restored -- which means if the signal handler
itself called longjmp, it may recursively enter on the signal stack
rather than the original stack.
>How-To-Repeat:
// https://www.openwall.com/lists/musl/2024/02/18/16
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

static volatile long cnt = 1000000;
jmp_buf jb;

void handle(int s)
{
      volatile int x;
      if (cnt % 1000 == 0) printf("%p\n", &x);
      if (!cnt--) return;
      raise(s);
      longjmp(jb, 1);
}

int main()
{
      if (setjmp(jb)) return 0;
      signal(SIGALRM, handle);
      raise(SIGALRM);
}

>Fix:
Restore signal mask last in longjmp (and in siglongjmp for the savemask case).

>Release-Note:

>Audit-Trail:
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src
Date: Mon, 19 Feb 2024 04:30:39 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 04:30:39 UTC 2024

 Modified Files:
 	src/distrib/sets/lists/debug: mi
 	src/distrib/sets/lists/tests: mi
 	src/tests/lib/libc/setjmp: Makefile
 Added Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3): Add test for PR lib/57946.


 To generate a diff of this commit:
 cvs rdiff -u -r1.424 -r1.425 src/distrib/sets/lists/debug/mi
 cvs rdiff -u -r1.1305 -r1.1306 src/distrib/sets/lists/tests/mi
 cvs rdiff -u -r1.2 -r1.3 src/tests/lib/libc/setjmp/Makefile
 cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src/tests/lib/libc/setjmp
Date: Mon, 19 Feb 2024 04:33:21 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 04:33:21 UTC 2024

 Modified Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3): Paranoia: more error checking in PR lib/57946 test.


 To generate a diff of this commit:
 cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->analyzed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Mon, 19 Feb 2024 04:40:30 +0000
State-Changed-Why:
problem analyzed


From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src/tests/lib/libc/setjmp
Date: Mon, 19 Feb 2024 12:29:48 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 12:29:48 UTC 2024

 Modified Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3): Test signal mask vs stack restore with siglongjmp too.

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.2 -r1.3 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src/tests/lib/libc/setjmp
Date: Mon, 19 Feb 2024 12:41:19 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 12:41:19 UTC 2024

 Modified Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3) t_sigstack: Print which entry failed.

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.3 -r1.4 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src/tests/lib/libc/setjmp
Date: Mon, 19 Feb 2024 12:41:27 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 12:41:27 UTC 2024

 Modified Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3) t_sigstack: Note aarch64 seems to DTRT.

 But only by code inspection; it appears to have another problem: on
 re-entry, the signal handler is called on the normal stack, not on
 the alternate signal stack.

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.4 -r1.5 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src/tests/lib/libc/setjmp
Date: Mon, 19 Feb 2024 13:34:48 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 13:34:48 UTC 2024

 Modified Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3) t_sigstack: Use a sigaltstack per handler entry.

 longjmp evidently doesn't reset the state of whether the process is
 executing on the alternate signal stack.  So when we re-enter the
 signal handler, the alternate stack appears to be still in use, and
 the system chooses the original stack for the second call to the
 signal handler -- which trips our assertion asking to verify that the
 signal handler is always using an alternate stack.

 Not strictly necessary for the signal handler to use an alternate
 stack on re-entry, but this makes it clearer that the signal handler
 itself is always using the alternate stack so we can verify that the
 interrupted code is _not_ in the signal handler.

 With this change, the test now passes on aarch64.

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.5 -r1.6 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src/tests/lib/libc/setjmp
Date: Mon, 19 Feb 2024 19:43:27 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Mon Feb 19 19:43:27 UTC 2024

 Modified Files:
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 longjmp(3) t_sigstack: Fix fencepost error.

 Extremely unlikely to cause trouble, but let's just turn that into
 `never' to keep it easier for readers.

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.6 -r1.7 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src
Date: Thu, 4 Apr 2024 00:46:30 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Thu Apr  4 00:46:30 UTC 2024

 Modified Files:
 	src/lib/libc/arch/x86_64/gen: __setjmp14.S __sigsetjmp14.S
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 amd64 longjmp: Restore stack first, then signal mask.

 Otherwise, a pending signal may be delivered on the wrong stack when
 we restore the signal mask.

 While here:

 - Tidy the code a little bit.
 - Sprinkle comments to explain what's going on.
 - Use `xorl %eXX,%eXX' instead of `xorq %rXX,%rXX'.
   => Same effect, one byte shorter, breaks dep chain on more uarches.
 - Use forward branches for statically predicted not-taken.
   => val==0 is unlikely in longjmp

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.3 -r1.4 src/lib/libc/arch/x86_64/gen/__setjmp14.S \
     src/lib/libc/arch/x86_64/gen/__sigsetjmp14.S
 cvs rdiff -u -r1.7 -r1.8 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/57946 CVS commit: src
Date: Thu, 4 Apr 2024 00:46:42 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Thu Apr  4 00:46:42 UTC 2024

 Modified Files:
 	src/lib/libc/arch/i386/gen: setjmp.S sigsetjmp.S
 	src/tests/lib/libc/setjmp: t_sigstack.c

 Log Message:
 i386 longjmp: Restore stack first, then signal mask.

 Otherwise, a pending signal may be delivered on the wrong stack when
 we restore the signal mask.

 While here:

 - Tidy the code a little bit.
 - Sprinkle comments to explain what's going on.
 - Use forward branches for statically predicted not-taken.
   => val==0 is unlikely in longjmp

 PR lib/57946


 To generate a diff of this commit:
 cvs rdiff -u -r1.17 -r1.18 src/lib/libc/arch/i386/gen/setjmp.S
 cvs rdiff -u -r1.18 -r1.19 src/lib/libc/arch/i386/gen/sigsetjmp.S
 cvs rdiff -u -r1.8 -r1.9 src/tests/lib/libc/setjmp/t_sigstack.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.