From 1603d629241d879ab9c5b14499e44857f5ff680b Mon Sep 17 00:00:00 2001 From: rdevshp Date: Tue, 5 May 2026 13:45:34 +0000 Subject: [PATCH] __pthread_internal_remap_stack_with_mte: stop setting stack top guard to RW. --- libc/bionic/pthread_create.cpp | 3 +++ libc/bionic/pthread_internal.cpp | 2 +- libc/bionic/pthread_internal.h | 3 +++ tests/struct_layout_test.cpp | 38 +++++++++++++++++--------------- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index aa793f70cfc..836b6c03fa8 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -329,6 +329,8 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si // than the space originally wasted by pthread_internal_t for compatibility. result.stack_top = space + stack_guard_size + stack_size - arc4random_uniform(sizeof(pthread_internal_t)); result.stack_top = __builtin_align_down(result.stack_top, 16); + + result.stack_size = stack_size; return result; } @@ -388,6 +390,7 @@ static int __allocate_thread(pthread_attr_t* attr, bionic_tcb** tcbp, void** chi thread->mmap_size_unguarded = mapping.mmap_size_unguarded; thread->stack_top = reinterpret_cast(stack_top); thread->stack_bottom = reinterpret_cast(attr->stack_base); + thread->stack_size = mapping.stack_size; *tcbp = tcb; *child_stack = stack_top; diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp index 7c66c75312e..55585944c4b 100644 --- a/libc/bionic/pthread_internal.cpp +++ b/libc/bionic/pthread_internal.cpp @@ -226,7 +226,7 @@ bool __pthread_internal_remap_stack_with_mte() { } for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) { if (t->terminating || t->is_main()) continue; - if (mprotect(t->mmap_base_unguarded, t->mmap_size_unguarded, + if (t->stack_size && mprotect(t->mmap_base_unguarded, t->stack_size, PROT_READ | PROT_WRITE | PROT_MTE)) { async_safe_fatal("error: failed to set PROT_MTE on thread: %d", t->tid); } diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h index c10e25fb926..e8d6840df0c 100644 --- a/libc/bionic/pthread_internal.h +++ b/libc/bionic/pthread_internal.h @@ -168,6 +168,8 @@ class pthread_internal_t { size_t mmap_size_unguarded; char vma_name_buffer[32]; + size_t stack_size; + thread_local_dtor* thread_local_dtors; /* @@ -198,6 +200,7 @@ struct ThreadMapping { char* static_tls; char* stack_base; char* stack_top; + size_t stack_size; char* libgen_buffers; }; diff --git a/tests/struct_layout_test.cpp b/tests/struct_layout_test.cpp index 3574d0c72ab..93ce15c4b60 100644 --- a/tests/struct_layout_test.cpp +++ b/tests/struct_layout_test.cpp @@ -30,7 +30,7 @@ void tests(CheckSize check_size, CheckOffset check_offset) { #define CHECK_OFFSET(name, field, offset) \ check_offset(#name, #field, offsetof(name, field), offset) #ifdef __LP64__ - CHECK_SIZE(pthread_internal_t, 832); + CHECK_SIZE(pthread_internal_t, 840); CHECK_OFFSET(pthread_internal_t, next, 0); CHECK_OFFSET(pthread_internal_t, prev, 8); CHECK_OFFSET(pthread_internal_t, tid, 16); @@ -51,14 +51,15 @@ void tests(CheckSize check_size, CheckOffset check_offset) { CHECK_OFFSET(pthread_internal_t, mmap_base_unguarded, 192); CHECK_OFFSET(pthread_internal_t, mmap_size_unguarded, 200); CHECK_OFFSET(pthread_internal_t, vma_name_buffer, 208); - CHECK_OFFSET(pthread_internal_t, thread_local_dtors, 240); - CHECK_OFFSET(pthread_internal_t, current_dlerror, 248); - CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 256); - CHECK_OFFSET(pthread_internal_t, bionic_tls, 768); - CHECK_OFFSET(pthread_internal_t, errno_value, 776); - CHECK_OFFSET(pthread_internal_t, bionic_tcb, 784); - CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 792); - CHECK_OFFSET(pthread_internal_t, should_allocate_stack_mte_ringbuffer, 824); + CHECK_OFFSET(pthread_internal_t, stack_size, 240); + CHECK_OFFSET(pthread_internal_t, thread_local_dtors, 248); + CHECK_OFFSET(pthread_internal_t, current_dlerror, 256); + CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 264); + CHECK_OFFSET(pthread_internal_t, bionic_tls, 776); + CHECK_OFFSET(pthread_internal_t, errno_value, 784); + CHECK_OFFSET(pthread_internal_t, bionic_tcb, 792); + CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 800); + CHECK_OFFSET(pthread_internal_t, should_allocate_stack_mte_ringbuffer, 832); CHECK_SIZE(bionic_tls, 4016); CHECK_OFFSET(bionic_tls, key_data, 0); CHECK_OFFSET(bionic_tls, locale, 2080); @@ -75,7 +76,7 @@ void tests(CheckSize check_size, CheckOffset check_offset) { CHECK_OFFSET(bionic_tls, bionic_systrace_enabled, 4009); CHECK_OFFSET(bionic_tls, padding, 4010); #else - CHECK_SIZE(pthread_internal_t, 712); + CHECK_SIZE(pthread_internal_t, 716); CHECK_OFFSET(pthread_internal_t, next, 0); CHECK_OFFSET(pthread_internal_t, prev, 4); CHECK_OFFSET(pthread_internal_t, tid, 8); @@ -96,14 +97,15 @@ void tests(CheckSize check_size, CheckOffset check_offset) { CHECK_OFFSET(pthread_internal_t, mmap_base_unguarded, 104); CHECK_OFFSET(pthread_internal_t, mmap_size_unguarded, 108); CHECK_OFFSET(pthread_internal_t, vma_name_buffer, 112); - CHECK_OFFSET(pthread_internal_t, thread_local_dtors, 144); - CHECK_OFFSET(pthread_internal_t, current_dlerror, 148); - CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 152); - CHECK_OFFSET(pthread_internal_t, bionic_tls, 664); - CHECK_OFFSET(pthread_internal_t, errno_value, 668); - CHECK_OFFSET(pthread_internal_t, bionic_tcb, 672); - CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 676); - CHECK_OFFSET(pthread_internal_t, should_allocate_stack_mte_ringbuffer, 708); + CHECK_OFFSET(pthread_internal_t, stack_size, 144); + CHECK_OFFSET(pthread_internal_t, thread_local_dtors, 148); + CHECK_OFFSET(pthread_internal_t, current_dlerror, 152); + CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 156); + CHECK_OFFSET(pthread_internal_t, bionic_tls, 668); + CHECK_OFFSET(pthread_internal_t, errno_value, 672); + CHECK_OFFSET(pthread_internal_t, bionic_tcb, 676); + CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 680); + CHECK_OFFSET(pthread_internal_t, should_allocate_stack_mte_ringbuffer, 712); CHECK_SIZE(bionic_tls, 2892); CHECK_OFFSET(bionic_tls, key_data, 0); CHECK_OFFSET(bionic_tls, locale, 1040);