Chromium Code Reviews| Index: base/security_unittest.cc |
| diff --git a/base/security_unittest.cc b/base/security_unittest.cc |
| index 5db18fdfe457ad132092e7cdcb188c12d6ead3b0..6e7e609649be132dbf20bbbedfe00d0bdb597b9f 100644 |
| --- a/base/security_unittest.cc |
| +++ b/base/security_unittest.cc |
| @@ -2,17 +2,22 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| +#include <sys/stat.h> |
| +#include <sys/types.h> |
| #include <algorithm> |
| #include <limits> |
| +#include "base/file_util.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +using file_util::ScopedFD; |
| using std::nothrow; |
| namespace { |
| @@ -100,4 +105,56 @@ TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNewArray)) { |
| } |
| } |
| +#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) |
| +// Useful for debugging. |
| +void PrintProcSelfMaps() { |
| + int fd = open("/proc/self/maps", O_RDONLY); |
| + ScopedFD fd_closer(&fd); |
| + ASSERT_GE(fd, 0); |
| + char buffer[1<<13]; |
| + int ret; |
| + ret = read(fd, buffer, sizeof(buffer) - 1); |
|
Marius
2013/01/29 07:41:27
where's the close()?
jln (very slow on Chromium)
2013/01/29 07:48:15
I added a ScopedFD instead.
|
| + ASSERT_GT(ret, 0); |
| + buffer[ret - 1] = 0; |
| + fprintf(stdout, "%s\n", buffer); |
| +} |
| + |
| +// Check if TCMalloc uses an underlying random memory allocator. |
| +TEST(SecurityTest, ALLOC_TEST(RandomMemoryAllocations)) { |
| + if (IsTcMallocBypassed()) |
| + return; |
| + // Two successive calls to mmap() have roughly one chance out of 2^6 to be |
| + // detected as having the same order. With 32 allocations, we see ~16 that |
| + // trigger a call to mmap, so the chances of this test flaking is roughly |
| + // 2^-(6*15), i.e. virtually impossible. |
| + const int kAllocNumber = 32; |
| + bool is_contiguous = true; |
| + // Make kAllocNumber successive allocations of growing size and compare the |
| + // successive pointers to detect adjacent mappings. We grow the size because |
| + // TCMalloc can sometimes over-allocate. |
| + scoped_ptr<char, base::FreeDeleter> ptr[kAllocNumber]; |
| + for (int i = 0; i < kAllocNumber; ++i) { |
| + // Grow the Malloc size slightly sub-exponentially. |
| + const size_t kMallocSize = 1 << (12 + (i>>1)); |
| + ptr[i].reset(static_cast<char*>(malloc(kMallocSize))); |
| + ASSERT_TRUE(ptr[i] != NULL); |
| + if (i > 0) { |
| + // Without mmap randomization, the two high order nibbles |
| + // of a 47 bits userland address address will be identical. |
| + const uintptr_t kHighOrderMask = 0xff0000000000ULL; |
| + bool pointer_have_same_high_order = |
| + (reinterpret_cast<size_t>(ptr[i].get()) & kHighOrderMask) == |
| + (reinterpret_cast<size_t>(ptr[i - 1].get()) & kHighOrderMask); |
| + if (!pointer_have_same_high_order) { |
| + // PrintProcSelfMaps(); |
| + is_contiguous = false; |
| + break; |
| + } |
| + } |
| + } |
| + ASSERT_FALSE(is_contiguous); |
| +} |
| + |
| +#endif // (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) |
| + |
| } // namespace |