blob: b385a5d472df01cd1c36ccd9dfc6c3979e85d8e9 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/__stack_chk_fail.h"
#include <lib/zircon-internal/unique-backtrace.h>
#include "src/__support/common.h"
extern "C" {
// Calls to this function are generated by the compiler automatically in
// various modes controlled by `-fstack-protector` and other related switches.
// These are usually on by default, the various options controlling what kinds
// of functions will be "protected" by extra code in their frame setup logic.
// The Fuchsia Compiler ABI provides a pointer-sized "stack guard" value (via
// the thread pointer as specified in <zircon/tls.h>), which is randomized at
// process startup. The compiler reserves a slot at the edge of a "protected"
// function's stack frame, called the "stack canary". It emits extra code in
// the function prologue to copy the stack guard value provided by the ABI into
// the stack canary slot in the new call frame. Corresponding code in the
// function's epilogue then fetches the guard value via the ABI again and
// compares it to the stack canary. If they don't match, the epilogue calls
// __stack_chk_fail so the corrupted function will never return. This can be
// an important safety and security measure, because the return address may be
// stored on the stack nearby to the stack canary word--if the canary is
// corrupted, the return value may also be corrupted and perhaps exploited to
// hijack control flow. (This is not a direct risk when either safe-stack or
// shadow-call-stack is in use. When using safe-stack, the canary is on the
// unsafe stack while the return address is on the machine stack; when using
// shadow-call-stack, the canary is on the machine stack while the return
// address is on the shadow call stack. But other kinds of corruption can be
// dangerous and possibly exploited, so early detection here is still valued
// for safety and security.)
LLVM_LIBC_FUNCTION_ATTR [[noreturn]] void __stack_chk_fail() {
// If this is in a backtrace, it indicates that the calling function's stack
// frame was corrupted sometime between entering that function and returning
// from it. This can happen via a buffer overrun in that function itself, or
// in one of its previous callees; or via other kinds of memory corruption.
CRASH_WITH_UNIQUE_BACKTRACE();
}
} // extern "C"