
Stack protectors remain the same after forking, so reading the stack protector in one process (e.g. a renderer) reveals to an attacker the stack protector of the ancestor zygote and its children, including future children. This CL adds the capability to reset stack canaries after fork, which requires the functions already on the call stack to be compiled without stack protectors (or else they will use the original canary and crash on return). A command line flag is added to enable the behavior, which will be added by default to the chrome command line in a future CL. Bug: 1206626 Change-Id: I26e53c91986eda2bdf238bf912832649b7a14327 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2895917 Reviewed-by: Nico Weber <thakis@chromium.org> Reviewed-by: Avi Drissman <avi@chromium.org> Reviewed-by: Robert Sesek <rsesek@chromium.org> Commit-Queue: Matthew Denton <mpdenton@chromium.org> Cr-Commit-Position: refs/heads/master@{#904353}
47 lines
1.6 KiB
C++
47 lines
1.6 KiB
C++
// Copyright 2021 The Chromium 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 "base/stack_canary_linux.h"
|
|
|
|
#include "base/compiler_specific.h"
|
|
#include "build/build_config.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace base {
|
|
|
|
#if defined(LIBC_GLIBC) && \
|
|
(defined(ARCH_CPU_ARM_FAMILY) || defined(ARCH_CPU_X86_FAMILY))
|
|
|
|
namespace {
|
|
__attribute__((noinline, optnone)) void ResetCanaryAndReturn() {
|
|
// Create a buffer >=8 bytes to force the stack protector on this function,
|
|
// which should work as long as -fno-stack-protector isn't passed in the
|
|
// default options. We compile this file with -fstack-protector-all, but it
|
|
// may be overridden with -fstack-protector or -fstack-protector-strong.
|
|
char buffer[10];
|
|
ALLOW_UNUSED_LOCAL(buffer);
|
|
ResetStackCanaryIfPossible();
|
|
}
|
|
} // namespace
|
|
|
|
// Essentially tests that ResetStackCanaryIfPossible() changes the
|
|
// actual reference canary that is checked in the function prologue.
|
|
TEST(StackCanary, ChangingStackCanaryCrashesOnReturn) {
|
|
ASSERT_DEATH(ResetCanaryAndReturn(), "stack smashing");
|
|
}
|
|
|
|
#if !defined(NDEBUG)
|
|
// Tests that the useful debug message works--specifically that on death, it
|
|
// prints out the bug URL with useful information.
|
|
TEST(StackCanary, ChangingStackCanaryPrintsDebugMessage) {
|
|
SetStackSmashingEmitsDebugMessage();
|
|
ASSERT_DEATH(ResetCanaryAndReturn(), "crbug\\.com/1206626");
|
|
}
|
|
#endif // !defined(NDEBUG)
|
|
|
|
#endif // defined(LIBC_GLIBC) && (defined(ARCH_CPU_ARM_FAMILY) ||
|
|
// defined(ARCH_CPU_X86_FAMILY))
|
|
|
|
} // namespace base
|