[libc-commits] [libc] try 2 (PR #68258)

via libc-commits libc-commits at lists.llvm.org
Wed Oct 4 13:58:29 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

<details>
<summary>Changes</summary>

- Re-generate pow-4.ll in preparation for D141060
- Auto-generate test checks for tests affected by D141060
- Regenerate test checks for tests affected by D141060
- Revert "[clang] Predefined macros for float128 support (#<!-- -->67196)"
- [NFC]Rename InstrProf::getFuncName{,orExternalSymbol} to getFuncOrValName{,IfDefined} (#<!-- -->68240)
- [LangRef] Specify NaN behavior more precisely (#<!-- -->66579)
- [LinkerWrapper] Fix resolution of weak symbols during LTO (#<!-- -->68215)
- [Libomptarget] Make the DeviceRTL configuration globals weak (#<!-- -->68220)
- [Libomptarget] Explicitly pass the OpenMP device libraries to tests (#<!-- -->68225)
- [RISCV][ISel] Fix comment to match direction of predicate in code. NFC. (#<!-- -->68248)
- [clang-format][NFC] AlignTokens: Rename Changes[i] to CurrentChange (#<!-- -->68152)
- [clang-format][NFC] AlignTokenSequence: Rename Changes[i] to CurrentC…
- [libc] Fix typo in long double negative block (#<!-- -->68243)
- [lld/ELF] Don't relax R_X86_64_(REX_)GOTPCRELX when offset is too far
- [clang] Default x86-64's medium code model -mlarge-data-threshold to 65535 (#<!-- -->67506)
- [clang-format][NFC] AlignTokenSequence: Skip loop iteration
- [Libomptarget] Disable AMDGPU complex math test after recent patch
- [RISCV] Relax vslide*_vl patterns to allow any mask. NFC (#<!-- -->68203)
- [RISCV][GlobalISel] Legalize G_FRAME_INDEX (#<!-- -->67746)
- [RISCV] Fix illegal build_vector when lowering double id buildvec on RV32 (#<!-- -->67017)
- [AMDGPU]: Allow combining into v_dot4
- [mlir][sparse] Print new syntax (#<!-- -->68130)
- [Clang][CodeGen][NFC] Add (broken) test case for GH67937
- [libc++][NFC] Fix broken formatting in comment
- Introduce and use codegen::createTargetMachineForTriple()
- [libc] Add x86-64 stack protector support.


---
Full diff: https://github.com/llvm/llvm-project/pull/68258.diff


4 Files Affected:

- (modified) libc/startup/linux/x86_64/CMakeLists.txt (+1) 
- (modified) libc/startup/linux/x86_64/start.cpp (+20-1) 
- (modified) libc/test/integration/src/unistd/CMakeLists.txt (+23) 
- (added) libc/test/integration/src/unistd/stack_smashing_test.cpp (+68) 


``````````diff
diff --git a/libc/startup/linux/x86_64/CMakeLists.txt b/libc/startup/linux/x86_64/CMakeLists.txt
index 40f01836c131344..076c0c3e444f565 100644
--- a/libc/startup/linux/x86_64/CMakeLists.txt
+++ b/libc/startup/linux/x86_64/CMakeLists.txt
@@ -10,6 +10,7 @@ add_startup_object(
     libc.src.__support.threads.thread
     libc.src.__support.OSUtil.osutil
     libc.src.stdlib.exit
+    libc.src.stdlib.abort
     libc.src.stdlib.atexit
     libc.src.string.memory_utils.inline_memcpy
     libc.src.unistd.environ
diff --git a/libc/startup/linux/x86_64/start.cpp b/libc/startup/linux/x86_64/start.cpp
index 4b46a4f4a7b0813..e791326c97418f7 100644
--- a/libc/startup/linux/x86_64/start.cpp
+++ b/libc/startup/linux/x86_64/start.cpp
@@ -7,8 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "config/linux/app.h"
+#include "src/__support/OSUtil/io.h"
 #include "src/__support/OSUtil/syscall.h"
 #include "src/__support/threads/thread.h"
+#include "src/stdlib/abort.h"
 #include "src/stdlib/atexit.h"
 #include "src/stdlib/exit.h"
 #include "src/string/memory_utils/inline_memcpy.h"
@@ -23,6 +25,11 @@
 
 extern "C" int main(int, char **, char **);
 
+extern "C" void __stack_chk_fail() {
+  __llvm_libc::write_to_stderr("stack smashing detected");
+  __llvm_libc::abort();
+}
+
 namespace LIBC_NAMESPACE {
 
 #ifdef SYS_mmap2
@@ -54,7 +61,9 @@ void init_tls(TLSDescriptor &tls_descriptor) {
   // Per the x86_64 TLS ABI, the entry pointed to by the thread pointer is the
   // address of the TLS block. So, we add more size to accomodate this address
   // entry.
-  uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t);
+  // We also need to include space for the stack canary. The canary is at
+  // offset 0x28 (40) and is of size uintptr_t.
+  uintptr_t tlsSizeWithAddr = tlsSize + sizeof(uintptr_t) + 40;
 
   // We cannot call the mmap function here as the functions set errno on
   // failure. Since errno is implemented via a thread local variable, we cannot
@@ -76,6 +85,16 @@ void init_tls(TLSDescriptor &tls_descriptor) {
   LIBC_NAMESPACE::inline_memcpy(reinterpret_cast<char *>(tlsAddr),
                                 reinterpret_cast<const char *>(app.tls.address),
                                 app.tls.init_size);
+  uintptr_t *stackGuardAddr = reinterpret_cast<uintptr_t *>(endPtr + 40);
+  // Setting the stack guard to a random value.
+  // We cannot call the get_random function here as the function sets errno on
+  // failure. Since errno is implemented via a thread local variable, we cannot
+  // use errno before TLS is setup.
+  ssize_t stackGuardRetVal = __llvm_libc::syscall_impl<ssize_t>(
+      SYS_getrandom, reinterpret_cast<long>(stackGuardAddr), sizeof(uint64_t),
+      0);
+  if (stackGuardRetVal < 0)
+    LIBC_NAMESPACE::syscall_impl(SYS_exit, 1);
 
   tls_descriptor = {tlsSizeWithAddr, uintptr_t(tlsAddr), endPtr};
   return;
diff --git a/libc/test/integration/src/unistd/CMakeLists.txt b/libc/test/integration/src/unistd/CMakeLists.txt
index 72fdb8fc7e6b018..10aac212af355ea 100644
--- a/libc/test/integration/src/unistd/CMakeLists.txt
+++ b/libc/test/integration/src/unistd/CMakeLists.txt
@@ -33,6 +33,29 @@ add_integration_test(
     libc.src.unistd.fork
 )
 
+if((${LIBC_TARGET_OS} STREQUAL "linux") AND (${LIBC_TARGET_ARCHITECTURE_IS_X86}))
+  add_integration_test(
+    stack_smashing_test
+    SUITE
+      unistd-integration-tests
+    SRCS
+      stack_smashing_test.cpp
+    DEPENDS
+      libc.include.errno
+      libc.include.signal
+      libc.include.sys_wait
+      libc.include.unistd
+      libc.src.pthread.pthread_atfork
+      libc.src.signal.raise
+      libc.src.sys.wait.wait
+      libc.src.sys.wait.wait4
+      libc.src.sys.wait.waitpid
+      libc.src.unistd.fork
+    COMPILE_OPTIONS
+      -fstack-protector-all
+  )
+endif()
+
 add_executable(
   libc_execv_test_normal_exit
   EXCLUDE_FROM_ALL
diff --git a/libc/test/integration/src/unistd/stack_smashing_test.cpp b/libc/test/integration/src/unistd/stack_smashing_test.cpp
new file mode 100644
index 000000000000000..f5bc935464a9b85
--- /dev/null
+++ b/libc/test/integration/src/unistd/stack_smashing_test.cpp
@@ -0,0 +1,68 @@
+//===--- Stack smashing test to check stack canary set up  ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/string.h"
+#include "src/__support/OSUtil/io.h"
+#include "src/pthread/pthread_atfork.h"
+#include "src/signal/raise.h"
+#include "src/sys/wait/wait.h"
+#include "src/sys/wait/wait4.h"
+#include "src/sys/wait/waitpid.h"
+#include "src/unistd/fork.h"
+
+#include "test/IntegrationTest/test.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+void no_stack_smashing_normal_exit() {
+  pid_t pid = __llvm_libc::fork();
+  if (pid == 0) {
+    // Child process
+    char foo[30];
+    for (int i = 0; i < 30; i++)
+      foo[i] = (foo[i] != 42) ? 42 : 24;
+    return;
+  }
+  ASSERT_TRUE(pid > 0);
+  int status;
+  pid_t cpid = __llvm_libc::wait(&status);
+  ASSERT_TRUE(cpid > 0);
+  ASSERT_EQ(cpid, pid);
+  ASSERT_TRUE(WIFEXITED(status));
+}
+
+void stack_smashing_abort() {
+  pid_t pid = __llvm_libc::fork();
+  if (pid == 0) {
+    // Child process
+    char foo[30];
+    char *frame_ptr = static_cast<char *>(__builtin_frame_address(0));
+    char *cur_ptr = &foo[0];
+    // Corrupt the stack
+    while (cur_ptr != frame_ptr) {
+      *cur_ptr = (*cur_ptr != 42) ? 42 : 24;
+      cur_ptr++;
+    }
+    return;
+  }
+  ASSERT_TRUE(pid > 0);
+  int status;
+  pid_t cpid = __llvm_libc::wait(&status);
+  ASSERT_TRUE(cpid > 0);
+  ASSERT_EQ(cpid, pid);
+  ASSERT_TRUE(WTERMSIG(status) == SIGABRT);
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+  no_stack_smashing_normal_exit();
+  stack_smashing_abort();
+  return 0;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/68258


More information about the libc-commits mailing list