diff options
author | Sverker Eriksson <sverker@erlang.org> | 2020-09-16 23:03:25 +0200 |
---|---|---|
committer | Sverker Eriksson <sverker@erlang.org> | 2020-09-25 12:58:59 +0200 |
commit | bf984876f69ad039b64f573baeef57a51c48f1e3 (patch) | |
tree | d8074f473709e54d1fa4bb52d84dde6bb6c6bc83 /erts | |
parent | 9303603b91f268181596a391c6af64248baba1a2 (diff) | |
download | erlang-bf984876f69ad039b64f573baeef57a51c48f1e3.tar.gz |
erts: Preserve instruction word arguments in call_nif_early
to fix race when a write of call_nif_early comes between
instruction dispatch and a repeated read of arguments from I[0].
This is already done for tracing when writing i_generic_breakpoint
instruction.
Race seen provoked when compiled with NO_JUMP_TABLE.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 9b12c459fe..420826ea86 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -4604,6 +4604,7 @@ Eterm erts_load_nif(Process *c_p, BeamInstr *I, Eterm filename, Eterm args) static void patch_call_nif_early(ErlNifEntry* entry, struct erl_module_instance* this_mi) { + const BeamInstr call_nif_early = BeamOpCodeAddr(op_call_nif_early); int i; ERTS_LC_ASSERT(erts_has_code_write_permission()); @@ -4626,13 +4627,13 @@ static void patch_call_nif_early(ErlNifEntry* entry, * Code write permission protects against racing breakpoint writes. */ GenericBp* g = ci->u.gen_bp; - g->orig_instr = BeamOpCodeAddr(op_call_nif_early); + g->orig_instr = BeamSetCodeAddr(g->orig_instr, call_nif_early); if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint)) continue; } else ASSERT(!BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint)); - code_ptr[0] = BeamOpCodeAddr(op_call_nif_early); + code_ptr[0] = BeamSetCodeAddr(code_ptr[0], call_nif_early); } } @@ -4711,12 +4712,12 @@ static void load_nif_2nd_finisher(void* vlib) * Function traced, patch the original instruction word */ GenericBp* g = ci->u.gen_bp; - ASSERT(g->orig_instr == BeamOpCodeAddr(op_call_nif_early)); + ASSERT(BeamIsOpCode(g->orig_instr, op_call_nif_early)); g->orig_instr = BeamOpCodeAddr(op_call_nif_WWW); if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint)) continue; } - ASSERT(code_ptr[0] == BeamOpCodeAddr(op_call_nif_early)); + ASSERT(BeamIsOpCode(code_ptr[0], op_call_nif_early)); code_ptr[0] = BeamOpCodeAddr(op_call_nif_WWW); } } |