threading: fix race condition when _ecl_frs_push is interrupted with a call to ecl_unwind

If by chance env->frs_top->frs_val has the value ECL_PROTECT_TAG,
    ecl_unwind will stop and call longjmp. However, at this point
    setjmp has not yet been called, leading to a segmentation fault.
This commit is contained in:
Marius Gerbershagen 2018-02-10 18:11:27 +01:00
parent 6d7ec733eb
commit ca5ef0f977
4 changed files with 11 additions and 2 deletions

View file

@ -532,6 +532,12 @@ frs_overflow(void) /* used as condition in list.d */
ecl_frame_ptr
_ecl_frs_push(register cl_env_ptr env, register cl_object val)
{
/* We store a dummy tag first, to make sure that it is safe to
* interrupt this method with a call to ecl_unwind. Otherwise, a
* stray ECL_PROTECT_TAG will lead to segfaults. AO_store_full is
* needed to ensure that the CPU doesn't reorder the memory
* stores. */
AO_store_full((AO_t*)&(env->frs_top+1)->frs_val,(AO_t)ECL_DUMMY_TAG);
ecl_frame_ptr output = ++env->frs_top;
if (output >= env->frs_limit) {
frs_overflow();

View file

@ -74,6 +74,7 @@ cl_symbols[] = {
{"T", CL_ORDINARY, NULL, -1, OBJNULL},
{SYS_ "UNBOUND", SI_CONSTANT, si_unbound, 0, ECL_UNBOUND},
{SYS_ "PROTECT-TAG", SI_ORDINARY, NULL, -1, OBJNULL},
{SYS_ "DUMMY-TAG", SI_ORDINARY, NULL, -1, OBJNULL},
{SYS_ "*RESTART-CLUSTERS*", SI_SPECIAL, NULL, -1, Cnil},
{SYS_ "*HANDLER-CLUSTERS*", SI_SPECIAL, NULL, -1, Cnil},

View file

@ -74,6 +74,7 @@ cl_symbols[] = {
{"T",NULL},
{SYS_ "UNBOUND","si_unbound"},
{SYS_ "PROTECT-TAG",NULL},
{SYS_ "DUMMY-TAG",NULL},
{SYS_ "*RESTART-CLUSTERS*",NULL},
{SYS_ "*HANDLER-CLUSTERS*",NULL},

View file

@ -246,8 +246,9 @@ enum ecl_stype { /* symbol type */
#define ECL_T ((cl_object)(cl_symbols+1))
#define ECL_UNBOUND ((cl_object)(cl_symbols+2))
#define ECL_PROTECT_TAG ((cl_object)(cl_symbols+3))
#define ECL_RESTART_CLUSTERS ((cl_object)(cl_symbols+4))
#define ECL_HANDLER_CLUSTERS ((cl_object)(cl_symbols+5))
#define ECL_DUMMY_TAG ((cl_object)(cl_symbols+4))
#define ECL_RESTART_CLUSTERS ((cl_object)(cl_symbols+5))
#define ECL_HANDLER_CLUSTERS ((cl_object)(cl_symbols+6))
#define ECL_NO_TL_BINDING ((cl_object)(1 << ECL_TAG_BITS))
struct ecl_symbol {