[libc-commits] [libc] [libc] Simple __stack_chk_guard implementation (PR #78804)

Petr Hosek via libc-commits libc-commits at lists.llvm.org
Fri Jan 19 15:11:23 PST 2024


https://github.com/petrhosek created https://github.com/llvm/llvm-project/pull/78804

This is needed on systems that don't use TLS to store the stack canary.

>From 193308ac2d4e698d8c8145ac3143d69d6cbd542f Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 4 Jan 2024 09:41:42 +0000
Subject: [PATCH] [libc] Simple __stack_chk_guard implementation

This is needed on systems that don't use TLS to store the stack canary.
---
 libc/config/baremetal/arm/entrypoints.txt     |  1 +
 libc/config/baremetal/riscv/entrypoints.txt   |  1 +
 libc/config/linux/aarch64/entrypoints.txt     |  1 +
 libc/config/linux/arm/entrypoints.txt         |  8 ++++
 libc/src/compiler/CMakeLists.txt              | 17 +++++++-
 libc/src/compiler/__stack_chk_guard.h         | 20 ++++++++++
 libc/src/compiler/baremetal/CMakeLists.txt    |  7 ++++
 .../compiler/baremetal/__stack_chk_guard.cpp  | 17 ++++++++
 libc/src/compiler/linux/CMakeLists.txt        | 11 ++++++
 libc/src/compiler/linux/__stack_chk_guard.cpp | 39 +++++++++++++++++++
 libc/test/src/compiler/CMakeLists.txt         |  1 +
 11 files changed, 121 insertions(+), 2 deletions(-)
 create mode 100644 libc/src/compiler/__stack_chk_guard.h
 create mode 100644 libc/src/compiler/baremetal/CMakeLists.txt
 create mode 100644 libc/src/compiler/baremetal/__stack_chk_guard.cpp
 create mode 100644 libc/src/compiler/linux/CMakeLists.txt
 create mode 100644 libc/src/compiler/linux/__stack_chk_guard.cpp

diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index f725b1c2394c6a3..39f54440780deb8 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -19,6 +19,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # compiler entrypoints (no corresponding header)
     libc.src.compiler.__stack_chk_fail
+    libc.src.compiler.__stack_chk_guard
 
     # errno.h entrypoints
     libc.src.errno.errno
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5da755170fda96e..79bd24bea103aea 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -19,6 +19,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # compiler entrypoints (no corresponding header)
     libc.src.compiler.__stack_chk_fail
+    libc.src.compiler.__stack_chk_guard
 
     # errno.h entrypoints
     libc.src.errno.errno
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 625fa6bffe63c65..7496947a781bd4f 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -366,6 +366,7 @@ if(LLVM_LIBC_FULL_BUILD)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # compiler entrypoints (no corresponding header)
     libc.src.compiler.__stack_chk_fail
+    libc.src.compiler.__stack_chk_guard
 
     # network.h entrypoints
     libc.src.network.htonl
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index c75ac2302d4ac45..7070f6c4e5a1521 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -235,6 +235,14 @@ set(TARGET_LIBM_ENTRYPOINTS
     libc.src.math.truncl
 )
 
+if(LLVM_LIBC_FULL_BUILD)
+  list(APPEND TARGET_LIBC_ENTRYPOINTS
+    # compiler entrypoints (no corresponding header)
+    libc.src.compiler.__stack_chk_fail
+    libc.src.compiler.__stack_chk_guard
+  )
+endif()
+
 set(TARGET_LLVMLIBC_ENTRYPOINTS
   ${TARGET_LIBC_ENTRYPOINTS}
   ${TARGET_LIBM_ENTRYPOINTS}
diff --git a/libc/src/compiler/CMakeLists.txt b/libc/src/compiler/CMakeLists.txt
index aa59d84e08d1467..b37b2dbe1c61989 100644
--- a/libc/src/compiler/CMakeLists.txt
+++ b/libc/src/compiler/CMakeLists.txt
@@ -1,9 +1,9 @@
 if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
   add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
-else()
-  add_subdirectory(generic)
 endif()
 
+add_subdirectory(generic)
+
 if(TARGET libc.src.compiler.${LIBC_TARGET_OS}.__stack_chk_fail)
   set(stack_chk_fail_dep libc.src.compiler.${LIBC_TARGET_OS}.__stack_chk_fail)
 else()
@@ -16,3 +16,16 @@ add_entrypoint_object(
   DEPENDS
     ${stack_chk_fail_dep}
 )
+
+if(TARGET libc.src.compiler.${LIBC_TARGET_OS}.__stack_chk_guard)
+  set(stack_chk_guard_dep libc.src.compiler.${LIBC_TARGET_OS}.__stack_chk_guard)
+else()
+  set(stack_chk_guard_dep libc.src.compiler.generic.__stack_chk_guard)
+endif()
+
+add_entrypoint_object(
+  __stack_chk_guard
+  ALIAS
+  DEPENDS
+    ${stack_chk_guard_dep}
+)
diff --git a/libc/src/compiler/__stack_chk_guard.h b/libc/src/compiler/__stack_chk_guard.h
new file mode 100644
index 000000000000000..17edefa3465d7e5
--- /dev/null
+++ b/libc/src/compiler/__stack_chk_guard.h
@@ -0,0 +1,20 @@
+//===-- Internal header for __stack_chk_guard -------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_COMPILER___STACK_CHK_GUARD_H
+#define LLVM_LIBC_SRC_COMPILER___STACK_CHK_GUARD_H
+
+#include <stdint.h>
+
+// The compiler will emit calls implicitly to a non-namespaced version.
+// TODO: can we additionally provide a namespaced alias so that tests can
+// explicitly call the namespaced variant rather than the non-namespaced
+// definition?
+extern "C" uintptr_t __stack_chk_guard;
+
+#endif // LLVM_LIBC_SRC_COMPILER___STACK_CHK_GUARD_H
diff --git a/libc/src/compiler/baremetal/CMakeLists.txt b/libc/src/compiler/baremetal/CMakeLists.txt
new file mode 100644
index 000000000000000..222ca9fc1523671
--- /dev/null
+++ b/libc/src/compiler/baremetal/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_entrypoint_object(
+  __stack_chk_guard
+  SRCS
+    __stack_chk_guard.cpp
+  HDRS
+    ../__stack_chk_guard.h
+)
diff --git a/libc/src/compiler/baremetal/__stack_chk_guard.cpp b/libc/src/compiler/baremetal/__stack_chk_guard.cpp
new file mode 100644
index 000000000000000..691e0c4f725220f
--- /dev/null
+++ b/libc/src/compiler/baremetal/__stack_chk_guard.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of __stack_chk_guard -------------------------------===//
+//
+// 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/compiler/__stack_chk_guard.h"
+
+#include <stdint.h>
+
+extern "C" {
+
+uintptr_t __stack_chk_guard = 0x00000aff; // 0, 0, '\n', 255
+
+} // extern "C"
diff --git a/libc/src/compiler/linux/CMakeLists.txt b/libc/src/compiler/linux/CMakeLists.txt
new file mode 100644
index 000000000000000..33918fb2f4db28c
--- /dev/null
+++ b/libc/src/compiler/linux/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_entrypoint_object(
+  __stack_chk_guard
+  SRCS
+    __stack_chk_guard.cpp
+  HDRS
+    ../__stack_chk_guard.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+  COMPILE_OPTIONS
+    -Wno-global-constructors
+)
diff --git a/libc/src/compiler/linux/__stack_chk_guard.cpp b/libc/src/compiler/linux/__stack_chk_guard.cpp
new file mode 100644
index 000000000000000..112dd2a52da70cd
--- /dev/null
+++ b/libc/src/compiler/linux/__stack_chk_guard.cpp
@@ -0,0 +1,39 @@
+//===-- Implementation of __stack_chk_guard -------------------------------===//
+//
+// 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/compiler/__stack_chk_guard.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h>
+
+extern "C" {
+
+uintptr_t __stack_chk_guard = 0;
+
+} // extern "C"
+
+namespace LIBC_NAMESPACE {
+namespace {
+
+class StackCheckGuard {
+public:
+  StackCheckGuard() {
+    // TODO: Use getauxval(AT_RANDOM) once available.
+    long retval =
+        syscall_impl(SYS_getrandom, reinterpret_cast<long>(&__stack_chk_guard),
+                     sizeof(uintptr_t), 0);
+    if (retval < 0)
+      __stack_chk_guard = 0x00000aff; // 0, 0, '\n', 255
+  }
+};
+
+StackCheckGuard stack_check_guard;
+
+} // anonymous namespace
+} // namespace LIBC_NAMESPACE
diff --git a/libc/test/src/compiler/CMakeLists.txt b/libc/test/src/compiler/CMakeLists.txt
index 65a9acceb6f7f10..39f96eb2272431a 100644
--- a/libc/test/src/compiler/CMakeLists.txt
+++ b/libc/test/src/compiler/CMakeLists.txt
@@ -9,6 +9,7 @@ add_libc_unittest(
   DEPENDS
     libc.src.__support.macros.sanitizer
     libc.src.compiler.__stack_chk_fail
+    libc.src.compiler.__stack_chk_guard
     libc.src.string.memset
   COMPILE_OPTIONS
     -fstack-protector-all



More information about the libc-commits mailing list