From aabcd6b399222410b3c1eef94415b0911b879aa6 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 30 Aug 2022 16:49:59 -0400 Subject: [PATCH] runtime_loader: Correct destruction of old TLS DSO blocks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of checking against the current block's DSO generation, the DSO that the operator[] was invoked on was being checked instead. This could lead to spurious deletions of TLS data in the case where the generation count changed between accesses of the TLS variable (currently that only happens when modules are unloaded.) May fix #17896, but I did not have a reliable way to reproduce that. Change-Id: Ie1ee51c1fbbe638918fd5a010047a2b56d481f2b Reviewed-on: https://review.haiku-os.org/c/haiku/+/5604 Tested-by: Commit checker robot Reviewed-by: waddlesplash Reviewed-by: Jérôme Duval --- src/system/runtime_loader/elf_tls.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/system/runtime_loader/elf_tls.cpp b/src/system/runtime_loader/elf_tls.cpp index fbef3f6e36..4b587affef 100644 --- a/src/system/runtime_loader/elf_tls.cpp +++ b/src/system/runtime_loader/elf_tls.cpp @@ -235,11 +235,13 @@ DynamicThreadVector::operator[](unsigned dso) { unsigned generation = TLSBlockTemplates::Get().GetGeneration(-1); if (_Generation() < generation) { - for (unsigned i = 0; i < _Size(); i++) { - TLSBlock& block = (*fVector)[i + 1]; + // We need to destroy any blocks whose DSO generation has changed + // to be greater than our own generation. + for (unsigned dsoIndex = 0; dsoIndex < _Size(); dsoIndex++) { + TLSBlock& block = (*fVector)[dsoIndex + 1]; unsigned dsoGeneration - = TLSBlockTemplates::Get().GetGeneration(dso); - if (_Generation() < dsoGeneration && dsoGeneration <= generation) + = TLSBlockTemplates::Get().GetGeneration(dsoIndex); + if (dsoGeneration > _Generation() && dsoGeneration <= generation) block.Destroy(); } @@ -257,7 +259,7 @@ DynamicThreadVector::operator[](unsigned dso) status_t result = block.Initialize(dso); if (result != B_OK) return fNullBlock; - }; + } return block; }