Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

try 2 #68258

Merged
merged 2 commits into from
Oct 4, 2023
Merged

try 2 #68258

merged 2 commits into from
Oct 4, 2023

Conversation

tnv01
Copy link
Contributor

@tnv01 tnv01 commented Oct 4, 2023

No description provided.

@llvmbot llvmbot added the libc label Oct 4, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 4, 2023

@llvm/pr-subscribers-libc

Changes
  • 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 --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;
+}

@sivachandra sivachandra self-requested a review October 4, 2023 21:00
@sivachandra sivachandra merged commit 28245b4 into llvm:main Oct 4, 2023
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants