Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:27
erlang
0119-JIT-Fix-unsafe-in-place-update-during-disa...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0119-JIT-Fix-unsafe-in-place-update-during-disabled-GC.patch of Package erlang
From a1805974f864fe68280feecac2839be6e4ea0016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Fri, 31 May 2024 09:23:16 +0200 Subject: [PATCH 2/2] JIT: Fix unsafe in-place update during disabled GC When GC was temporarily disabled (for example during the execution of some BIFs), an unsafe in-place update of a record could occur. --- erts/emulator/beam/erl_gc.c | 5 ++++ erts/emulator/beam/jit/arm/instr_common.cpp | 23 +++++++++++++++++ erts/emulator/beam/jit/beam_jit_common.cpp | 26 +++++++++++++++++++ erts/emulator/beam/jit/beam_jit_common.hpp | 4 +++ erts/emulator/beam/jit/x86/instr_common.cpp | 28 +++++++++++++++++++++ 5 files changed, 86 insertions(+) diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 3b1fd5009b..928015a740 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -559,6 +559,11 @@ delay_garbage_collection(Process *p, int need, int fcalls) } p->abandoned_heap = orig_heap; erts_adjust_memory_break(p, orig_htop - p->high_water); + + /* Point at the end of the address range to ensure that + * test for the safe range in the new heap in the + * update_record_in_place instruction fails. */ + p->high_water = (Eterm *) (Uint) -1; } #ifdef CHECK_FOR_HOLES diff --git a/erts/emulator/beam/jit/arm/instr_common.cpp b/erts/emulator/beam/jit/arm/instr_common.cpp index 62af175655..397d5b88fe 100644 --- a/erts/emulator/beam/jit/arm/instr_common.cpp +++ b/erts/emulator/beam/jit/arm/instr_common.cpp @@ -1071,6 +1071,29 @@ void BeamModuleAssembler::emit_update_record_in_place( a.add(destination.reg, untagged_src, TAG_PRIMARY_BOXED); flush_var(destination); + +#ifdef DEBUG + if (!all_safe && maybe_immediate.isNil()) { + Label pointer_ok = a.newLabel(); + + /* If p->high_water contained a garbage value, a tuple not in + * the safe part of the new heap could have been destructively + * updated. */ + comment("sanity-checking tuple pointer"); + mov_arg(ARG2, Dst); + a.ldr(ARG4, arm::Mem(c_p, offsetof(Process, heap))); + a.cmp(ARG2, HTOP); + a.ccmp(ARG2, ARG4, imm(NZCV::kNone), imm(arm::CondCode::kLO)); + a.b_hs(pointer_ok); + + emit_enter_runtime(); + a.mov(ARG1, c_p); + runtime_call<2>(beam_jit_invalid_heap_ptr); + emit_leave_runtime(); + + a.bind(pointer_ok); + } +#endif } void BeamModuleAssembler::emit_set_tuple_element(const ArgSource &Element, diff --git a/erts/emulator/beam/jit/beam_jit_common.cpp b/erts/emulator/beam/jit/beam_jit_common.cpp index 1f2957addb..73f86ebbde 100644 --- a/erts/emulator/beam/jit/beam_jit_common.cpp +++ b/erts/emulator/beam/jit/beam_jit_common.cpp @@ -1365,3 +1365,29 @@ bool beam_jit_is_shallow_boxed(Eterm term) { return false; } } + +#ifdef DEBUG +void beam_jit_invalid_heap_ptr(Process *p, Eterm term) { + ASSERT((void *)term <= (void *)p->heap || (void *)term >= (void *)p->hend); + + erts_fprintf(stderr, + "term: %p\n" + "c_p: %p\n" + "heap: %p\n" + "high_water: %p\n" + "hend: %p\n" + "abandoned: %p\n", + (void *)term, + p, + p->heap, + p->high_water, + p->hend, + p->abandoned_heap); + if (p->old_heap != NULL && p->old_hend != NULL && + (void *)term < (void *)p->old_hend && + (void *)term >= (void *)p->old_heap) { + erts_fprintf(stderr, "the term is on the old heap\n"); + } + abort(); +} +#endif diff --git a/erts/emulator/beam/jit/beam_jit_common.hpp b/erts/emulator/beam/jit/beam_jit_common.hpp index d11c8768ca..6f6422d460 100644 --- a/erts/emulator/beam/jit/beam_jit_common.hpp +++ b/erts/emulator/beam/jit/beam_jit_common.hpp @@ -659,4 +659,8 @@ Export *beam_jit_handle_unloaded_fun(Process *c_p, bool beam_jit_is_list_of_immediates(Eterm term); bool beam_jit_is_shallow_boxed(Eterm term); +#ifdef DEBUG +void beam_jit_invalid_heap_ptr(Process *p, Eterm term); +#endif + #endif diff --git a/erts/emulator/beam/jit/x86/instr_common.cpp b/erts/emulator/beam/jit/x86/instr_common.cpp index ec609b42d0..d722a19d37 100644 --- a/erts/emulator/beam/jit/x86/instr_common.cpp +++ b/erts/emulator/beam/jit/x86/instr_common.cpp @@ -1078,6 +1078,34 @@ void BeamModuleAssembler::emit_update_record_in_place( } mov_arg(Dst, RET); + +#ifdef DEBUG + if (!all_safe && maybe_immediate.isNil()) { + Label bad_pointer = a.newLabel(), pointer_ok = a.newLabel(); + + /* If p->high_water contained a garbage value, a tuple not in + * the safe part of the new heap could have been destructively + * updated. */ + comment("sanity-checking tuple pointer"); + a.mov(ARG1, x86::Mem(c_p, offsetof(Process, heap))); + a.cmp(RET, HTOP); + a.short_().jae(bad_pointer); + + a.cmp(RET, ARG1); + a.short_().jae(pointer_ok); + + a.bind(bad_pointer); + { + emit_enter_runtime(); + a.mov(ARG1, c_p); + a.mov(ARG2, RET); + runtime_call<2>(beam_jit_invalid_heap_ptr); + emit_leave_runtime(); + } + + a.bind(pointer_ok); + } +#endif } void BeamModuleAssembler::emit_set_tuple_element(const ArgSource &Element, -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor