Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: base/security_unittest.cc

Issue 12210023: Security unittests: add more compiler barriers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <fcntl.h> 5 #include <fcntl.h>
6 #include <stdio.h> 6 #include <stdio.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <string.h> 8 #include <string.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
(...skipping 10 matching lines...) Expand all
21 #if defined(OS_POSIX) 21 #if defined(OS_POSIX)
22 #include <sys/mman.h> 22 #include <sys/mman.h>
23 #include <unistd.h> 23 #include <unistd.h>
24 #endif 24 #endif
25 25
26 using std::nothrow; 26 using std::nothrow;
27 using std::numeric_limits; 27 using std::numeric_limits;
28 28
29 namespace { 29 namespace {
30 30
31 // This function acts as a compiler optimization barrier. We use it to
32 // prevent the compiler from making an expression a compile-time constant.
33 // We also use it so that the compiler doesn't discard certain return values
34 // as something we don't need (see the comment with calloc below).
35 template <typename Type>
36 Type HideValueFromCompiler(volatile Type value) {
37 return value;
38 }
39
31 // Check that we can not allocate a memory range that cannot be indexed 40 // Check that we can not allocate a memory range that cannot be indexed
32 // via an int. This is used to mitigate vulnerabilities in libraries that use 41 // via an int. This is used to mitigate vulnerabilities in libraries that use
33 // int instead of size_t. 42 // int instead of size_t.
34 // See crbug.com/169327. 43 // See crbug.com/169327.
35 44
36 // - NO_TCMALLOC because we only patched tcmalloc 45 // - NO_TCMALLOC because we only patched tcmalloc
37 // - ADDRESS_SANITIZER because it has its own memory allocator 46 // - ADDRESS_SANITIZER because it has its own memory allocator
38 // - IOS does not seem to honor nothrow in new properly 47 // - IOS does not seem to honor nothrow in new properly
39 // - OS_MACOSX does not use tcmalloc 48 // - OS_MACOSX does not use tcmalloc
40 #if !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \ 49 #if !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \
(...skipping 19 matching lines...) Expand all
60 } 69 }
61 70
62 // Fake test that allow to know the state of TCMalloc by looking at bots. 71 // Fake test that allow to know the state of TCMalloc by looking at bots.
63 TEST(SecurityTest, ALLOC_TEST(IsTCMallocDynamicallyBypassed)) { 72 TEST(SecurityTest, ALLOC_TEST(IsTCMallocDynamicallyBypassed)) {
64 printf("Malloc is dynamically bypassed: %s\n", 73 printf("Malloc is dynamically bypassed: %s\n",
65 IsTcMallocBypassed() ? "yes." : "no."); 74 IsTcMallocBypassed() ? "yes." : "no.");
66 } 75 }
67 76
68 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsMalloc)) { 77 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsMalloc)) {
69 if (!IsTcMallocBypassed()) { 78 if (!IsTcMallocBypassed()) {
70 scoped_ptr<char, base::FreeDeleter> 79 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
71 ptr(static_cast<char*>(malloc(kTooBigAllocSize))); 80 HideValueFromCompiler(malloc(kTooBigAllocSize))));
72 ASSERT_TRUE(ptr == NULL); 81 ASSERT_TRUE(!ptr);
73 } 82 }
74 } 83 }
75 84
76 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsCalloc)) { 85 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsCalloc)) {
77 if (!IsTcMallocBypassed()) { 86 if (!IsTcMallocBypassed()) {
78 scoped_ptr<char, base::FreeDeleter> 87 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
79 ptr(static_cast<char*>(calloc(kTooBigAllocSize, 1))); 88 HideValueFromCompiler(calloc(kTooBigAllocSize, 1))));
80 ASSERT_TRUE(ptr == NULL); 89 ASSERT_TRUE(!ptr);
81 } 90 }
82 } 91 }
83 92
84 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsRealloc)) { 93 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsRealloc)) {
85 if (!IsTcMallocBypassed()) { 94 if (!IsTcMallocBypassed()) {
86 char* orig_ptr = static_cast<char*>(malloc(1)); 95 char* orig_ptr = static_cast<char*>(malloc(1));
87 ASSERT_TRUE(orig_ptr != NULL); 96 ASSERT_TRUE(orig_ptr);
88 scoped_ptr<char, base::FreeDeleter> 97 scoped_ptr<char, base::FreeDeleter> ptr(static_cast<char*>(
89 ptr(static_cast<char*>(realloc(orig_ptr, kTooBigAllocSize))); 98 HideValueFromCompiler(realloc(orig_ptr, kTooBigAllocSize))));
90 ASSERT_TRUE(ptr == NULL); 99 ASSERT_TRUE(!ptr);
91 // If realloc() did not succeed, we need to free orig_ptr. 100 // If realloc() did not succeed, we need to free orig_ptr.
92 free(orig_ptr); 101 free(orig_ptr);
93 } 102 }
94 } 103 }
95 104
96 typedef struct { 105 typedef struct {
97 char large_array[kTooBigAllocSize]; 106 char large_array[kTooBigAllocSize];
98 } VeryLargeStruct; 107 } VeryLargeStruct;
99 108
100 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNew)) { 109 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNew)) {
101 if (!IsTcMallocBypassed()) { 110 if (!IsTcMallocBypassed()) {
102 scoped_ptr<VeryLargeStruct> ptr(new (nothrow) VeryLargeStruct); 111 scoped_ptr<VeryLargeStruct> ptr(
103 ASSERT_TRUE(ptr == NULL); 112 HideValueFromCompiler(new (nothrow) VeryLargeStruct));
113 ASSERT_TRUE(!ptr);
104 } 114 }
105 } 115 }
106 116
107 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNewArray)) { 117 TEST(SecurityTest, ALLOC_TEST(MemoryAllocationRestrictionsNewArray)) {
108 if (!IsTcMallocBypassed()) { 118 if (!IsTcMallocBypassed()) {
109 scoped_ptr<char[]> ptr(new (nothrow) char[kTooBigAllocSize]); 119 scoped_ptr<char[]> ptr(
110 ASSERT_TRUE(ptr == NULL); 120 HideValueFromCompiler(new (nothrow) char[kTooBigAllocSize]));
121 ASSERT_TRUE(!ptr);
111 } 122 }
112 } 123 }
113 124
114 // The tests bellow check for overflows in new[] and calloc(). 125 // The tests bellow check for overflows in new[] and calloc().
115 126
116 #if defined(OS_IOS) || defined(OS_WIN) 127 #if defined(OS_IOS) || defined(OS_WIN)
117 #define DISABLE_ON_IOS_AND_WIN(function) DISABLED_##function 128 #define DISABLE_ON_IOS_AND_WIN(function) DISABLED_##function
118 #else 129 #else
119 #define DISABLE_ON_IOS_AND_WIN(function) function 130 #define DISABLE_ON_IOS_AND_WIN(function) function
120 #endif 131 #endif
(...skipping 15 matching lines...) Expand all
136 printf("Platform has overflow: %s\n", 147 printf("Platform has overflow: %s\n",
137 !overflow_detected ? "yes." : "no."); 148 !overflow_detected ? "yes." : "no.");
138 #else 149 #else
139 // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT 150 // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT
140 // aren't). 151 // aren't).
141 EXPECT_TRUE(overflow_detected); 152 EXPECT_TRUE(overflow_detected);
142 #endif 153 #endif
143 } 154 }
144 } 155 }
145 156
146 // This function acts as a compiler optimization barrier. We use it to
147 // prevent the compiler from making an expression a compile-time constant.
148 // We also use it so that the compiler doesn't discard certain return values
149 // as something we don't need (see the comment with calloc below).
150 template <typename Type>
151 Type HideValueFromCompiler(volatile Type value) {
152 return value;
153 }
154
155 // Test array[TooBig][X] and array[X][TooBig] allocations for int overflows. 157 // Test array[TooBig][X] and array[X][TooBig] allocations for int overflows.
156 // IOS doesn't honor nothrow, so disable the test there. 158 // IOS doesn't honor nothrow, so disable the test there.
157 // Disable on Windows, we suspect some are failing because of it. 159 // Disable on Windows, we suspect some are failing because of it.
158 TEST(SecurityTest, DISABLE_ON_IOS_AND_WIN(NewOverflow)) { 160 TEST(SecurityTest, DISABLE_ON_IOS_AND_WIN(NewOverflow)) {
159 const size_t kArraySize = 4096; 161 const size_t kArraySize = 4096;
160 // We want something "dynamic" here, so that the compiler doesn't 162 // We want something "dynamic" here, so that the compiler doesn't
161 // immediately reject crazy arrays. 163 // immediately reject crazy arrays.
162 const size_t kDynamicArraySize = HideValueFromCompiler(kArraySize); 164 const size_t kDynamicArraySize = HideValueFromCompiler(kArraySize);
163 // numeric_limits are still not constexpr until we switch to C++11, so we 165 // numeric_limits are still not constexpr until we switch to C++11, so we
164 // use an ugly cast. 166 // use an ugly cast.
165 const size_t kMaxSizeT = ~static_cast<size_t>(0); 167 const size_t kMaxSizeT = ~static_cast<size_t>(0);
166 ASSERT_EQ(numeric_limits<size_t>::max(), kMaxSizeT); 168 ASSERT_EQ(numeric_limits<size_t>::max(), kMaxSizeT);
167 const size_t kArraySize2 = kMaxSizeT / kArraySize + 10; 169 const size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
168 const size_t kDynamicArraySize2 = HideValueFromCompiler(kArraySize2); 170 const size_t kDynamicArraySize2 = HideValueFromCompiler(kArraySize2);
169 { 171 {
170 scoped_ptr<char[][kArraySize]> array_pointer(new (nothrow) 172 scoped_ptr<char[][kArraySize]> array_pointer(new (nothrow)
171 char[kDynamicArraySize2][kArraySize]); 173 char[kDynamicArraySize2][kArraySize]);
172 OverflowTestsSoftExpectTrue(array_pointer == NULL); 174 OverflowTestsSoftExpectTrue(!array_pointer);
173 } 175 }
174 { 176 {
175 scoped_ptr<char[][kArraySize2]> array_pointer(new (nothrow) 177 scoped_ptr<char[][kArraySize2]> array_pointer(new (nothrow)
176 char[kDynamicArraySize][kArraySize2]); 178 char[kDynamicArraySize][kArraySize2]);
177 OverflowTestsSoftExpectTrue(array_pointer == NULL); 179 OverflowTestsSoftExpectTrue(!array_pointer);
178 } 180 }
179 } 181 }
180 182
181 // Test if calloc() can overflow. Disable on ASAN for now since the 183 // Test if calloc() can overflow. Disable on ASAN for now since the
182 // overflow seems present there. 184 // overflow seems present there.
183 TEST(SecurityTest, DISABLE_ON_ASAN(CallocOverflow)) { 185 TEST(SecurityTest, DISABLE_ON_ASAN(CallocOverflow)) {
184 const size_t kArraySize = 4096; 186 const size_t kArraySize = 4096;
185 const size_t kMaxSizeT = numeric_limits<size_t>::max(); 187 const size_t kMaxSizeT = numeric_limits<size_t>::max();
186 const size_t kArraySize2 = kMaxSizeT / kArraySize + 10; 188 const size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
187 { 189 {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 // kRandomMask, so we use it as an additional detection mechanism. 269 // kRandomMask, so we use it as an additional detection mechanism.
268 const uintptr_t kRandomMask = 0x3fffffffffffULL; 270 const uintptr_t kRandomMask = 0x3fffffffffffULL;
269 bool impossible_random_address = 271 bool impossible_random_address =
270 reinterpret_cast<uintptr_t>(ptr.get()) & ~kRandomMask; 272 reinterpret_cast<uintptr_t>(ptr.get()) & ~kRandomMask;
271 EXPECT_FALSE(impossible_random_address); 273 EXPECT_FALSE(impossible_random_address);
272 } 274 }
273 275
274 #endif // (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__) 276 #endif // (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__)
275 277
276 } // namespace 278 } // namespace
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698