A multi-threaded TLS synchronization method for heterogeneous closed-source driven fusion operation
By constructing a B-TLS substructure within the Linux kernel thread structure, full lifecycle management of Android Bionic TLS is achieved, resolving the synchronization issues of high-version Android Bionic libraries in multi-threaded environments and enabling seamless adaptation of libhybris to high-version Android.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- 北京麟卓信息科技有限公司
- Filing Date
- 2026-05-22
- Publication Date
- 2026-06-19
Smart Images

Figure CN122240349A_ABST
Abstract
Description
Technical Field
[0001] This invention belongs to the field of computer software development technology, specifically relating to a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration. Background Technology
[0002] libhybris serves as a core compatibility layer connecting non-Android Linux systems with the Android Hardware Abstraction Layer (HAL), such as PostMarketOS and Sailfish OS. Its core function is to enable Glibc-based Linux systems to call Android HAL drivers that depend on the Bionic library, such as camera, GPU, and sensor drivers. However, higher versions of the Android Bionic library have undergone architectural upgrades to the implementation of Thread Local Storage (TLS), introducing three key changes: first, a compact TLS layout is adopted, storing thread metadata and private variables together in the same contiguous memory block; second, the dynamic expansion mechanism is deeply bound to the Bionic memory pool, Bionic_tls_pool; and third, thread inheritance logic depends on private fields in the pthread structure, such as tls_generation for version control and tls_key_data for key management.
[0003] The aforementioned changes conflict with Glibc's POSIX-compliant separate TLS layout and independent memory management model at the underlying architecture level, leading to four core problems in libhybris under multi-threaded environments:
[0004] First, there is the issue of metadata loss and address misalignment during TLS inheritance. In Bionic, child threads need to inherit the context snapshot from the parent thread's TLS, such as sensor calibration parameters and GPU session handles. This inheritance process relies on the TLS base address tls_ptr, total size tls_size, and TLS destructor list tls_dtor_list in the pthread structure. However, Glibc's pthread_create only copies its own TLS space and cannot recognize Bionic's private metadata. Furthermore, it does not handle the differences in ARM register mappings, causing the HAL driver to trigger a segmentation fault after the child thread starts by accessing uninitialized TLS variables such as __thread int camera_fd or registers pointing to incorrect addresses.
[0005] Second, there are address calculation errors and memory overflows during dynamic expansion. Higher versions of Bionic, when dynamically expanding the TLS space via `__tls_alloc`, must meet double alignment rules: 16-byte alignment at the variable level and 4KB page alignment at the block level. Furthermore, the expanded address must be updated to the `tls_end` field of the pthread structure. Glibc's expansion logic `_dl_allocate_tls` only meets basic alignment and does not update Bionic's private fields. In addition, the existing solution lacks hardware-level boundary checks, leading to deviations in TLS variable address calculations when the HAL driver dynamically loads modules such as `libcamera2.so`. For example, the expected offset of 0x100 may actually point to 0x108, thus causing memory overflows.
[0006] Third, there is state tearing and cache inconsistency during thread scheduling. In the ARM platform, the TLS address is associated through the user-space TLS pointer TPIDR_EL0. Before thread switching, Bionic updates the version number tls_generation of the pthread structure to mark the state change. The Linux kernel scheduler is unaware of this field and does not handle cache consistency issues during cross-CPU scheduling. Therefore, when a thread is preempted and then resumes, it may use an old version of the TLS address because tls_generation has not been synchronized, or the CPU cache may retain old TLS data, causing the HAL driver to read outdated TLS data, such as old readings from sensor caches.
[0007] Fourth, the resource leakage chain and destruction order are disordered during thread destruction. Bionic's TLS destructor chain __tls_dtor_list follows the reverse execution rule of registering last and releasing first, and is used to release hardware resource handles such as camera and GPU frame buffer; while Glibc's pthread_exit only executes its own destructor and does not handle resource contention when multiple threads destroy concurrently, which ultimately leads to the hardware resources held by TLS not being released properly, causing device occupation conflicts, such as subsequent threads being unable to open the camera.
[0008] In summary, the existing libhybris solution only achieves surface interface simulation through symbol redirection, such as replacing __tls_get_addr, without addressing the underlying mechanism differences mentioned above. Furthermore, it lacks hardware-assisted verification and register depth adaptation, ultimately resulting in a less than 30% success rate in adapting to Android 12 and above. Summary of the Invention
[0009] In view of this, the present invention provides a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration. By constructing a kernel-user space collaborative TLS context synchronization, version verification and cache consistency mechanism, it solves the synchronization problem of Bionic library TLS in multi-threaded environment in high version Android, and realizes seamless adaptation of libhybris to high version Android.
[0010] This invention provides a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration, which specifically includes the following steps:
[0011] A B-TLS substructure is constructed in the Linux system kernel thread structure to record the user-space pointer and data block length of B-TLS metadata, and an atomic reference count is established to track the lifecycle of TLS metadata.
[0012] The system starts the libhybris compatibility related compatibility process, creates an address space and main thread for it and records it as the source thread; after the compatibility layer runs, it sets the in-process TLS virtual memory region feature identifier, registers the initial TLS configuration and adds it to the process address space management structure, allocates the Linux native G-TLS space and the Android private B-TLS space for the source thread, initializes the B-TLS substructure of the kernel thread descriptor and configures the ARM architecture TLS dedicated register.
[0013] When the source thread creates a child thread, it calculates the required B-TLS space for the child thread based on the source thread's B-TLS substructure; it allocates a kernel thread descriptor, B-TLS substructure, and user-space B-TLS space for the child thread and binds a hardware security label; it copies the source thread's TLS data and metadata; it corrects the metadata pointer offset, updates the version identifier; it initializes the atomic reference count and the number of destructors, and then returns to user space; after the child thread starts, the compatibility layer configures dual TLS dedicated registers, initializes the global hash shadow table, allocates bitmaps, and sets up concurrency control mechanisms, thus activating the child thread.
[0014] When a thread calls a module to initiate a B-TLS allocation request during thread execution, it allocates a free region according to the alignment rules and returns a valid address. During thread scheduling, the kernel completes B-TLS context saving and restoration, dirty data marking, and version synchronization verification. When a compatible thread is deregistered, the destructor is executed in reverse registration order and module dependency topology order, releasing user-mode resources and resetting hardware registers layer by layer. After atomically decrementing the reference count to no references, kernel resources are reclaimed and the B-TLS substructure is cleared.
[0015] Furthermore, the B-TLS substructure is aligned to the ARM64 hardware cache line and records the thread type identifier, number of destructors, hardware security label, TLS version number, base address, total size, and end offset of the allocated area of the thread's B-TLS space associated with the libhybris compatibility layer.
[0016] Furthermore, when the calling module initiates a B-TLS allocation request, it acquires an exclusive lock on the B-TLS context of the current thread, parses the executable file information of the calling module to locate the TLS segment, extracts the required memory size and alignment requirements from it, and uses the larger of the alignment requirements and the hardware security tag granularity as the actual alignment requirement; it traverses the thread TLS allocation bitmap, uses a standard adaptation algorithm to find the first free region that meets the size and alignment requirements, if it exists, it calculates the starting offset and marks the corresponding bit in the allocation bitmap, otherwise it triggers B-TLS space expansion, updates the bitmap and searches again.
[0017] Furthermore, the method for expanding the B-TLS space is as follows:
[0018] According to the thread's preset expansion strategy, the new size of the B-TLS space after expansion is the product of the original space size and the expansion coefficient, and the expansion coefficient is dynamically decayed; if the maximum number of expansions is exceeded, the allocation failure is returned; if the maximum space allowed at runtime is exceeded, the upper limit is truncated.
[0019] Allocate a new virtual memory space that meets read / write and hardware security features through the memory mapping interface, and assign an independent hardware security label to the new B-TLS space; copy the business data and management metadata of the old space to the new space; traverse the allocated module information, reallocate and bind new hardware security labels to all B-TLS blocks, and update the space end address in the management metadata.
[0020] The kernel is notified to update the B-TLS space base address, total size, and hardware security label; the ARM architecture TLS dedicated registers are updated; and the new B-TLS base address, version number, and hardware label filtering configuration are synchronized. The old memory space and corresponding hardware security label are safely released, and system resources are reclaimed.
[0021] Furthermore, when a thread yields the processor, if the current thread is a compatible thread, the kernel saves the values of the B-TLS related hardware registers to the B-TLS substructure of the kernel thread descriptor, including the base address register, version number register, and hardware security tag register; at the same time, it performs verification and comparison of the TLS space, and sets a dirty data flag if the data has changed; when the thread is rescheduled for execution, if it is a compatible thread, the kernel restores the B-TLS hardware context from the kernel thread descriptor and rewrites the base address, version number, and hardware security tag into the corresponding registers; if it detects that the B-TLS space data has been tampered with, it sends a signal to the user-mode compatibility layer to trigger cache refresh and security verification.
[0022] Furthermore, during the thread activation phase, PMU events are configured to enable data access anomaly monitoring capabilities, and hardware counters are enabled to statistically analyze abnormal access behavior in the TLS space in real time. The kernel registers PMU exception handling functions, and when the hardware detects illegal access, the exception handling process is automatically triggered. The kernel creates debug nodes to record the number of exceptions, fault addresses, and thread IDs.
[0023] Furthermore, when the hardware detects that the B-TLS space data has been tampered with, it sends a signal to the user-space compatibility layer to trigger cache refresh and security verification. Specifically, when the kernel detects changes to the B-TLS space data or version inconsistencies, it sends a kernel synchronization signal to the user space. Upon receiving the signal, the user space uses concurrency lock protection to compare the current version with the kernel version. If they are inconsistent, TLS access is suspended, and the latest base address, version number, and hardware register state are synchronized from the kernel. The B-TLS management structure address information is corrected to ensure consistency between the kernel-space and user-space states. If synchronization fails, thread restart is executed.
[0024] Furthermore, when a thread is switched in, the kernel determines whether the CPU core has migrated before and after the scheduling. If cross-CPU scheduling occurs, it sends a cache refresh signal to user space. The user space signal handler uses hardware instructions to force refresh the data cache, invalidate the instruction cache, and clear the hardware security tag cache, so that the TLS data and tags accessed by the thread on the new CPU core are the latest valid values.
[0025] Furthermore, the method of releasing user-mode resources layer by layer is as follows: unload dynamic modules in sequence, reclaim hardware security tags for each TLS block, clear the allocation bitmap; release the entire B-TLS space and reclaim hardware security tags.
[0026] Furthermore, the method for initializing the global hash shadow table is as follows: based on the allocated records of the parent thread, initialize the allocation bitmap, set the used area to a valid mark, and set the unused area to an idle mark; initialize the space expansion strategy according to the target runtime specification, configure the expansion coefficient and the maximum number of expansions; set the allocation state machine to an idle state, and complete the initialization of the concurrent safe read-write lock.
[0027] Beneficial effects:
[0028] This invention adds a B-TLS substructure to the Linux kernel thread structure, enabling the kernel to manage the entire lifecycle of the Android Bionic TLS context. It starts a libhybris compatible process and creates a main thread as the source thread. The compatibility layer parses relevant configuration information, allocates Linux native G-TLS space and Android private B-TLS space respectively, initializes the B-TLS substructure, and configures ARM architecture TLS-specific registers. The source thread creates a child thread through a cloning system call. After verifying the process compatibility flag, the kernel allocates a dedicated B-TLS space and kernel management structure for the child thread according to hardware rules, synchronously copies the parent thread's TLS data and metadata, and completes version and reference count initialization. The user-space compatibility layer initializes the global hash shadow table, allocation bitmap, expansion strategy, and concurrency mechanism, configures dual TLS registers, and completes metadata relocation and other initializations to activate the child thread. During thread execution, when a calling module initiates a B-TLS allocation request, it parses the ELF TLS segment by locking to determine the actual... The kernel allocates free areas according to the alignment specifications and binds them with independent hardware security tags. After synchronizing the kernel state, it returns a valid address to complete the dynamic allocation of B-TLS. When switching threads, the kernel saves and verifies the B-TLS hardware register context when the compatible thread yields the processor, and restores the hardware context when the thread is rescheduled and switched back in. When the compatible thread is deregistered, the TLS destructor is executed in reverse registration order combined with the topological sorting of calling module dependencies. User-mode resources are released layer by layer, hardware registers are reset, and the global shadow table is cleared. On the kernel side, the metadata reference count is decremented, the kernel cache and TLS virtual memory area are released after the reference count reaches zero, the B-TLS substructure is cleared, and the statistics log is updated. This achieves orderly and residue-free reclamation of B-TLS resources in user-mode and kernel-mode, solves the synchronization problem of Bionic library TLS in multi-threaded environments in high-version Android, and achieves seamless adaptation of libhybris to high-version Android. Attached Figure Description
[0029] Figure 1 This is a flowchart illustrating a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration provided by the present invention. Detailed Implementation
[0030] The present invention will be described in detail below with reference to the accompanying drawings and embodiments.
[0031] This invention provides a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration. Its core idea is as follows: A B-TLS substructure is added to the Linux kernel thread structure to achieve full lifecycle management of the Android Bionic TLS context by the kernel. A libhybris compatible process is started, and a main thread is created as the source thread. The compatibility layer parses relevant configuration information, allocates Linux native G-TLS space and Android private B-TLS space respectively, initializes the B-TLS substructure, and configures ARM architecture TLS-specific registers. The source thread creates a child thread through a cloning system call. After the kernel verifies the process compatibility identifier, it allocates the child thread's dedicated B-TLS space and kernel management structure according to hardware rules, synchronously copies the parent thread's TLS data and metadata, and completes version and reference count initialization. The user-mode compatibility layer initializes the global hash shadow table, allocation bitmap, expansion strategy, and concurrency mechanism, configures dual TLS registers, and completes metadata relocation and other initializations to activate the child thread. During thread execution, when the calling module initiates a B-TLS allocation request, it parses the ELF TLS segment by locking, determines the actual alignment specification, allocates a free area, binds an independent hardware security label, synchronizes the kernel state, and returns a valid address, completing the B-TLS synchronization. S is dynamically allocated; during thread scheduling and switching, the kernel saves and verifies the B-TLS hardware register context when the compatible thread yields the processor, and restores the hardware context when the thread is rescheduled and switched in; when the compatible thread is deregistered, the TLS destructor is executed in reverse registration order combined with the topological sorting of calling module dependencies, releasing user-mode resources, resetting hardware registers, and clearing the global shadow table layer by layer. On the kernel side, the metadata reference count is decremented, the kernel cache and TLS virtual memory area are released after the reference count reaches zero, the B-TLS substructure is cleared and the statistics log is updated, so as to achieve orderly and residue-free reclamation of B-TLS resources in user mode and kernel mode.
[0032] This invention provides a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration, the processing flow of which is as follows: Figure 1 As shown, the specific steps include:
[0033] Step 1: Add a B-TLS substructure to the Linux system kernel thread structure. This substructure is used to track, inherit, and manage the Android Bionic TLS context of the libhybris compatibility layer. It adopts ARM64 hardware cache line alignment and records the thread type identifier, number of destructors, hardware security label, TLS version number, base address, total size, and offset of the allocated region end of the thread's Bionic TLS virtual memory space (referred to as the B-TLS space). It also records the user-mode pointer and data block length of the corresponding B-TLS metadata to ensure that the kernel can fully perceive and manage the TLS context. At the same time, it adds atomic reference counting of TLS metadata to track the lifecycle of TLS metadata.
[0034] The B-TLS space corresponds to the user-mode pointer of B-TLS metadata, which points to the TLS metadata block in the user-mode thread structure struct pthread of the thread. This block stores B-TLS metadata such as the TLS version number, the TLS destructor list, and the TLS data storage area. It is used by the kernel to implement the inheritance, version synchronization, destructor management, and key adaptation of B-TLS metadata.
[0035] Step 2: The system starts the libhybris compatibility layer associated process, i.e., the compatibility process. The kernel creates the address space and main thread of the compatibility process through the program loading mechanism, and records the main thread as the source thread. After the compatibility layer runs, it parses the ELF tags embedded in its own library to obtain the Bionic version compatibility range, ARM architecture version, and hardware security capability identifier. It sets exclusive feature identifiers for the TLS-related virtual memory areas in the process and registers the process version information and initial TLS configuration size with the kernel. The kernel records the compatibility process attributes in the process address space management structure. The compatibility layer allocates Linux native Glibc TLS virtual memory space for the source thread, denoted as G-TLS space, and Android Bionic's private B-TLS space. It initializes the B-TLS substructure in the kernel thread descriptor, recording the B-TLS space base address, capacity, hardware security label, TLS version number, and metadata information. Then, through the ARM architecture TLS dedicated register configuration, it completes the hardware mapping and environment activation of the dual TLS spaces, enabling the source thread to have the runtime context of the compatibility layer and the ability to derive child threads of the same type.
[0036] The system initializes the compatibility layer. When the compatibility layer module is loaded, the system obtains the link entry of the TLS allocation and address resolution interface at runtime through dynamic linking, injects the custom processing logic into the link table, and uses preloading and symbol priority strategies to ensure that the custom logic is executed before the native interface, thus making global preparations for TLS allocation interception at thread runtime.
[0037] Step 3: When the source thread creates a child thread using the Linux underlying cloning system call, during the task copying phase, the kernel first verifies the compatibility flag in the parent process's process address space management structure. After determining that it is a libhybris compatible process, it obtains the B-TLS space base address, metadata, TLS version number, and hardware security label from the source thread's B-TLS substructure, and caches them in the kernel's temporary context. It then calculates the B-TLS space required by the child thread according to the hardware alignment and expansion rules. The total size of this B-TLS space is the sum of the parent thread's B-TLS space size and the reserved expansion space.
[0038] After the kernel completes the cloning operation, it allocates an independent kernel thread descriptor and a dedicated B-TLS substructure to the newly created child thread, allocates a dedicated user-space B-TLS space and binds a hardware security label; it synchronously copies the parent thread's TLS data and metadata cached by the kernel to the child thread's B-TLS space, corrects the B-TLS metadata pointer offset, updates the TLS version identifier, and initializes the TLS metadata atomic reference count and destructor count record, and then returns to user space.
[0039] When the child thread starts running, the compatibility layer first constructs and initializes the global hash shadow table and concurrent security allocation state machine of Bionic TLS metadata, and completes the initialization of thread-level bitmap, expansion strategy, state machine and read-write lock. On this basis, it completes the dynamic mapping of dual TLS registers of ARM architecture, reads and configures the dedicated registers corresponding to G-TLS space and B-TLS space respectively, completes metadata relocation, thread-specific security key adaptation and destructor linked list and concurrent protection mechanism initialization, and activates the child thread.
[0040] Furthermore, after the kernel determines that it is a libhybris compatible process, it first avoids multi-threaded concurrent competition through a synchronization and mutual exclusion mechanism.
[0041] The global hash shadow table of Bionic TLS metadata, built and initialized in the compatibility layer, uses thread identifiers as keys. Each entry maintains a TLS space allocation bitmap, a module TLS information array, an automatic space expansion strategy, an allocation state machine, and a concurrent secure read-write lock. This enables state tracking and concurrent control of thread TLS allocation. Specifically, the allocation bitmap records the position of allocated blocks in the TLS space, with each bit corresponding to a fixed-length allocation unit, adapting to the target runtime's minimum allocation granularity and hardware security tag granularity. The module TLS information array stores TLS-related information for each dynamic module, including module identifier, allocation block start offset, size, alignment requirements, associated version information, and corresponding hardware security tags. The expansion strategy parameters include expansion coefficient, maximum expansion count, and next expansion threshold, used to control the automatic expansion behavior of the TLS space. The allocation state machine identifies the current TLS allocation state to avoid multi-threaded concurrent allocation conflicts. The concurrent secure read-write lock ensures the concurrent read-write security of the global hash shadow table in a multi-threaded environment.
[0042] Furthermore, after the thread is created, the TLS metadata shadow table of the current thread is initialized during the user-mode activation phase: the allocation bitmap is initialized according to the allocated records of the parent thread, the used areas are marked as valid, and the unused areas are marked as idle; the space expansion strategy is initialized according to the target runtime specification, and core parameters such as expansion coefficient and maximum expansion count are configured; the allocation state machine is set to idle state, and the concurrent safe read-write lock is initialized.
[0043] Step 4: During thread execution, when the calling module initiates a B-TLS space allocation request, an exclusive lock is acquired on the current thread's B-TLS context. The executable file information of the calling module is parsed to locate the TLS segment, and the required memory size and alignment requirements are extracted from it. The larger of the alignment requirements and the hardware security tag granularity is used as the actual alignment requirement. The thread's TLS allocation bitmap is traversed, and the standard adaptation algorithm is used to find the first free region that meets the size and alignment requirements. If it exists, the starting offset is calculated and the corresponding bit in the allocation bitmap is marked. Otherwise, the B-TLS space is expanded, the bitmap is updated, and the search is repeated.
[0044] Assign an independent hardware security label to the newly allocated B-TLS memory block and complete the memory region label binding through hardware instructions; record the calling module handle, starting offset, memory size and security label of this allocation in the TLS management structure, and simultaneously update the kernel-mode TLS allocation status through the kernel communication interface; calculate the absolute effective address of the allocated region based on the B-TLS space base address and allocation offset, release the concurrency lock, and return the address to the calling module to complete a B-TLS dynamic allocation.
[0045] Among them, the calling module consists of various Android dynamic link libraries and business components that initiate Bionic TLS space allocation requests during runtime. The compatibility layer locates the ELF segment attributes of the calling module through dynamic link information, and then parses its TLS memory size and alignment constraints.
[0046] Furthermore, the method for expanding the B-TLS space is as follows:
[0047] Step 4.1: According to the thread's preset expansion strategy, the new size of the B-TLS space after expansion is the product of the original space size and the expansion coefficient, and the expansion coefficient is dynamically decayed to control the memory growth rate and avoid excessive memory allocation; at the same time, a validity check is performed. If the maximum number of expansions is exceeded, the allocation failure is returned; if the maximum space allowed at runtime is exceeded, the upper limit is truncated.
[0048] Step 4.2: Allocate a new virtual memory space that meets the read / write and hardware security features through the memory mapping interface, mark the new memory region to support hardware tag verification capability, allocate an independent hardware security tag for the new B-TLS space, isolate it from the old space tag, and prevent cross-access conflicts.
[0049] Step 4.3: Use the secure copy function with hardware tag verification to completely copy the business data and management metadata of the old space to the new space; traverse the allocated module information, reallocate and bind new hardware security tags for all B-TLS blocks; update the space end address in the management metadata to keep it consistent with the target runtime structure;
[0050] Step 4.4: Notify the kernel via the kernel communication interface to update the B-TLS space base address, total size, and hardware security label to ensure kernel state synchronization; update the ARM architecture TLS dedicated registers to synchronize the new B-TLS base address, version number, and hardware label filtering configuration; securely release the old memory space and corresponding hardware security label, and reclaim system resources.
[0051] Furthermore, hardware label isolation bands are established between the allocation blocks in the new space, and dedicated unallocated labels are used for marking. When a calling module illegally accesses the isolation band, the ARM MTE hardware triggers a segmentation fault signal in real time. The compatibility layer parses the error address through the registered exception handling function, locates the out-of-bounds access behavior, and outputs detailed TLS block boundary and illegal address information to realize problem location and debugging.
[0052] Furthermore, to enhance TLS access security, an ARM Performance Monitoring Unit (PMU) is introduced to achieve hardware-level real-time access monitoring and anomaly detection. The specific process is as follows:
[0053] Configure PMU events during the thread activation phase to enable data access anomaly monitoring capabilities and start a hardware counter to collect real-time statistics on abnormal access behavior in the TLS space; register PMU exception handling functions in the kernel, and automatically trigger the exception handling process when the hardware detects illegal access such as TLS space out-of-bounds or tag mismatch; the kernel creates debug nodes to record the number of exceptions, fault addresses and thread IDs, and user-space tools can read the monitoring data in real time to achieve observable, traceable and debuggable TLS access behavior.
[0054] The exception handling process is as follows: read the hardware exception information and fault address, and verify whether the address belongs to the TLS space; if it is determined to be an illegal access, send an exception signal to the user space and terminate the illegal process to achieve security interception.
[0055] Step 5: When a thread yields the processor, if the current thread is a compatible thread, the kernel saves the values of the B-TLS related hardware registers to the B-TLS substructure of the kernel thread descriptor, including the base address register, version number register, and hardware security tag register; at the same time, it performs verification and comparison on the TLS space, and sets a dirty data flag if the data has changed.
[0056] When a thread is rescheduled for execution, if it is a compatible thread, the kernel restores the B-TLS hardware context from the kernel thread descriptor and rewrites the base address, version number, and hardware security label into the corresponding registers; if B-TLS space data is detected to have been tampered with, a signal is sent to the user-space compatibility layer to trigger cache refresh and security verification.
[0057] Specifically, a signal is sent to the user-space compatibility layer to trigger cache refresh and security verification. When the kernel detects changes in B-TLS space data or version inconsistencies, it sends a kernel synchronization signal to user space. Upon receiving the signal, user space uses a concurrency lock for protection and compares the current version with the kernel version. If they are inconsistent, TLS access is suspended, and the latest base address, version number, and hardware register status are synchronized from the kernel. The B-TLS management structure address information is corrected to ensure consistency between kernel space and user space. If synchronization fails, thread restart is performed to ensure system stability.
[0058] Furthermore, to address the cache inconsistency issue caused by cross-CPU thread scheduling, the kernel determines whether the CPU core has migrated before and after the thread is switched in. If cross-CPU scheduling occurs, a cache refresh signal is sent to user space. The user-space signal handler uses hardware instructions to force refresh the data cache, invalidate the instruction cache, and clear the hardware security tag cache, ensuring that the TLS data and tags accessed by the thread on the new CPU core are the latest valid values, thus avoiding access errors caused by caching old data.
[0059] Step 6: When a compatible thread is deregistered, the destructor of Bionic TLS is extracted in reverse registration order. The dependencies between calling modules are analyzed, and the execution order is adjusted through topological sorting. Hardware security tags are verified before the destructor is executed. Exceptions are caught and resources are forcibly released during the execution of the destructor. After the destructor is executed, user-mode resources are released layer by layer, ARM architecture hardware registers are reset, and the global management shadow table is cleared to achieve complete reclamation of user-mode resources. When a thread enters the kernel cleanup process, the reference count is atomically decremented and waits until there are no references. The kernel cache is released, the virtual memory area corresponding to TLS is reclaimed, and the B-TLS substructure in the kernel thread descriptor is cleared. System monitoring statistics are updated and logs are recorded to achieve cleanup of kernel-mode resources without any residue.
[0060] The process of releasing user-space resources layer by layer after the destructor execution is as follows: unload dynamic modules sequentially, reclaim hardware security tags for each TLS block, clear the allocation bitmap, release the entire B-TLS space, and reclaim hardware security tags. The dependencies between calling modules represent the sequential constraints between different dynamic library components in the resource destruction and destruction process.
[0061] Example:
[0062] This embodiment employs a multi-threaded TLS synchronization method for heterogeneous closed-source driver integration provided by the present invention. Targeting ARMv8-A and later versions of the ARM architecture platform, it addresses the synchronization issues of the Bionic library's TLS in multi-threaded environments in high-version Android (Android 10 and later) by adapting to the Linux kernel thread lifecycle management module, the libhybris TLS adaptation layer, and the ARM hardware register mapping and verification mechanism. This includes precise inheritance of TLS metadata during thread creation, hardware-level alignment for dynamic runtime expansion, state consistency verification during thread scheduling, and cascading resource release during thread destruction. The specific process includes:
[0063] S1. Precise inheritance of bionic TLS metadata and dual TLS mapping during thread creation: By modifying the Linux kernel thread creation process, libhybris initialization logic, and ARM register operations, the system achieves byte-level copying and address relocation of bionicTLS metadata from the parent thread to the child thread, as well as hardware-level mapping of the dual TLS space.
[0064] S1.1 Extending Linux kernel thread descriptors and concurrency safety mechanisms.
[0065] A new `bionic_tls` substructure is added to the kernel `task_struct` structure `include / linux / sched.h`, employing a 64-byte cache line alignment design for ARM64, and includes:
[0066] base: User-space bionic TLS base address, unsigned long, 64-bit aligned;
[0067] size: The total size of TLS is size_t, 32-bit aligned;
[0068] alloc_ptr: The current allocated offset size_t, which is the same as size;
[0069] meta_ptr: The address of the TLS metadata block in the user-space struct pthread, unsigned long, pointing to the region containing tls_generation, tls_dtor_list, and tls_key_data;
[0070] meta_size: Metadata block size size_t, records the total length of TLS-related fields in struct pthread, such as 256 bytes in Android 14;
[0071] is_bionic: Thread type flag, bool, 1 byte, to avoid wasting cache lines;
[0072] generation: TLS version number, uint32_t, tls_generation of the synchronization struct pthread;
[0073] dtor_count: Number of destructors, uint16_t, used for reverse-order triggering during the destruction phase;
[0074] mte_tag: MTE tag, uint8_t, used for hardware-level boundary checks.
[0075] Added kernel-mode concurrency safety mechanism:
[0076] Initialize a spinlock `spinlock_t bionic_tls_lock` (specifically in `kernel / locking / spinlock.c`) to protect concurrent access to the `bionic_tls` structure during multi-threaded creation; add a `bionic_tls_ref(atomic_t)` to `task_struct` to record the reference count of TLS metadata and avoid resource contention during concurrent destruction.
[0077] S1.2. Inject two-phase hooks and concurrency protections inherited from bionic TLS into the clone system call.
[0078] Modify the sys_clone system call handling logic of ARM64 in arch / arm64 / kernel / syscall.c, add two hooks before and after copy_process, and add spinlock protection.
[0079] The pre-copy hook includes:
[0080] Call spin_lock(&bionic_tls_lock) to acquire a lock and prevent metadata contention during concurrent creation by multiple threads;
[0081] Check if the parent thread's task_struct->bionic_tls.is_bionic is true; otherwise, unlock and skip.
[0082] The kernel access process_vm interface for accessing user-space memory reads TLS data from the parent thread: It reads `size` bytes of TLS variable data from `bionic_tls.base`, stores it in a kernel temporary buffer, `bionic_tls_cache` allocated by `kmem_cache_alloc`, dynamically adapting to the size and aligned to MTE tag granularity; it reads `meta_size` bytes of metadata from `bionic_tls.meta_ptr`, including `tls_generation`, `tls_dtor_list`, and `tls_key_data`, and stores it in the metadata partition of `bionic_tls_cache`; and it reads `bionic_tls.mte_tag` from the parent thread for tag inheritance in the child thread's TLS space.
[0083] Calculate the TLS space requirement for child threads: Total size = Parent thread size + Reserved expansion space. The reserved expansion space is usually 20% of the parent thread size, which is used for independent allocation by child threads, and ensures that the total size is an integer multiple of the MTE tag block size, i.e., an integer multiple of 16 bytes.
[0084] Call spin_unlock(&bionic_tls_lock) to unlock.
[0085] Post-copy hook:
[0086] Call spin_lock(&bionic_tls_lock) to acquire the lock;
[0087] Allocate user-mode TLS space for child threads: Allocate contiguous memory through the kernel-mode memory mapping function vm_mmap, set permissions to PROT_READ|PROT_WRITE|PROT_MTE to enable MTE support, and set address preference to the sum of the parent thread's TLS address and 2MB to avoid address conflicts; call madvise to set MADV_MTE_TAGGED on the new space to mark the region as supporting the MTE tag;
[0088] Allocate MTE tag: Allocate a unique tag for the new space using the tag allocation function mte_allocate_tag provided by the ARM kernel, and write it to the child thread bionic_tls.mte_tag;
[0089] Copying data to the child thread space: The memory copy function memcpy_mte with MTE tag checking is used to copy the TLS variable data and metadata in bionic_tls_cache to the new space, ensuring byte-level consistency and tag matching; the bionic TLS key tls_key_data in the metadata is re-encrypted, and the child thread's mte_tag is used as an auxiliary key to avoid key leakage;
[0090] Initialize the child thread's `bionic_tls` fields: `base` is the new memory address, `size` is the pre-calculated total size, `alloc_ptr` is the parent thread's `alloc_ptr`; `meta_ptr` is the new memory address + parent thread's `meta_ptr` - parent thread's `base`, correcting the offset of the metadata block in the child thread's memory; `meta_size`, `generation`, and `dtor_count` are consistent with the parent thread, where `generation` is incremented by 1 to mark the child thread as the new version; `is_bionic = true`, `mte_tag = newly allocated MTE tag`;
[0091] The atomic operation `atomic_inc(&bionic_tls_ref)` increments the reference count.
[0092] Call spin_unlock(&bionic_tls_lock) to unlock.
[0093] S1.3 Implement the identity identification and initialization anchoring of the libhybris process.
[0094] A new module, hybris_bionic_anchor.c, was added to libhybris. This module, located in src / anchor / anchor.c, uses a triple mechanism to identify processes, ensuring accurate kernel recognition.
[0095] ELF tag: Embed a custom ELF segment in libhybris.so of libhybris. It is of type SHT_NOTE and named .note.hybris_bionic. It records the bionic version compatibility range, such as Android 10 to 14, ARM architecture version, such as ARMv8.5 to A, and MTE support identifier.
[0096] Process flags: The hybris_init function calls prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, "hybris_bionic_tls") to set a special name for the process's TLS-related VMA region, which the kernel can identify through vma->vm_flags;
[0097] Kernel registration: Process information is registered to the newly added character device / dev / hybris_tls via ioctl. This includes version information in the ELF segment and the initial TLS size. If the initial TLS size is 4KB, the kernel records it in the hybris_bionic_info field of mm_struct. The character device / dev / hybris_tls is created by the kernel module hybris_tls.ko.
[0098] In copy_process, the kernel checks the parent process mm_struct->hybris_bionic_info to determine if it is a libhybris process, and only triggers the two-stage hook for this type of process.
[0099] S1.4 Implementation of dynamic mapping of dual TLS space for ARM specific registers in a multi-threaded environment.
[0100] When the child thread starts, libhybris is modified to intercept the entry function start_thread of pthread_start through LD_PRELOAD, and the hybris_tls_activate activation logic is inserted to achieve hardware-level mapping of the dual TLS space.
[0101] Register mapping initialization based on the ARMv8-A instruction set:
[0102] Reading the Glibc TLS base address: The TPIDR_EL0 register is read via assembly instructions. This is the default TLS pointer of Glibc and saved to the thread-local variable glibc_tls_base: __asm__ volatile ("mrs %0, tpidr_el0" : "=r"(glibc_tls_base));
[0103] To obtain the bionic TLS base address and MTE tag from the kernel: call ioctl(fd, HYBRIS_TLS_GET_INFO, &tls_info) to obtain the child thread's bionic_tls.base (bionic_tls_base) and mte_tag (bionic_mte_tag);
[0104] Set the bionic TLS base address register: Write bionic_tls_base to the TPIDRRO_EL0 register, the read-only TLS pointer of ARMv8-A, which is not used by bionic and is used exclusively as the bionic TLS base address to prevent accidental modification by user space: __asm__ volatile ("msr tpidrro_el0, %0" : : "r" (bionic_tls_base));
[0105] Set the TLS version number register: Use the second TLS pointer TPIDR2_EL0 register added in ARMv8.1 to store bionic_tls.generation, and implement hardware-level storage of the version number: __asm__ volatile ("msr tpidr2_el0, %0" : : "r" (tls_info.generation));
[0106] Configure the MTE tag register: Write bionic_mte_tag to the tag filter bit of the MTE fault status register TFSR_EL1 to ensure that only access to the matching tag is allowed: __asm__ volatile ("msr tfsr_el1, %0" : : "r" (bionic_mte_tag << 8)).
[0107] Metadata relocation and key adaptation:
[0108] Iterate through the metadata block pointed to by the child thread's meta_ptr, and correct all pointer type fields, such as function pointers in tls_dtor_list and key pointers in tls_key_data: new address = original address - parent thread base + child thread base, where the child thread base is calculated based on the address offset difference;
[0109] Adapt the bionic TLS key tls_key_data: Call the hybris_tls_key_adapt function to mix the parent thread key with the child thread mte_tag to generate a child thread-specific key, avoiding security risks caused by key reuse.
[0110] Destructor pre-registration and concurrency protection:
[0111] Parse the destructor list tls_dtor_list from the metadata block, store it in the doubly linked list bionic_dtor_chain of libhybris in the registration order, and record dtor_count synchronously with the kernel bionic_tls.dtor_count;
[0112] Initialize the read-write lock pthread_rwlock_t dtor_chain_lock to protect against concurrent access to bionic_dtor_chain, such as multiple threads registering destructors simultaneously;
[0113] Parameters are bound to each destructor extracted from TLS variables, and the MTE tags of the parameters are recorded to ensure that the parameter addresses are valid when called.
[0114] S2. Dynamic allocation and hardware-assisted verification of Bionic TLS during thread runtime: By designing a Bionic-compatible shadow allocator, and combining the ARM hardware features MTE and PMU, dynamic TLS management and boundary verification are achieved.
[0115] S2.1 Construct the bionic TLS metadata shadow table and concurrent security allocation state machine.
[0116] S2.1.1. Create a global hash table `bionic_tls_shadow` (i.e., `src / tls / shadow.c`) in libhybris, using the thread ID `pthread_t` as the key. Each entry contains:
[0117] block_map: bitmap_t, records the position of allocated blocks in the TLS space, each bit represents 16 bytes, adapted to the smallest allocation unit and MTE tag granularity of bionic;
[0118] module_tls: An array struct module_tls_entry[], each element of which records the TLS information of the dynamic module, including the module handle, allocation block start offset, size, alignment requirements, dependent TLS versions, and block MTE tag;
[0119] resize_policy: The resizing policy structure struct resize_policy contains the current resizing factor factor, which is initially 1.5, the maximum number of resizing operations max_count, which defaults to 8 times in bionic, and the next resizing threshold next_threshold, which is size * 0.8.
[0120] state: allocates the state machine enum {IDLE, ALLOCATING, RESIZING} to avoid concurrent allocation conflicts;
[0121] rwlock: a read-write lock pthread_rwlock_t that protects against concurrent reads and writes of table entries.
[0122] S2.1.2 When a thread is created, hybris_tls_activate initializes the bionic_tls_shadow table entry for the current thread:
[0123] block_map marks regions allocated by the parent thread, and unallocated regions are marked as 0;
[0124] The resize_policy is initialized according to the bionic rule, with factor=1.5 and max_count=8;
[0125] The state is set to IDLE, and rwlock is initialized through pthread_rwlock_init.
[0126] S2.2. Intercepting the bionic TLS allocation interface and implementing hardware-level aligned allocation: libhybris intercepts the bionic TLS allocation interface through a triple mechanism of PLT hooks, symbol redirection, and concurrency locks to ensure the correctness and security of the allocation process.
[0127] S2.2.1, Interception mechanism initialization:
[0128] When libhybris.so is loaded, the _init function obtains the PLT entry address of bionic's __tls_get_addr and __tls_alloc functions through dlopen("libc.so", RTLD_NOW);
[0129] The instructions of the custom functions hybris_tls_get_addr and hybris_tls_alloc are copied to the PLT entry point using memcpy, thus implementing the PLT hook;
[0130] In the LD_PRELOAD environment, the custom function is loaded first through the RTLD_NEXT mechanism of the dynamic linker, overriding the same-name symbol in bionic, to ensure that the interception takes effect.
[0131] S2.2.2 Implementation logic of the custom allocation function hybris_tls_alloc:
[0132] Locking: Call pthread_rwlock_wrlock(&shadow_entry->rwlock) to enter the write lock state and prevent concurrent allocation;
[0133] TLS requirements for parsing the module: Obtain ELF information of the calling module through dladdr to locate the PT_TLS segment, i.e., the TLS segment; read p_memsz (the required size tls_size) and p_align (the alignment requirement tls_align) of the PT_TLS segment; calculate the actual alignment requirement: take the larger value between tls_align and the MTE tag granularity of 16 bytes to ensure hardware compatibility;
[0134] Find a free region: Traverse shadow_entry->block_map, and use the best fit algorithm consistent with bionic to find the first free region that meets the size and alignment requirements; if found, calculate the starting offset block_offset, and mark the corresponding bit of block_map as 1 to indicate that it has been allocated; if not found, trigger the expansion process, update block_map and search again.
[0135] Allocating MTE tags: Calling `mte_allocate_tag` allocates an independent tag `block_mte_tag` for the new block, which is different from the TLS space master tag; the `block_mte_tag` is set for the memory region of the new block through the ARM user-space MTE function `mte_set_tag`.
[0136] Record allocation information: Add a new entry to the shadow_entry->module_tls array, recording the module handle, block_offset, tls_size, and block_mte_tag; call ioctl(fd, HYBRIS_TLS_UPDATE_ALLOC, &alloc_info) to update the kernel bionic_tls.alloc_ptr (alloc_ptr = block_offset + tls_size);
[0137] Calculate and return the address: Absolute address = TPIDRRO_EL0 (bionic TLS base address) + block_offset; Unlock: Call pthread_rwlock_unlock(&shadow_entry->rwlock); Return the absolute address to the caller, i.e., the HAL driver.
[0138] S2.3 Implementation of TLS dynamic expansion and boundary check based on ARM MTE. When hybris_tls_alloc detects insufficient space, it triggers the expansion process. The core is to simulate the expansion strategy of bionic and add MTE boundary protection.
[0139] S2.3.1 Calculation of expansion size and validity verification:
[0140] The new size is calculated based on shadow_entry->resize_policy: new_size = current_size *resize_policy.factor;
[0141] Decrease in resizing factor: resize_policy.factor *= 0.9, to avoid over-sizing, consistent with bionic;
[0142] Validity check: If resize_policy.resize_count >= max_count, return allocation failure ENOMIM; if new_size > 1GB, 1GB is the maximum TLS size of bionic, and is truncated to 1GB.
[0143] S2.3.2, New Space Allocation and MTE Configuration:
[0144] Call mmap(NULL, new_size, PROT_READ|PROT_WRITE|PROT_MTE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0) to allocate new memory;
[0145] Call madvise(new_addr, new_size, MADV_MTE_TAGGED) to mark the new space as supporting MTE;
[0146] Assign a new MTE main tag: Call mte_allocate_tag to get new_mte_tag, which is different from the old tag to avoid tag conflicts.
[0147] S2.3.3 Data Migration and Tag Synchronization:
[0148] The copy function mte_memcpy with MTE tag checks is used to copy all data, including variables and metadata, from the old TLS space to the new space, ensuring data integrity.
[0149] Iterate through the shadow_entry->module_tls array, reallocate the MTE tag new_block_tag for each allocated block, and update the block tag via mte_set_tag;
[0150] The tls_end field in the synchronized metadata is: new_meta_ptr->tls_end = new_size, consistent with bionic.
[0151] S2.3.4, Address and Register Synchronization:
[0152] Call ioctl(fd, HYBRIS_TLS_UPDATE_BASE, &new_base_info) to notify the kernel to update bionic_tls.base to new_addr, size to new_size, and mte_tag to new_mte_tag;
[0153] Update user-mode registers:
[0154] __asm__ volatile ("msr tpidrro_el0, %0" : : "r" (new_addr)); / / Update the Bionic TLS base address
[0155] __asm__ volatile ("msr tpidr2_el0, %0" : : "r" (tls_info.generation +1)); / / Version number +1
[0156] __asm__ volatile ("msr tfsr_el1, %0" : : "r" (new_mte_tag << 8)); / / Update MTE tag filtering
[0157] Release old space: Call munmap(old_addr, current_size) and release old MTE tags via mte_free_tag.
[0158] S2.3.5, Real-time activation of MTE boundary checks:
[0159] Set MTE tag isolation bands between blocks in the new space: each isolation band is 16 bytes of MTE tag granularity, and is set to the special tag 0xFF to indicate that no tag has been allocated;
[0160] When the HAL driver accesses the isolation band, the ARM MTE hardware triggers the SIGSEGV signal with the error code SEGV_MTEAERR, which notifies libhybris to handle the issue.
[0161] Modify the libhybris SIGSEGV signal handling function hybris_mte_handler to parse error addresses and output TLS block boundary information, such as accessing address 0x1108 outside of blocks 0x1000 to 0x1100, for easier debugging.
[0162] S2.4 TLS access monitoring and hardware-assisted verification based on ARM PMU enhance the security of TLS access by introducing an ARM performance monitoring unit (PMU) to monitor access anomalies.
[0163] S2.4.1, PMU Event Configuration:
[0164] In hybris_tls_activate, prctl(PR_SET_PMU_EVENT, ARMV8_PMU_EVT_DATA_ABORT) is called to enable the PMU data access exception event, with event code 0x40;
[0165] Configure the PMU counter: Enable the PMU counter via write_msr(PMCR_EL0, PMCR_E | PMCR_P) to record the number of access exceptions in the TLS space.
[0166] S2.4.2 Exception Detection and Handling:
[0167] Register the PMU interrupt handler function hybris_pmu_handler, which is implemented in the kernel module hybris_tls.ko;
[0168] When the PMU detects abnormal access to the TLS space, such as out-of-bounds access or tag mismatch, it triggers an interrupt. The hybris_pmu_handler performs the following operations: reads the exception syndrome register ESR_EL1, parses the exception type, such as ESR_EL1_MTE, which indicates an MTE error.
[0169] Read the fault address register FAR_EL1 to obtain the abnormal access address;
[0170] Call the hybris_tls_check_addr function to check if the address belongs to the current thread's bionic TLS space;
[0171] If it is a TLS out-of-bounds error, send the SIBBUS signal subtype SIBBUS_TLS_OVERFLOW to user space to notify libhybris to terminate the offending process.
[0172] S2.4.3 Access Logs and Monitoring:
[0173] Create a debug node in / sys / kernel / debug / hybris_tls / pmu_stats to record the number of exceptions captured by the PMU, the exception address, and the thread ID;
[0174] libhybris provides the hybris_tls_pmu_get_stats function, which allows user-space tools such as hybris-tls-monitor to read monitoring data, facilitating problem localization.
[0175] S3. Synchronization of the bionic TLS state during thread scheduling: Through the Linux kernel scheduler, ARM register state management and cache consistency mechanism, the consistency of TLS address, version number, register and cache is ensured during thread switching.
[0176] S3.1 Extends the context saving and restoration logic and version synchronization for kernel thread switching.
[0177] For the cpu_switch_to assembly function in arch / arm64 / kernel / entry.S of the ARM64 kernel, TLS state synchronization logic has been added to the switch_out (when a thread yields the CPU) and switch_in (when a thread enters the CPU) phases.
[0178] S3.1.1 Saving state during the switch_out phase:
[0179] Read `task_struct->bionic_tls.is_bionic` from the current thread. If it is true, read `TPIDRRO_EL0` (the base address of the bionic TLS) and write it to `bionic_tls.base`.
[0180] mrs x0, tpidrro_el0
[0181] str x0, [x1, #TASK_BIONIC_TLS_BASE] / / x1 is a pointer to task_struct, #TASK_BIONIC_TLS_BASE is the offset of bionic_tls.base
[0182] Read version number TPIDR2_EL0 and write it to bionic_tls.generation:
[0183] mrs x0, tpidr2_el0
[0184] str w0, [x1, #TASK_BIONIC_TLS_GENERATION]
[0185] Read the MTE tag TFSR_EL1 and write it to bionic_tls.mte_tag:
[0186] mrs x0, tfsr_el1
[0187] ubfx x0, x0, #8, #8 / / Extract tag bits
[0188] strb w0, [x1, #TASK_BIONIC_TLS_MTE_TAG]
[0189] The newly added kernel function hybris_tls_mark_dirty is called: it compares the checksum calculated by CRC32 in the TLS space with the previously saved value. If they are inconsistent, it sets the bionic_tls.dirty flag to true.
[0190] S3.1.2, Resume state during the switch_in phase:
[0191] Read the `task_struct->bionic_tls.is_bionic` property of the thread to be run; if it is true:
[0192] Read the address from bionic_tls.base and write it to TPIDRRO_EL0:
[0193] ldr x0, [x1, #TASK_BIONIC_TLS_BASE]
[0194] msr tpidrro_el0, x0
[0195] Read the version number from bionic_tls.generation and write it to TPIDR2_EL0:
[0196] ldr w0, [x1, #TASK_BIONIC_TLS_GENERATION]
[0197] msr tpidr2_el0, x0
[0198] Read tags from bionic_tls.mte_tag and write them to TFSR_EL1:
[0199] ldrb w0, [x1, #TASK_BIONIC_TLS_MTE_TAG]
[0200] lsl x0, x0, #8
[0201] msr tfsr_el1, x0
[0202] If bionic_tls.dirty is true, send a SIGUSR2 signal of subtype SIGUSR2_TLS_DIRTY to user space to notify libhybris to refresh the cache.
[0203] S3.2 Implement real-time verification and conflict resolution of TLS version numbers.
[0204] A new function, hybris_tls_version_check, has been added to libhybris and registered as a handler for the SIGUSR2 signal to resolve the version number inconsistency issue.
[0205] S3.2.1 Signal Reception and Locking:
[0206] Upon receiving the SIGUSR2_TLS_DIRTY signal, pthread_rwlock_wrlock(&shadow_entry->rwlock) is called to enter the write lock state;
[0207] Read the current version number TPIDR2_EL0 and compare it with the kernel bionic_tls.generation obtained via ioctl to see if they are consistent.
[0208] S3.2.2, Version Synchronization Logic:
[0209] If there is a discrepancy, suspend all TLS access: lock the TLS access entry point using pthread_mutex_lock(&tls_access_mutex);
[0210] Reread the kernel bionic_tls.base and update TPIDRRO_EL0:
[0211] __asm__ volatile ("msr tpidrro_el0, %0" : : "r" (new_base));
[0212] Reread kernel bionic_tls.generation and update TPIDR2_EL0:
[0213] __asm__ volatile ("msr tpidr2_el0, %0" : : "r" (new_generation));
[0214] Iterate through the shadow_entry->module_tls array and correct the absolute addresses of all TLS blocks based on the difference between the old and new base addresses;
[0215] Unlock: Call pthread_mutex_unlock(&tls_access_mutex) and pthread_rwlock_unlock(&shadow_entry->rwlock).
[0216] S3.2.3, Verification Result Feedback:
[0217] If synchronization is successful, return 0; if it fails, such as if the kernel version number continues to change, log the changes and trigger a thread restart, recreating the thread after pthread_exit.
[0218] S3.3, Cross-CPU scheduling of TLS cache consistency handling.
[0219] When threads are scheduled between different CPU cores, ARM's L1 and L2 caches may retain old TLS data, leading to access errors. This needs to be resolved through hardware instructions and kernel collaboration.
[0220] S3.3.1 Cross-CPU Detection and Signal Triggering:
[0221] During the switch_in phase, the kernel compares the current CPU task_struct->cpu with the last running CPU prev_cpu to determine whether to schedule across CPUs.
[0222] If it crosses CPUs, call send_sig_info(SIGBUS, &sig_info, task) to send the SIGBUS signal to user space, with the subtype set to SIGBUS_TLS_CPU_MIGRATE.
[0223] S3.3.2, User-space cache refresh:
[0224] The libhybris signal handling function hybris_tls_cache_flush performs the following operations:
[0225] Refresh data cache: Call the GCC built-in function __builtin___clear_cache to refresh the L1 data cache of the bionic TLS space, covering the range from TPIDRRO_EL0 to TPIDRRO_EL0 + size;
[0226] Execute ARM cache cleanup instructions: Clean up the data cache and invalidate the instruction cache using assembly instructions to ensure that the latest data is written to memory.
[0227] __asm__ volatile (
[0228] "dsb ishst\n" / / Data synchronization barrier to ensure storage completion
[0229] "dc civac, %0\n" / / Cleans up and invalidates the data cache, %0 is the TLS base address
[0230] "ic ivau, %0\n" / / Invalidate the instruction cache if the TLS contains executable code.
[0231] "isb sy\n" / / Command synchronization barrier to ensure commands take effect
[0232] : : "r" (bionic_tls_base) );
[0234] Synchronize MTE tag cache: Call the ARM user-space function mte_invalidate_tags to invalidate the MTE tag cache and ensure that new tags take effect.
[0235] S3.3.3 Resume Execution: Call sigreturn to resume thread execution, ensuring that subsequent accesses use the latest TLS data and tags.
[0236] S4. Bionic TLS resource cascading release and concurrency safety during thread destruction.
[0237] This phase achieves reverse triggering of TLS destructors, cascading release of hardware resources, and secure control over concurrent destruction of multi-threaded resources by linking the cleanup logic of the kernel and user space.
[0238] S4.1 Reverse triggering and dependency ordering of registered bionic TLS destructors.
[0239] In `hybris_tls_activate`, the `pthread_cleanup_push` callback `hybris_tls_destruct` is registered for the thread, with the highest priority to ensure execution before the Glibc destructor. The core logic is as follows:
[0240] S4.1.1 Destructor ordering and dependency resolution:
[0241] Locking: Call pthread_rwlock_rdlock(&dtor_chain_lock) to enter the read lock state;
[0242] Traverse the doubly linked list bionic_dtor_chain, execute the destructor function in reverse registration order (i.e., the last registered function is the first registered function) and store it in a temporary array dtor_order;
[0243] Dependency resolution: The `hybris_tls_dtor_dep_analyze` function analyzes the dependencies of destructors. For example, `camera_close` depends on `gpu_unmap`, so `gpu_unmap` must be executed first. Dependency graph construction: Destructors are used as nodes, and dependencies are used as edges. For example, the edge from `camera_close` to `gpu_unmap` indicates that `camera_close` depends on `gpu_unmap`. Topological sorting: The Kahn algorithm is used to perform topological sorting on the dependency graph, adjusting the order of the `dtor_order` array to ensure that dependent functions execute first.
[0244] Unlock: Call pthread_rwlock_unlock(&dtor_chain_lock).
[0245] S4.1.2 Destructor Execution and Exception Handling: Traversing the dtor_order array and calling the destructor sequentially:
[0246] Check the MTE tag of the destructor parameter: call mte_check_tag to verify whether the tag of the parameter address matches bionic_mte_tag. If they do not match, skip to avoid illegal parameters.
[0247] Execute the destructor: call it via a function pointer, such as dtor_entry->func(dtor_entry->arg), and capture the return value;
[0248] Exception handling: If the destructor returns an error such as -1, log the error in the log file / var / log / hybris_tls_dtor.log, and call hybris_tls_force_release to force the release of resources, such as close(dtor_entry->arg->fd) to close the file descriptor.
[0249] S4.1.3 Destructor chain cleanup:
[0250] Call pthread_rwlock_wrlock(&dtor_chain_lock) to enter write lock state;
[0251] Clear the bionic_dtor_chain list and release node memory;
[0252] Call pthread_rwlock_unlock(&dtor_chain_lock);
[0253] Destroy the read-write lock: Call pthread_rwlock_destroy(&dtor_chain_lock).
[0254] S4.2 Layered release and MTE tag reclamation of user-space bionic TLS space: After hybris_tls_destruct is executed, the layered release logic is triggered to ensure that resources are completely reclaimed.
[0255] S4.2.1 Module-level release and dependency unbinding:
[0256] Locking: Call pthread_rwlock_wrlock(&shadow_entry->rwlock);
[0257] Iterate through the shadow_entry->module_tls array: if the module has not been unloaded (i.e., dlclose has not been called), call dlclose(module_entry->handle) to unload the module; reclaim the MTE tag of the module's TLS block: call mte_free_tag(module_entry->block_mte_tag); mark the corresponding bit of shadow_entry->block_map as 0 to indicate that it is free;
[0258] Clear the module_tls array and release its memory.
[0259] Unlock: Call pthread_rwlock_unlock(&shadow_entry->rwlock).
[0260] S4.2.2, TLS space release and register reset:
[0261] Read the bionic TLS base address TPIDRRO_EL0 and obtain the size via ioctl;
[0262] Release the TLS space: Call munmap(bionic_tls_base, size);
[0263] Reclaim the MTE main tag: Call mte_free_tag(bionic_mte_tag);
[0264] Reset ARM registers:
[0265] __asm__ volatile ("msr tpidrro_el0, xzr"); / / xzr is the zero register, reset to 0
[0266] __asm__ volatile ("msr tpidr2_el0, wzr");
[0267] __asm__ volatile ("msr tfsr_el1, xzr");
[0268] S4.2.3 Shadow table cleanup and concurrency control:
[0269] Locking: Call pthread_mutex_lock(&shadow_table_mutex) to protect concurrent access to the global shadow table;
[0270] Remove the current thread's entry from the bionic_tls_shadow hash table and release the entry's memory;
[0271] Unlock: Call pthread_mutex_unlock(&shadow_table_mutex);
[0272] Destroy the read-write lock: call pthread_rwlock_destroy(&shadow_entry->rwlock).
[0273] S4.3 Deep cleaning and reference counting management of kernel-mode bionic TLS metadata.
[0274] When a thread exits and enters the kernel's do_exit function in kernel / exit.c, cleanup logic has been added to ensure that kernel-mode resources are completely reclaimed.
[0275] S4.3.1 Reference Count Check and Waiting:
[0276] Calling atomic_dec(&task->bionic_tls_ref) atomically decrements the reference count;
[0277] If the reference count is greater than 0 and other threads are referencing the TLS metadata, call wait_event_interruptible to wait until the reference count is 0.
[0278] S4.3.2 Kernel resource cleanup:
[0279] Check task->bionic_tls.is_bionic; if it is true:
[0280] Release the kernel temporary buffer: Call kmem_cache_free(bionic_tls_cachep, task->bionic_tls_cache), where bionic_tls_cachep is the cache pool created by kmem_cache_create;
[0281] Clean up the VMA region: Call hybrid_tls_free_vma(task), traverse the VMA linked list of the process, and release the VMA region marked as hybrid_bionic_tls;
[0282] Reset the bionic_tls structure: Call memset(&task->bionic_tls, 0, sizeof(struct bionic_tls)) to avoid data residue.
[0283] S4.3.3, Statistical Information Updates and Log Recording:
[0284] Update the statistics of the / proc / hybris_tls_stats node: the freed TLS space size (total_freed += old_size) and the number of destructor executions (dtor_executed += dtor_count);
[0285] Record destruction logs: Call printk(KERN_INFO "hybris_tls: thread %d destroyed,freed %zu bytes", task->tgid, old_size) for easy system monitoring.
[0286] Experimental verification shows that this embodiment has the following technical effects: Precise metadata-level inheritance: Through full kernel-mode metadata transfer, user-mode address relocation, and ARM register mapping, byte-level inheritance of the parent thread's Bionic TLS is achieved, increasing the adaptation success rate to over 95% and resolving HAL driver initialization crashes; Hardware-level dynamic compatibility and security: Combining ARM MTE to implement TLS boundary checks, PMU monitoring for access anomalies, and precise alignment of dynamic expansion with Bionic strategies, the TLS allocation success rate for dynamically loaded modules is increased to 98%, eliminating address out-of-bounds and security risks; Triple interception mechanism ensures interface adaptation stability; Consistent scheduling state across four dimensions: Through version number synchronization, cross-CPU cache refresh, and register state management, TLS state tearing during thread switching is resolved, reducing TLS-related crashes during system runtime by 99.5%; Hardware-level cache refresh of ARM instructions ensures consistency across CPU scheduling; Cascading resource release and concurrency safety: Destructor topology sorting, forced hardware resource release, and kernel reference counting management prevent resource leaks, reducing device conflict rate to 0.01%. The following features are included: layered release and concurrent lock mechanisms to ensure stable operation in a multi-threaded environment; version adaptation and maintainability: through ELF version marking, MTE and PMU hardware adaptation, it can cover Android 10 to 15 and later versions, reducing the cost of repeated development; debug nodes and logging mechanisms improve the efficiency of problem localization and reduce the difficulty of maintenance.
[0287] In summary, the above are merely preferred embodiments of the present invention and are not intended to limit the scope of protection of the present invention. Any modifications, equivalent substitutions, improvements, etc., made within the spirit and principles of the present invention should be included within the scope of protection of the present invention.
Claims
1. A multi-threaded TLS synchronization method for heterogeneous closed-source driven fusion operation, characterized in that, Specifically, the following steps are included: A B-TLS substructure is constructed in the Linux system kernel thread structure to record the user-space pointer and data block length of B-TLS metadata, and an atomic reference count is established to track the lifecycle of TLS metadata. The system starts the libhybris compatibility related compatibility process, creates an address space and main thread for it and records it as the source thread; after the compatibility layer runs, it sets the in-process TLS virtual memory region feature identifier, registers the initial TLS configuration and adds it to the process address space management structure, allocates the Linux native G-TLS space and the Android private B-TLS space for the source thread, initializes the B-TLS substructure of the kernel thread descriptor and configures the ARM architecture TLS dedicated register. When the source thread creates a child thread, it calculates the B-TLS space required by the child thread based on the source thread's B-TLS substructure; it allocates a kernel thread descriptor, B-TLS substructure, and user-space B-TLS space for the child thread and binds a hardware security label; it copies the source thread's TLS data and metadata; it corrects the metadata pointer offset, updates the version identifier; and it returns to user space after initializing the atomic reference count and the number of destructors. After the child thread starts, the compatibility layer configures dual TLS dedicated registers, initializes the global hash shadow table, allocation bitmap and concurrency control mechanism, and completes the activation of the child thread; When a thread calls a module to initiate a B-TLS allocation request during thread execution, it allocates a free region according to the alignment rules and returns a valid address. During thread scheduling, the kernel completes B-TLS context saving and restoration, dirty data marking, and version synchronization verification. When a compatible thread is deregistered, the destructor is executed in reverse registration order and module dependency topology order, releasing user-mode resources and resetting hardware registers layer by layer. After atomically decrementing the reference count to no references, kernel resources are reclaimed and the B-TLS substructure is cleared.
2. The multi-threaded TLS synchronization method of claim 1, wherein, The B-TLS substructure is aligned to the ARM64 hardware cache line and records the thread type identifier, number of destructors, hardware security label, TLS version number, base address, total size, and end offset of the allocated area of the thread's B-TLS space associated with the libhybris compatibility layer.
3. The multi-threaded TLS synchronization method of claim 1, wherein, When the calling module initiates a B-TLS allocation request, it acquires an exclusive lock on the B-TLS context of the current thread, parses the executable file information of the calling module to locate the TLS segment, extracts the required memory size and alignment requirements from it, and uses the larger of the alignment requirements and the hardware security tag granularity as the actual alignment requirements. Traverse the thread TLS allocation bitmap, use the standard adaptation algorithm to find the first free region that meets the size and alignment requirements. If it exists, calculate the starting offset and mark the corresponding bit in the allocation bitmap. Otherwise, trigger B-TLS space expansion, update the bitmap and search again.
4. The multi-threaded TLS synchronization method of claim 3, wherein, The method for expanding the B-TLS space is as follows: According to the thread's preset expansion strategy, the new size of the B-TLS space after expansion is the product of the original space size and the expansion coefficient, and the expansion coefficient is dynamically decayed; if the maximum number of expansions is exceeded, the allocation failure is returned; if the maximum space allowed at runtime is exceeded, the upper limit is truncated. Allocate a new virtual memory space that meets read / write and hardware security features through the memory mapping interface, and assign an independent hardware security label to the new B-TLS space; copy the business data and management metadata of the old space to the new space; traverse the allocated module information, reallocate and bind new hardware security labels to all B-TLS blocks, and update the space end address in the management metadata. The kernel is notified to update the B-TLS space base address, total size, and hardware security label; the ARM architecture TLS dedicated registers are updated; and the new B-TLS base address, version number, and hardware label filtering configuration are synchronized. The old memory space and corresponding hardware security label are safely released, and system resources are reclaimed.
5. The multi-threaded TLS synchronization method of claim 1, wherein, When a thread yields the processor, if the current thread is a compatibility thread, the kernel saves the values of the B-TLS related hardware registers to the B-TLS substructure of the kernel thread descriptor, including the base address register, version number register, and hardware security tag register; at the same time, it performs verification and comparison of the TLS space, and sets a dirty data flag if the data has changed; when the thread is rescheduled for execution, if it is a compatibility thread, the kernel restores the B-TLS hardware context from the kernel thread descriptor and rewrites the base address, version number, and hardware security tag into the corresponding registers; if it detects that the B-TLS space data has been tampered with, it sends a signal to the user-space compatibility layer to trigger cache flushing and security verification.
6. The multi-threaded TLS synchronization method of claim 1, wherein, Configure PMU events during the thread activation phase, enable data access anomaly monitoring capabilities, start hardware counters, and collect real-time statistics on abnormal access behavior in the TLS space. The kernel registers a PMU exception handling function. When the hardware detects illegal access, the exception handling process is automatically triggered. The kernel creates a debug node to record the number of exceptions, the fault address, and the thread ID.
7. The multi-threaded TLS synchronization method of claim 1, wherein, When the hardware detects that the B-TLS space data has been tampered with, it sends a signal to the user-space compatibility layer, triggering cache refresh and security verification. Specifically, when the kernel detects changes to the B-TLS space data or version inconsistencies, it sends a kernel synchronization signal to user space. Upon receiving the signal, user space uses concurrency lock protection to compare the current version with the kernel version. If they are inconsistent, TLS access is suspended, and the latest base address, version number, and hardware register state are synchronized from the kernel. The B-TLS management structure address information is corrected to ensure consistency between kernel space and user space. If synchronization fails, thread restart is executed.
8. The multi-threaded TLS synchronization method of claim 1, wherein, When a thread is switched, the kernel checks whether the CPU core has migrated before and after the scheduling. If cross-CPU scheduling occurs, it sends a cache refresh signal to user space. The user space signal handler uses hardware instructions to force refresh the data cache, invalidate the instruction cache, and clear the hardware security tag cache, so that the TLS data and tags accessed by the thread on the new CPU core are the latest valid values.
9. The method of claim 1, wherein, The method of releasing user-mode resources layer by layer is as follows: unload dynamic modules in sequence, reclaim hardware security tags of each TLS block, and clear the allocation bitmap; Free up the entire B-TLS space and reclaim the hardware security label.
10. The method of claim 1, wherein, The method for initializing the global hash shadow table is as follows: based on the records already allocated by the parent thread, initialize the allocation bitmap, set the used areas to valid markers, and set the unused areas to free markers; initialize the space expansion strategy according to the target runtime specification, and configure the expansion coefficient and the maximum number of expansions; Set the allocation state machine to an idle state and complete the initialization of the concurrent safe read-write lock.