diff options
author | Schrodinger ZHU Yifan <yifanzhu@rochester.edu> | 2023-12-12 15:31:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-12 12:31:51 -0800 |
commit | 3568521e3d2d09d12bd0c476d0376de165b19178 (patch) | |
tree | a80334dce385db3cecfaeaf3d09424a8b1e58988 /libc/startup | |
parent | 7f54070194f552e0c5de7543ad05e9ea163461ba (diff) | |
download | llvm-3568521e3d2d09d12bd0c476d0376de165b19178.zip llvm-3568521e3d2d09d12bd0c476d0376de165b19178.tar.gz llvm-3568521e3d2d09d12bd0c476d0376de165b19178.tar.bz2 |
[libc] fix issues around stack protector (#74567)
If a function is declared with stack-protector, the compiler may try to
load the TLS. However, inside certain runtime functions, TLS may not be
available. This patch disables stack protectors for such routines to fix
the problem.
Closes #74487.
Diffstat (limited to 'libc/startup')
-rw-r--r-- | libc/startup/linux/aarch64/start.cpp | 14 | ||||
-rw-r--r-- | libc/startup/linux/riscv/start.cpp | 14 | ||||
-rw-r--r-- | libc/startup/linux/x86_64/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libc/startup/linux/x86_64/start.cpp | 14 |
4 files changed, 25 insertions, 18 deletions
diff --git a/libc/startup/linux/aarch64/start.cpp b/libc/startup/linux/aarch64/start.cpp index b5c4268..c3e20eb 100644 --- a/libc/startup/linux/aarch64/start.cpp +++ b/libc/startup/linux/aarch64/start.cpp @@ -184,7 +184,9 @@ __attribute__((noinline)) static void do_start() { app.tls.align = phdr->p_align; } - LIBC_NAMESPACE::TLSDescriptor tls; + // This descriptor has to be static since its cleanup function cannot + // capture the context. + static LIBC_NAMESPACE::TLSDescriptor tls; LIBC_NAMESPACE::init_tls(tls); if (tls.size != 0) LIBC_NAMESPACE::set_thread_ptr(tls.tp); @@ -192,7 +194,11 @@ __attribute__((noinline)) static void do_start() { LIBC_NAMESPACE::self.attrib = &LIBC_NAMESPACE::main_thread_attrib; LIBC_NAMESPACE::main_thread_attrib.atexit_callback_mgr = LIBC_NAMESPACE::internal::get_thread_atexit_callback_mgr(); - + // We register the cleanup_tls function to be the last atexit callback to be + // invoked. It will tear down the TLS. Other callbacks may depend on TLS (such + // as the stack protector canary). + LIBC_NAMESPACE::atexit( + []() { LIBC_NAMESPACE::cleanup_tls(tls.tp, tls.size); }); // We want the fini array callbacks to be run after other atexit // callbacks are run. So, we register them before running the init // array callbacks as they can potentially register their own atexit @@ -208,10 +214,6 @@ __attribute__((noinline)) static void do_start() { reinterpret_cast<char **>(app.args->argv), reinterpret_cast<char **>(env_ptr)); - // TODO: TLS cleanup should be done after all other atexit callbacks - // are run. So, register a cleanup callback for it with atexit before - // everything else. - LIBC_NAMESPACE::cleanup_tls(tls.addr, tls.size); LIBC_NAMESPACE::exit(retval); } diff --git a/libc/startup/linux/riscv/start.cpp b/libc/startup/linux/riscv/start.cpp index bf04be5..4d37662 100644 --- a/libc/startup/linux/riscv/start.cpp +++ b/libc/startup/linux/riscv/start.cpp @@ -187,7 +187,9 @@ __attribute__((noinline)) static void do_start() { app.tls.align = phdr->p_align; } - LIBC_NAMESPACE::TLSDescriptor tls; + // This descriptor has to be static since its cleanup function cannot + // capture the context. + static LIBC_NAMESPACE::TLSDescriptor tls; LIBC_NAMESPACE::init_tls(tls); if (tls.size != 0) LIBC_NAMESPACE::set_thread_ptr(tls.tp); @@ -195,7 +197,11 @@ __attribute__((noinline)) static void do_start() { LIBC_NAMESPACE::self.attrib = &LIBC_NAMESPACE::main_thread_attrib; LIBC_NAMESPACE::main_thread_attrib.atexit_callback_mgr = LIBC_NAMESPACE::internal::get_thread_atexit_callback_mgr(); - + // We register the cleanup_tls function to be the last atexit callback to be + // invoked. It will tear down the TLS. Other callbacks may depend on TLS (such + // as the stack protector canary). + LIBC_NAMESPACE::atexit( + []() { LIBC_NAMESPACE::cleanup_tls(tls.tp, tls.size); }); // We want the fini array callbacks to be run after other atexit // callbacks are run. So, we register them before running the init // array callbacks as they can potentially register their own atexit @@ -211,10 +217,6 @@ __attribute__((noinline)) static void do_start() { reinterpret_cast<char **>(app.args->argv), reinterpret_cast<char **>(env_ptr)); - // TODO: TLS cleanup should be done after all other atexit callbacks - // are run. So, register a cleanup callback for it with atexit before - // everything else. - LIBC_NAMESPACE::cleanup_tls(tls.addr, tls.size); LIBC_NAMESPACE::exit(retval); } diff --git a/libc/startup/linux/x86_64/CMakeLists.txt b/libc/startup/linux/x86_64/CMakeLists.txt index 076c0c3..aac5a06 100644 --- a/libc/startup/linux/x86_64/CMakeLists.txt +++ b/libc/startup/linux/x86_64/CMakeLists.txt @@ -15,6 +15,7 @@ add_startup_object( libc.src.string.memory_utils.inline_memcpy libc.src.unistd.environ COMPILE_OPTIONS + -fno-stack-protector -fno-omit-frame-pointer -ffreestanding # To avoid compiler warnings about calling the main function. -fno-builtin diff --git a/libc/startup/linux/x86_64/start.cpp b/libc/startup/linux/x86_64/start.cpp index bc1b4f0..496105d 100644 --- a/libc/startup/linux/x86_64/start.cpp +++ b/libc/startup/linux/x86_64/start.cpp @@ -222,7 +222,9 @@ extern "C" void _start() { app.tls.align = phdr->p_align; } - LIBC_NAMESPACE::TLSDescriptor tls; + // This descriptor has to be static since its cleanup function cannot + // capture the context. + static LIBC_NAMESPACE::TLSDescriptor tls; LIBC_NAMESPACE::init_tls(tls); if (tls.size != 0 && !LIBC_NAMESPACE::set_thread_ptr(tls.tp)) LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, 1); @@ -230,7 +232,11 @@ extern "C" void _start() { LIBC_NAMESPACE::self.attrib = &LIBC_NAMESPACE::main_thread_attrib; LIBC_NAMESPACE::main_thread_attrib.atexit_callback_mgr = LIBC_NAMESPACE::internal::get_thread_atexit_callback_mgr(); - + // We register the cleanup_tls function to be the last atexit callback to be + // invoked. It will tear down the TLS. Other callbacks may depend on TLS (such + // as the stack protector canary). + LIBC_NAMESPACE::atexit( + []() { LIBC_NAMESPACE::cleanup_tls(tls.tp, tls.size); }); // We want the fini array callbacks to be run after other atexit // callbacks are run. So, we register them before running the init // array callbacks as they can potentially register their own atexit @@ -246,9 +252,5 @@ extern "C" void _start() { reinterpret_cast<char **>(app.args->argv), reinterpret_cast<char **>(env_ptr)); - // TODO: TLS cleanup should be done after all other atexit callbacks - // are run. So, register a cleanup callback for it with atexit before - // everything else. - LIBC_NAMESPACE::cleanup_tls(tls.addr, tls.size); LIBC_NAMESPACE::exit(retval); } |