security_unittest.cc revision 45779228f8c9e40851cfd23f727e2bd8ffdd4714
1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <fcntl.h> 60d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stddef.h> 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <stdio.h> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <stdlib.h> 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <string.h> 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/stat.h> 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/types.h> 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <algorithm> 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <limits> 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/files/file_util.h" 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/scoped_ptr.h" 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "build/build_config.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "testing/gtest/include/gtest/gtest.h" 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_POSIX) 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/mman.h> 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <unistd.h> 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratusing std::nothrow; 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratusing std::numeric_limits; 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This function acts as a compiler optimization barrier. We use it to 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// prevent the compiler from making an expression a compile-time constant. 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// We also use it so that the compiler doesn't discard certain return values 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// as something we don't need (see the comment with calloc below). 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <typename Type> 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratNOINLINE Type HideValueFromCompiler(volatile Type value) { 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(__GNUC__) 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // In a GCC compatible compiler (GCC or Clang), make this compiler barrier 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // more robust than merely using "volatile". 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat __asm__ volatile ("" : "+r" (value)); 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // __GNUC__ 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return value; 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Tcmalloc and Windows allocator shim support setting malloc limits. 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// - NO_TCMALLOC (should be defined if compiled with use_allocator!="tcmalloc") 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// - ADDRESS_SANITIZER and SYZYASAN because they have their own memory allocator 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// - IOS does not use tcmalloc 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// - OS_MACOSX does not use tcmalloc 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// - Windows allocator shim defines ALLOCATOR_SHIM 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if (!defined(NO_TCMALLOC) || defined(ALLOCATOR_SHIM)) && \ 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat !defined(ADDRESS_SANITIZER) && !defined(OS_IOS) && !defined(OS_MACOSX) && \ 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat !defined(SYZYASAN) 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define MALLOC_OVERFLOW_TEST(function) function 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define MALLOC_OVERFLOW_TEST(function) DISABLED_##function 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#if defined(OS_LINUX) && defined(__x86_64__) 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Detect runtime TCMalloc bypasses. 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool IsTcMallocBypassed() { 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This should detect a TCMalloc bypass from Valgrind. 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat char* g_slice = getenv("G_SLICE"); 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (g_slice && !strcmp(g_slice, "always-malloc")) 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// There are platforms where these tests are known to fail. We would like to 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// be able to easily check the status on the bots, but marking tests as 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// FAILS_ is too clunky. 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid OverflowTestsSoftExpectTrue(bool overflow_detected) { 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!overflow_detected) { 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX) 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Sadly, on Linux, Android, and OSX we don't have a good story yet. Don't 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // fail the test, but report. 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat printf("Platform has overflow: %s\n", 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat !overflow_detected ? "yes." : "no."); 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // aren't). 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(overflow_detected); 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 8945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko#if defined(OS_IOS) || defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define MAYBE_NewOverflow DISABLED_NewOverflow 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define MAYBE_NewOverflow NewOverflow 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Test array[TooBig][X] and array[X][TooBig] allocations for int overflows. 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// IOS doesn't honor nothrow, so disable the test there. 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Crashes on Windows Dbg builds, disable there as well. 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Fails on Mac 10.8 http://crbug.com/227092 9845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// Disabled on Linux because failing Linux Valgrind bot, and Valgrind exclusions 9945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// are not currently read. See http://crbug.com/582398 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(SecurityTest, MAYBE_NewOverflow) { 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kArraySize = 4096; 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We want something "dynamic" here, so that the compiler doesn't 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // immediately reject crazy arrays. 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kDynamicArraySize = HideValueFromCompiler(kArraySize); 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // numeric_limits are still not constexpr until we switch to C++11, so we 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // use an ugly cast. 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kMaxSizeT = ~static_cast<size_t>(0); 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_EQ(numeric_limits<size_t>::max(), kMaxSizeT); 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kArraySize2 = kMaxSizeT / kArraySize + 10; 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kDynamicArraySize2 = HideValueFromCompiler(kArraySize2); 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<char[][kArraySize]> array_pointer(new (nothrow) 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat char[kDynamicArraySize2][kArraySize]); 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat OverflowTestsSoftExpectTrue(!array_pointer); 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // On windows, the compiler prevents static array sizes of more than 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 0x7fffffff (error C2148). 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ALLOW_UNUSED_LOCAL(kDynamicArraySize); 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<char[][kArraySize2]> array_pointer(new (nothrow) 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat char[kDynamicArraySize][kArraySize2]); 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat OverflowTestsSoftExpectTrue(!array_pointer); 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS) 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_LINUX) && defined(__x86_64__) 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Check if ptr1 and ptr2 are separated by less than size chars. 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool ArePointersToSameArea(void* ptr1, void* ptr2, size_t size) { 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ptrdiff_t ptr_diff = reinterpret_cast<char*>(std::max(ptr1, ptr2)) - 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reinterpret_cast<char*>(std::min(ptr1, ptr2)); 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return static_cast<size_t>(ptr_diff) <= size; 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Check if TCMalloc uses an underlying random memory allocator. 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(SecurityTest, MALLOC_OVERFLOW_TEST(RandomMemoryAllocations)) { 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (IsTcMallocBypassed()) 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t kPageSize = 4096; // We support x86_64 only. 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Check that malloc() returns an address that is neither the kernel's 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // un-hinted mmap area, nor the current brk() area. The first malloc() may 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // not be at a random address because TCMalloc will first exhaust any memory 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that it has allocated early on, before starting the sophisticated 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // allocators. 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void* default_mmap_heap_address = 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat mmap(0, kPageSize, PROT_READ|PROT_WRITE, 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_NE(default_mmap_heap_address, 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static_cast<void*>(MAP_FAILED)); 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_EQ(munmap(default_mmap_heap_address, kPageSize), 0); 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void* brk_heap_address = sbrk(0); 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_NE(brk_heap_address, reinterpret_cast<void*>(-1)); 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_TRUE(brk_heap_address != NULL); 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 1 MB should get us past what TCMalloc pre-allocated before initializing 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // the sophisticated allocators. 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t kAllocSize = 1<<20; 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat scoped_ptr<char, base::FreeDeleter> ptr( 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static_cast<char*>(malloc(kAllocSize))); 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_TRUE(ptr != NULL); 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // If two pointers are separated by less than 512MB, they are considered 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // to be in the same area. 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Our random pointer could be anywhere within 0x3fffffffffff (46bits), 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and we are checking that it's not withing 1GB (30 bits) from two 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // addresses (brk and mmap heap). We have roughly one chance out of 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 2^15 to flake. 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const size_t kAreaRadius = 1<<29; 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool in_default_mmap_heap = ArePointersToSameArea( 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ptr.get(), default_mmap_heap_address, kAreaRadius); 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(in_default_mmap_heap); 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool in_default_brk_heap = ArePointersToSameArea( 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ptr.get(), brk_heap_address, kAreaRadius); 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(in_default_brk_heap); 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // In the implementation, we always mask our random addresses with 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // kRandomMask, so we use it as an additional detection mechanism. 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const uintptr_t kRandomMask = 0x3fffffffffffULL; 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool impossible_random_address = 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reinterpret_cast<uintptr_t>(ptr.get()) & ~kRandomMask; 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(impossible_random_address); 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_LINUX) && defined(__x86_64__) 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 188