6fbb4db452
Don't use %configure macro because that breaks on riscv64. https://bugzilla.redhat.com/2124272
195 lines
6.8 KiB
Diff
195 lines
6.8 KiB
Diff
From 1c4df0352d5f75464acdb27377ccd10d1e0ba10a Mon Sep 17 00:00:00 2001
|
|
From: Xavier Leroy <xavierleroy@users.noreply.github.com>
|
|
Date: Mon, 22 Aug 2022 16:06:50 +0200
|
|
Subject: [PATCH 18/24] More prudent deallocation of alternate signal stack
|
|
(#11496)
|
|
|
|
After `caml_setup_stack_overflow_detection` is called,
|
|
a C library can install its own alternate stack for signal handling.
|
|
|
|
Therefore, `caml_stop_stack_overflow_detection` must not free the
|
|
alternate signal stack block, only the block that
|
|
`caml_setup_stack_overflow_detection` allocated.
|
|
|
|
Fixes: #11489
|
|
---
|
|
Changes | 4 +++
|
|
otherlibs/systhreads/st_stubs.c | 5 ++--
|
|
runtime/caml/signals.h | 4 +--
|
|
runtime/signals_byt.c | 4 +--
|
|
runtime/signals_nat.c | 47 +++++++++++++++++++++------------
|
|
5 files changed, 41 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/Changes b/Changes
|
|
index 6b537edca9..4d1bb10435 100644
|
|
--- a/Changes
|
|
+++ b/Changes
|
|
@@ -41,6 +41,10 @@ OCaml 4.14 maintenance branch
|
|
mingw-w64 i686 port.
|
|
(David Allsopp, review by Xavier Leroy and Sébastien Hinderer)
|
|
|
|
+- #11489, #11496: More prudent deallocation of alternate signal stack
|
|
+ (Xavier Leroy, report by @rajdakin, review by Florian Angeletti)
|
|
+
|
|
+
|
|
OCaml 4.14.0 (28 March 2022)
|
|
----------------------------
|
|
|
|
diff --git a/otherlibs/systhreads/st_stubs.c b/otherlibs/systhreads/st_stubs.c
|
|
index b7a6a9a6bb..043e07031e 100644
|
|
--- a/otherlibs/systhreads/st_stubs.c
|
|
+++ b/otherlibs/systhreads/st_stubs.c
|
|
@@ -524,6 +524,7 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg)
|
|
{
|
|
caml_thread_t th = (caml_thread_t) arg;
|
|
value clos;
|
|
+ void * signal_stack;
|
|
#ifdef NATIVE_CODE
|
|
struct longjmp_buffer termination_buf;
|
|
char tos;
|
|
@@ -536,7 +537,7 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg)
|
|
/* Acquire the global mutex */
|
|
caml_leave_blocking_section();
|
|
st_thread_set_id(Ident(th->descr));
|
|
- caml_setup_stack_overflow_detection();
|
|
+ signal_stack = caml_setup_stack_overflow_detection();
|
|
#ifdef NATIVE_CODE
|
|
/* Setup termination handler (for caml_thread_exit) */
|
|
if (sigsetjmp(termination_buf.buf, 0) == 0) {
|
|
@@ -550,7 +551,7 @@ static ST_THREAD_FUNCTION caml_thread_start(void * arg)
|
|
#ifdef NATIVE_CODE
|
|
}
|
|
#endif
|
|
- caml_stop_stack_overflow_detection();
|
|
+ caml_stop_stack_overflow_detection(signal_stack);
|
|
/* The thread now stops running */
|
|
return 0;
|
|
}
|
|
diff --git a/runtime/caml/signals.h b/runtime/caml/signals.h
|
|
index c6aeebfc78..62b0e7fafa 100644
|
|
--- a/runtime/caml/signals.h
|
|
+++ b/runtime/caml/signals.h
|
|
@@ -87,8 +87,8 @@ value caml_do_pending_actions_exn (void);
|
|
value caml_process_pending_actions_with_root (value extra_root); // raises
|
|
value caml_process_pending_actions_with_root_exn (value extra_root);
|
|
int caml_set_signal_action(int signo, int action);
|
|
-CAMLextern int caml_setup_stack_overflow_detection(void);
|
|
-CAMLextern int caml_stop_stack_overflow_detection(void);
|
|
+CAMLextern void * caml_setup_stack_overflow_detection(void);
|
|
+CAMLextern int caml_stop_stack_overflow_detection(void *);
|
|
CAMLextern void caml_init_signals(void);
|
|
CAMLextern void caml_terminate_signals(void);
|
|
CAMLextern void (*caml_enter_blocking_section_hook)(void);
|
|
diff --git a/runtime/signals_byt.c b/runtime/signals_byt.c
|
|
index 439fb56404..7cb461ac4d 100644
|
|
--- a/runtime/signals_byt.c
|
|
+++ b/runtime/signals_byt.c
|
|
@@ -81,7 +81,7 @@ int caml_set_signal_action(int signo, int action)
|
|
return 0;
|
|
}
|
|
|
|
-CAMLexport int caml_setup_stack_overflow_detection(void) { return 0; }
|
|
-CAMLexport int caml_stop_stack_overflow_detection(void) { return 0; }
|
|
+CAMLexport void * caml_setup_stack_overflow_detection(void) { return NULL; }
|
|
+CAMLexport int caml_stop_stack_overflow_detection(void * p) { return 0; }
|
|
CAMLexport void caml_init_signals(void) { }
|
|
CAMLexport void caml_terminate_signals(void) { }
|
|
diff --git a/runtime/signals_nat.c b/runtime/signals_nat.c
|
|
index 443f5d53b6..1dd8289c12 100644
|
|
--- a/runtime/signals_nat.c
|
|
+++ b/runtime/signals_nat.c
|
|
@@ -254,6 +254,10 @@ DECLARE_SIGNAL_HANDLER(segv_handler)
|
|
|
|
/* Initialization of signal stuff */
|
|
|
|
+#ifdef HAS_STACK_OVERFLOW_DETECTION
|
|
+static void * caml_signal_stack = NULL;
|
|
+#endif
|
|
+
|
|
void caml_init_signals(void)
|
|
{
|
|
/* Bound-check trap handling */
|
|
@@ -278,7 +282,8 @@ void caml_init_signals(void)
|
|
#endif
|
|
|
|
#ifdef HAS_STACK_OVERFLOW_DETECTION
|
|
- if (caml_setup_stack_overflow_detection() != -1) {
|
|
+ caml_signal_stack = caml_setup_stack_overflow_detection();
|
|
+ if (caml_signal_stack != NULL) {
|
|
struct sigaction act;
|
|
SET_SIGACT(act, segv_handler);
|
|
act.sa_flags |= SA_ONSTACK | SA_NODEFER;
|
|
@@ -314,7 +319,8 @@ void caml_terminate_signals(void)
|
|
|
|
#ifdef HAS_STACK_OVERFLOW_DETECTION
|
|
set_signal_default(SIGSEGV);
|
|
- caml_stop_stack_overflow_detection();
|
|
+ caml_stop_stack_overflow_detection(caml_signal_stack);
|
|
+ caml_signal_stack = NULL;
|
|
#endif
|
|
}
|
|
|
|
@@ -323,37 +329,44 @@ void caml_terminate_signals(void)
|
|
Each thread needs its own alternate stack.
|
|
The alternate stack used to be statically-allocated for the main thread,
|
|
but this is incompatible with Glibc 2.34 and newer, where SIGSTKSZ
|
|
- may not be a compile-time constant (issue #10250). */
|
|
+ may not be a compile-time constant (issue #10250).
|
|
+ Return the dynamically-allocated alternate signal stack, or NULL
|
|
+ if an error occurred.
|
|
+ The returned pointer must be passed to [caml_stop_stack_overflow_detection].
|
|
+*/
|
|
|
|
-CAMLexport int caml_setup_stack_overflow_detection(void)
|
|
+CAMLexport void * caml_setup_stack_overflow_detection(void)
|
|
{
|
|
#ifdef HAS_STACK_OVERFLOW_DETECTION
|
|
stack_t stk;
|
|
- stk.ss_sp = malloc(SIGSTKSZ);
|
|
- if (stk.ss_sp == NULL) return -1;
|
|
stk.ss_size = SIGSTKSZ;
|
|
+ stk.ss_sp = malloc(stk.ss_size);
|
|
+ if (stk.ss_sp == NULL) return NULL;
|
|
stk.ss_flags = 0;
|
|
if (sigaltstack(&stk, NULL) == -1) {
|
|
free(stk.ss_sp);
|
|
- return -1;
|
|
+ return NULL;
|
|
}
|
|
+ return stk.ss_sp;
|
|
+#else
|
|
+ return NULL;
|
|
#endif
|
|
- /* Success (or stack overflow detection not available) */
|
|
- return 0;
|
|
}
|
|
|
|
-CAMLexport int caml_stop_stack_overflow_detection(void)
|
|
+CAMLexport int caml_stop_stack_overflow_detection(void * signal_stack)
|
|
{
|
|
#ifdef HAS_STACK_OVERFLOW_DETECTION
|
|
stack_t oldstk, stk;
|
|
stk.ss_flags = SS_DISABLE;
|
|
+ stk.ss_sp = NULL; /* not required but avoids a valgrind false alarm */
|
|
+ stk.ss_size = SIGSTKSZ; /* macOS wants a valid size here */
|
|
if (sigaltstack(&stk, &oldstk) == -1) return -1;
|
|
- /* If caml_setup_stack_overflow_detection failed, we are not using
|
|
- an alternate signal stack. SS_DISABLE will be set in oldstk,
|
|
- and there is nothing to free in this case. */
|
|
- if (! (oldstk.ss_flags & SS_DISABLE)) free(oldstk.ss_sp);
|
|
- return 0;
|
|
-#else
|
|
- return 0;
|
|
+ /* Check whether someone else installed their own signal stack */
|
|
+ if (!(oldstk.ss_flags & SS_DISABLE) && oldstk.ss_sp != signal_stack) {
|
|
+ /* Re-activate their signal stack. */
|
|
+ sigaltstack(&oldstk, NULL);
|
|
+ }
|
|
+ free(signal_stack);
|
|
#endif
|
|
+ return 0;
|
|
}
|
|
--
|
|
2.37.0.rc2
|
|
|