https://github.com/jakos-sec created https://github.com/llvm/llvm-project/pull/198292
Introduce `sanitizer/safestack_interface.h` to expose SafeStack utility functions as a public interface, similar to other sanitizers. Exposed functions: * `__safestack_get_unsafe_stack_ptr` * `__safestack_get_unsafe_stack_bottom` * `__safestack_get_unsafe_stack_top` Deprecate the existing `__builtin___get_unsafe_stack_*` builtins and emit warnings suggesting the new `__safestack_` equivalents. Runtime compatibility aliases `__get_unsafe_stack_*` are maintained. Assisted by Gemini >From 3b579b216685137c3823644dd58b49310d247c6b Mon Sep 17 00:00:00 2001 From: Jakob Koschel <[email protected]> Date: Mon, 18 May 2026 13:01:12 +0000 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.7 --- clang/docs/SafeStack.rst | 43 +++++++++++++++---- clang/lib/Sema/SemaChecking.cpp | 20 +++++++++ .../test/Sema/safestack-deprecated-builtins.c | 17 ++++++++ compiler-rt/include/CMakeLists.txt | 1 + .../include/sanitizer/safestack_interface.h | 35 +++++++++++++++ compiler-rt/lib/safestack/CMakeLists.txt | 1 + compiler-rt/lib/safestack/safestack.cpp | 38 +++++++++++----- compiler-rt/test/safestack/sigaltstack.c | 16 +++---- 8 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 clang/test/Sema/safestack-deprecated-builtins.c create mode 100644 compiler-rt/include/sanitizer/safestack_interface.h diff --git a/clang/docs/SafeStack.rst b/clang/docs/SafeStack.rst index e347ae18b3506..edf8876931464 100644 --- a/clang/docs/SafeStack.rst +++ b/clang/docs/SafeStack.rst @@ -159,29 +159,56 @@ these variables, so extra care must be taken to manually ensure that all such accesses are safe. Furthermore, the addresses of such local variables should never be stored on the heap, as it would leak the location of the SafeStack. +``sanitizer/safestack_interface.h`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To use the low-level API, include the header ``<sanitizer/safestack_interface.h>``. + +``__safestack_get_unsafe_stack_ptr()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function returns current unsafe stack pointer of the current thread. + +``__safestack_get_unsafe_stack_bottom()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function returns a pointer to the bottom of the unsafe stack of the +current thread. + +``__safestack_get_unsafe_stack_top()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This function returns a pointer to the top of the unsafe stack of the +current thread. + + + +Deprecated Builtins +~~~~~~~~~~~~~~~~~~~ + +The following builtins are still supported but are deprecated and will emit a +warning. Use the corresponding functions from ``<sanitizer/safestack_interface.h>`` +instead. + ``__builtin___get_unsafe_stack_ptr()`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This builtin function returns current unsafe stack pointer of the current -thread. +Deprecated alias for ``__safestack_get_unsafe_stack_ptr()``. ``__builtin___get_unsafe_stack_bottom()`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This builtin function returns a pointer to the bottom of the unsafe stack of the -current thread. +Deprecated alias for ``__safestack_get_unsafe_stack_bottom()``. ``__builtin___get_unsafe_stack_top()`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This builtin function returns a pointer to the top of the unsafe stack of the -current thread. +Deprecated alias for ``__safestack_get_unsafe_stack_top()``. ``__builtin___get_unsafe_stack_start()`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Deprecated: This builtin function is an alias for -``__builtin___get_unsafe_stack_bottom()``. +Deprecated alias for ``__safestack_get_unsafe_stack_bottom()``. Design ====== diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 03091f2ba0cfe..b32032579aadd 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2915,6 +2915,26 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, FPOptions FPO; switch (BuiltinID) { + case Builtin::BI__builtin___get_unsafe_stack_start: + Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin) + << Context.BuiltinInfo.getQuotedName(BuiltinID) + << "__safestack_get_unsafe_stack_bottom"; + break; + case Builtin::BI__builtin___get_unsafe_stack_bottom: + Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin) + << Context.BuiltinInfo.getQuotedName(BuiltinID) + << "__safestack_get_unsafe_stack_bottom"; + break; + case Builtin::BI__builtin___get_unsafe_stack_top: + Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin) + << Context.BuiltinInfo.getQuotedName(BuiltinID) + << "__safestack_get_unsafe_stack_top"; + break; + case Builtin::BI__builtin___get_unsafe_stack_ptr: + Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin) + << Context.BuiltinInfo.getQuotedName(BuiltinID) + << "__safestack_get_unsafe_stack_ptr"; + break; case Builtin::BI__builtin_cpu_supports: case Builtin::BI__builtin_cpu_is: if (BuiltinCpu(*this, Context.getTargetInfo(), TheCall, diff --git a/clang/test/Sema/safestack-deprecated-builtins.c b/clang/test/Sema/safestack-deprecated-builtins.c new file mode 100644 index 0000000000000..c1818941b7d1c --- /dev/null +++ b/clang/test/Sema/safestack-deprecated-builtins.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -fsanitize=safe-stack + +void *test_bottom(void) { + return __builtin___get_unsafe_stack_bottom(); // expected-warning {{builtin '__builtin___get_unsafe_stack_bottom' is deprecated; use __safestack_get_unsafe_stack_bottom instead}} +} + +void *test_top(void) { + return __builtin___get_unsafe_stack_top(); // expected-warning {{builtin '__builtin___get_unsafe_stack_top' is deprecated; use __safestack_get_unsafe_stack_top instead}} +} + +void *test_ptr(void) { + return __builtin___get_unsafe_stack_ptr(); // expected-warning {{builtin '__builtin___get_unsafe_stack_ptr' is deprecated; use __safestack_get_unsafe_stack_ptr instead}} +} + +void *test_start(void) { + return __builtin___get_unsafe_stack_start(); // expected-warning {{builtin '__builtin___get_unsafe_stack_start' is deprecated; use __safestack_get_unsafe_stack_bottom instead}} +} diff --git a/compiler-rt/include/CMakeLists.txt b/compiler-rt/include/CMakeLists.txt index 8443e309d1e95..eb998478b081b 100644 --- a/compiler-rt/include/CMakeLists.txt +++ b/compiler-rt/include/CMakeLists.txt @@ -11,6 +11,7 @@ if (COMPILER_RT_BUILD_SANITIZERS) sanitizer/msan_interface.h sanitizer/netbsd_syscall_hooks.h sanitizer/rtsan_interface.h + sanitizer/safestack_interface.h sanitizer/scudo_interface.h sanitizer/tsan_interface.h sanitizer/tsan_interface_atomic.h diff --git a/compiler-rt/include/sanitizer/safestack_interface.h b/compiler-rt/include/sanitizer/safestack_interface.h new file mode 100644 index 0000000000000..bab74b355d10a --- /dev/null +++ b/compiler-rt/include/sanitizer/safestack_interface.h @@ -0,0 +1,35 @@ +//===-- sanitizer/safestack_interface.h -------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of SafeStack. +// +// Public interface header. +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_SAFESTACK_INTERFACE_H +#define SANITIZER_SAFESTACK_INTERFACE_H + +#include <sanitizer/common_interface_defs.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/// Returns the current unsafe stack pointer of the current thread. +void SANITIZER_CDECL *__safestack_get_unsafe_stack_ptr(void); + +/// Returns a pointer to the bottom of the unsafe stack of the current thread. +void SANITIZER_CDECL *__safestack_get_unsafe_stack_bottom(void); + +/// Returns a pointer to the top of the unsafe stack of the current thread. +void SANITIZER_CDECL *__safestack_get_unsafe_stack_top(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // SANITIZER_SAFESTACK_INTERFACE_H diff --git a/compiler-rt/lib/safestack/CMakeLists.txt b/compiler-rt/lib/safestack/CMakeLists.txt index 4cff95f546931..39a4e8294f359 100644 --- a/compiler-rt/lib/safestack/CMakeLists.txt +++ b/compiler-rt/lib/safestack/CMakeLists.txt @@ -5,6 +5,7 @@ set(SAFESTACK_SOURCES ) include_directories(..) +include_directories(../../include) set(SAFESTACK_CFLAGS ${SANITIZER_COMMON_CFLAGS}) diff --git a/compiler-rt/lib/safestack/safestack.cpp b/compiler-rt/lib/safestack/safestack.cpp index ec8c1dd6c8acb..ab0d0be72b53c 100644 --- a/compiler-rt/lib/safestack/safestack.cpp +++ b/compiler-rt/lib/safestack/safestack.cpp @@ -23,6 +23,7 @@ #include "safestack_platform.h" #include "safestack_util.h" #include "sanitizer_common/sanitizer_internal_defs.h" +#include "sanitizer/safestack_interface.h" // interception.h drags in sanitizer_redefine_builtins.h, which in turn // creates references to __sanitizer_internal_memcpy etc. The interceptors @@ -338,22 +339,39 @@ __attribute__((section(".preinit_array"), } #endif -extern "C" - __attribute__((visibility("default"))) void *__get_unsafe_stack_bottom() { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__safestack_get_unsafe_stack_bottom() { return unsafe_stack_start; } -extern "C" - __attribute__((visibility("default"))) void *__get_unsafe_stack_top() { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__safestack_get_unsafe_stack_top() { return (char*)unsafe_stack_start + unsafe_stack_size; } -extern "C" - __attribute__((visibility("default"))) void *__get_unsafe_stack_start() { - return unsafe_stack_start; -} -extern "C" - __attribute__((visibility("default"))) void *__get_unsafe_stack_ptr() { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__safestack_get_unsafe_stack_ptr() { return __safestack_unsafe_stack_ptr; } + +// Compatibility aliases +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__get_unsafe_stack_bottom() { + return __safestack_get_unsafe_stack_bottom(); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__get_unsafe_stack_top() { + return __safestack_get_unsafe_stack_top(); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__get_unsafe_stack_start() { + return __safestack_get_unsafe_stack_bottom(); +} + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void *__get_unsafe_stack_ptr() { + return __safestack_get_unsafe_stack_ptr(); +} diff --git a/compiler-rt/test/safestack/sigaltstack.c b/compiler-rt/test/safestack/sigaltstack.c index a6c77009874f6..395228b167a43 100644 --- a/compiler-rt/test/safestack/sigaltstack.c +++ b/compiler-rt/test/safestack/sigaltstack.c @@ -15,22 +15,20 @@ // Test that safe stack works with sigaltstack. int puts(const char *); -extern void *__get_unsafe_stack_ptr(); -extern void *__get_unsafe_stack_top(); -extern void *__get_unsafe_stack_bottom(); +#include <sanitizer/safestack_interface.h> __thread int signal_handlers_called = 0; void signal_handler(int signo) { signal_handlers_called += 1; - assert(__get_unsafe_stack_ptr() <= __get_unsafe_stack_top() && - __get_unsafe_stack_ptr() >= __get_unsafe_stack_bottom()); + assert(__safestack_get_unsafe_stack_ptr() <= __safestack_get_unsafe_stack_top() && + __safestack_get_unsafe_stack_ptr() >= __safestack_get_unsafe_stack_bottom()); } void signal_sigaction(int signo, siginfo_t *si, void *uc) { signal_handlers_called += 1; - assert(__get_unsafe_stack_ptr() <= __get_unsafe_stack_top() && - __get_unsafe_stack_ptr() >= __get_unsafe_stack_bottom()); + assert(__safestack_get_unsafe_stack_ptr() <= __safestack_get_unsafe_stack_top() && + __safestack_get_unsafe_stack_ptr() >= __safestack_get_unsafe_stack_bottom()); } void *t1_start(void *ptr) { @@ -113,8 +111,8 @@ int main() { raise(SIGUSR2); // Check that unsafe stack is set to the normal unsafe stack. - assert(__get_unsafe_stack_ptr() <= __get_unsafe_stack_top() && - __get_unsafe_stack_ptr() >= __get_unsafe_stack_bottom()); + assert(__safestack_get_unsafe_stack_ptr() <= __safestack_get_unsafe_stack_top() && + __safestack_get_unsafe_stack_ptr() >= __safestack_get_unsafe_stack_bottom()); assert(signal_handlers_called == 4); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
