0
Files
src/base/stack_canary_linux_unittest.cc
Matthew Denton bb0b03e29b Linux: Add ability to reset stack canaries after fork
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}
2021-07-22 16:18:13 +00:00

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