OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |