From d8891c3919f68347ae3fef68b3188bb25a775215 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:35:41 -0700 Subject: [PATCH 1/4] Update branding to 7.0.13 (#92970) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 9fb25e98c63da2..cd94301f9c2fea 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.12 + 7.0.13 7 0 - 12 + 13 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing From d20353e35ca439613dca2939c8b331fd6c68b432 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Mon, 5 Sep 2022 16:16:10 +0200 Subject: [PATCH 2/4] [Mono] Race in init_method when using LLVM AOT. When using LLVM AOT codegen, init_method updates two GOT slots. These slots are initialized as part of init_method, but there is a race between initialization of the two slots. Current implementation can have two threads running init_method for the same method, but as soon as: [got_slots [pindex]] = addr store is visible, it will trigger other threads to return back from init_method, but since that could happen before the corresponding LLVM AOT const slot is set, second thread will return to method calling init_method, load the LLVM aot const, and crash when trying to use it (since its still NULL). This crash is very rare but have been identified on x86/x64 CPU's, when one thread is either preempted between updating regular GOT slot and LLVM GOT slot or store into LLVM GOT slot gets delayed in store buffer. I have also been able to emulate the scenario in debugger, triggering the issue and crashing in the method loading from LLVM aot const slot. Fix change order of updates and make sure the update of LLVM aot const slot happens before memory_barrier, since: got [got_slots [pindex]] = addr; have release semantics in relation to addr and update of LLVM aot const slot. Fix also add acquire/release semantics for ji->type in init_method since it is used to guard if a thread ignores a patch or not and it should not be re-ordered with previous stores, since it can cause similar race conditions with updated slots. --- src/mono/mono/mini/aot-runtime.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 50639c2c397af2..2b65fb1924a08e 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -4633,10 +4633,13 @@ init_method (MonoAotModule *amodule, gpointer info, guint32 method_index, MonoMe * been initialized by load_method () for a static cctor before the cctor has * finished executing (#23242). */ - if (ji->type == MONO_PATCH_INFO_NONE) { - } else if (!got [got_slots [pindex]] || ji->type == MONO_PATCH_INFO_SFLDA) { + MonoJumpInfoType ji_type = ji->type; + LOAD_ACQUIRE_FENCE; + + if (ji_type == MONO_PATCH_INFO_NONE) { + } else if (!got [got_slots [pindex]] || ji_type == MONO_PATCH_INFO_SFLDA) { /* In llvm-only made, we might encounter shared methods */ - if (mono_llvm_only && ji->type == MONO_PATCH_INFO_METHOD && mono_method_check_context_used (ji->data.method)) { + if (mono_llvm_only && ji_type == MONO_PATCH_INFO_METHOD && mono_method_check_context_used (ji->data.method)) { g_assert (context); ji->data.method = mono_class_inflate_generic_method_checked (ji->data.method, context, error); if (!is_ok (error)) { @@ -4646,10 +4649,10 @@ init_method (MonoAotModule *amodule, gpointer info, guint32 method_index, MonoMe } } /* This cannot be resolved in mono_resolve_patch_target () */ - if (ji->type == MONO_PATCH_INFO_AOT_JIT_INFO) { + if (ji_type == MONO_PATCH_INFO_AOT_JIT_INFO) { // FIXME: Lookup using the index jinfo = mono_aot_find_jit_info (amodule->assembly->image, code); - ji->type = MONO_PATCH_INFO_ABS; + ji->type = ji_type = MONO_PATCH_INFO_ABS; ji->data.target = jinfo; } addr = mono_resolve_patch_target (method, code, ji, TRUE, error); @@ -4658,18 +4661,19 @@ init_method (MonoAotModule *amodule, gpointer info, guint32 method_index, MonoMe mono_mempool_destroy (mp); return FALSE; } - if (ji->type == MONO_PATCH_INFO_METHOD_JUMP) + if (ji_type == MONO_PATCH_INFO_METHOD_JUMP) addr = mono_create_ftnptr (addr); - mono_memory_barrier (); - got [got_slots [pindex]] = addr; - if (ji->type == MONO_PATCH_INFO_METHOD_JUMP) - register_jump_target_got_slot (ji->data.method, &(got [got_slots [pindex]])); - if (llvm) { void (*init_aotconst) (int, gpointer) = (void (*)(int, gpointer))amodule->info.llvm_init_aotconst; init_aotconst (got_slots [pindex], addr); } + mono_memory_barrier (); + got [got_slots [pindex]] = addr; + if (ji_type == MONO_PATCH_INFO_METHOD_JUMP) + register_jump_target_got_slot (ji->data.method, &(got [got_slots [pindex]])); } + + STORE_RELEASE_FENCE; ji->type = MONO_PATCH_INFO_NONE; } From 92c652187426434a26fe309eacb3cd3e8bf69938 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Wed, 7 Sep 2022 16:16:45 +0200 Subject: [PATCH 3/4] Move register_jump_target_got_slot above mono_memory_barrier. --- src/mono/mono/mini/aot-runtime.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 2b65fb1924a08e..36558cbdae7714 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -4661,16 +4661,16 @@ init_method (MonoAotModule *amodule, gpointer info, guint32 method_index, MonoMe mono_mempool_destroy (mp); return FALSE; } - if (ji_type == MONO_PATCH_INFO_METHOD_JUMP) + if (ji_type == MONO_PATCH_INFO_METHOD_JUMP) { addr = mono_create_ftnptr (addr); + register_jump_target_got_slot (ji->data.method, &(got [got_slots [pindex]])); + } if (llvm) { void (*init_aotconst) (int, gpointer) = (void (*)(int, gpointer))amodule->info.llvm_init_aotconst; init_aotconst (got_slots [pindex], addr); } mono_memory_barrier (); got [got_slots [pindex]] = addr; - if (ji_type == MONO_PATCH_INFO_METHOD_JUMP) - register_jump_target_got_slot (ji->data.method, &(got [got_slots [pindex]])); } STORE_RELEASE_FENCE; From e019f9da287bf15b2d52eea3a25ec8c2a397d6fe Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Thu, 5 Oct 2023 10:03:54 -0400 Subject: [PATCH 4/4] revert unintentional branding change --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index cd94301f9c2fea..9fb25e98c63da2 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 7.0.13 + 7.0.12 7 0 - 13 + 12 7.0.100 6.0.$([MSBuild]::Add($(PatchVersion), 11)) servicing