// Copyright 2023 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_GWP_ASAN_CLIENT_THREAD_LOCAL_STATE_H_ #define COMPONENTS_GWP_ASAN_CLIENT_THREAD_LOCAL_STATE_H_ #include "base/check.h" #include "base/compiler_specific.h" #include "build/build_config.h" #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID) // On macOS and Android (before Q), the first use of a `thread_local` variable // on a new thread will cause an allocation, leading to infinite recursion. // Also, `thread_local` goes through `emutls` on Android, which is slower than // `pthread_getspecific`. #define THREAD_LOCAL_STATE_USES_PARTITION_ALLOC_TLS #elif BUILDFLAG(IS_POSIX) && defined(COMPONENT_BUILD) // On POSIX platforms when built as component build, use of a `thread_local` // variable may or may not cause a call to `free()` depending on an // implementation of TLS. At least in case of glibc/glibc/elf/dl-tls.c, // `_dl_update_slotinfo()` calls `free()` (as of Apr 2024). // // This is a problem for LUD (Lightweight UaF Detector) and ELUD (Extreme LUD) // as they call `SamplingState::Sample()` inside `free()`, which leads to // infinite recursion. (See also https://crbug.com/332234169) // // Fortunately, statically-linked executables (non-component builds) do not hit // the problem because they use the "local-exec" model of TLS (i.e. do not call // any library function). #define THREAD_LOCAL_STATE_USES_PARTITION_ALLOC_TLS #endif #if defined(THREAD_LOCAL_STATE_USES_PARTITION_ALLOC_TLS) #include "partition_alloc/partition_tls.h" #endif namespace gwp_asan::internal { // Class that provides the optimal thread-local storage implementation depending // on the platform. template <typename T> class ThreadLocalState { … }; #if !defined(THREAD_LOCAL_STATE_USES_PARTITION_ALLOC_TLS) template <typename T> thread_local uintptr_t ThreadLocalState<T>::state_ = 0; #else template <typename T> partition_alloc::internal::PartitionTlsKey ThreadLocalState<T>::tls_key_ = …; #endif } // namespace gwp_asan::internal #endif // COMPONENTS_GWP_ASAN_CLIENT_THREAD_LOCAL_STATE_H_