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

Side by Side Diff: third_party/tcmalloc/chromium/src/system-alloc.cc

Issue 12093035: TCMalloc: support userland ASLR on Linux (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove "using" statement to make Windows happy. 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 | « base/security_unittest.cc ('k') | 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) 2005, Google Inc. 1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 // Check that no bit is set at position ADDRESS_BITS or higher. 93 // Check that no bit is set at position ADDRESS_BITS or higher.
94 template <int ADDRESS_BITS> bool CheckAddressBits(uintptr_t ptr) { 94 template <int ADDRESS_BITS> bool CheckAddressBits(uintptr_t ptr) {
95 return (ptr >> ADDRESS_BITS) == 0; 95 return (ptr >> ADDRESS_BITS) == 0;
96 } 96 }
97 97
98 // Specialize for the bit width of a pointer to avoid undefined shift. 98 // Specialize for the bit width of a pointer to avoid undefined shift.
99 template <> bool CheckAddressBits<8 * sizeof(void*)>(uintptr_t ptr) { 99 template <> bool CheckAddressBits<8 * sizeof(void*)>(uintptr_t ptr) {
100 return true; 100 return true;
101 } 101 }
102 102
103 // From libdieharder, public domain library by Bob Jenkins (rngav.c).
104 // Described at http://burtleburtle.net/bob/rand/smallprng.html.
105 // Not cryptographically secure, but good enough for what we need.
jar (doing other things) 2013/01/30 02:29:13 Why are we using this, rather than more standard c
jln (very slow on Chromium) 2013/01/30 02:52:13 What would be a more standard crypto function ? We
106 typedef uint32_t u4;
107 typedef struct ranctx { u4 a; u4 b; u4 c; u4 d; } ranctx;
108
109 #define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
110
111 u4 ranval(ranctx* x) {
112 /* xxx: the generator being tested */
113 u4 e = x->a - rot(x->b, 27);
114 x->a = x->b ^ rot(x->c, 17);
115 x->b = x->c + x->d;
116 x->c = x->d + e;
117 x->d = e + x->a;
118 return x->d;
119 }
120
121 void raninit(ranctx* x, u4 seed) {
122 u4 i;
123 x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
124 for (i=0; i<20; ++i) {
125 (void)ranval(x);
126 }
127 }
128
129 // End PRNG code.
130
131 #define ASLR_IS_SUPPORTED \\
jar (doing other things) 2013/01/30 02:29:13 I doubt you meant to postpend a double backslash..
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
132 (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(__x86_64__)
jar (doing other things) 2013/01/30 02:29:13 "defined" is only meaningful in the context of a "
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
133
134 // Give a random "hint" that is suitable for use with mmap(). This cannot make
135 // mmap fail , as the kernel will simply not follow the hint if it can't.
jar (doing other things) 2013/01/30 02:29:13 nit: Remove extra space: "fail , as" ---> "fail,
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
136 // However, this will create address space fragmentation. Currently, we only
137 // implement it on x86_64, where we have a 47 bits userland address space and
138 // fragmentation is not an issue.
139 void* GetRandomAddrHint() {
140 #if defined(ASLR_IS_SUPPORTED)
jar (doing other things) 2013/01/30 02:29:13 I'm pretty sure this will always evaluate to true,
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
141 // Note: we are protected by the general TCMalloc_SystemAlloc spinlock. Given
142 // the nature of what we're doing, it wouldn't be critical if we weren't.
143 // It's nice to share the state between threads, because scheduling will add
144 // some randomness to the succession of ranval() calls.
145 static ranctx ctx;
146 static bool initialized = false;
147 if (!initialized) {
148 volatile char c;
jar (doing other things) 2013/01/30 02:29:13 Why did you use the keyword volatile here? What d
jln (very slow on Chromium) 2013/01/30 02:52:13 I'm trying to tame a potential processor optimizat
149 // Pre-initialize our seed with a "random" address in case /dev/urandom is
150 // not available.
151 uint32_t seed = (reinterpret_cast<uint64_t>(&c) >> 32) ^
152 reinterpret_cast<uint64_t>(&c);
153 int urandom_fd = open("/dev/urandom", O_RDONLY);
154 if (urandom_fd >= 0) {
155 ssize_t len;
156 len = read(urandom_fd, &seed, sizeof(seed));
157 ASSERT(len == sizeof(seed));
158 int ret = close(urandom_fd);
159 ASSERT(ret == 0);
160 }
161 raninit(&ctx, seed);
162 initialized = true;
jar (doing other things) 2013/01/30 02:29:13 FWIW: the compiler can optimize this line to perfo
jln (very slow on Chromium) 2013/01/30 02:52:13 Yes, that comment was for the ranctx, but you're r
163 }
164 uint64_t random_address = (static_cast<uint64_t>(ranval(&ctx)) << 32) |
165 ranval(&ctx);
166 // If the kernel cannot honor the hint in arch_get_unmapped_area_topdown, it
167 // will simply ignore it. So we give a hint that has a good chance of
168 // working.
169 // The mmap top-down allocator will normally allocate below TASK_SIZE - gap,
170 // with a gap that depends on the max stack size. See x86/mm/mmap.c. We
171 // should make allocations that are below this area, which would be
172 // 0x7ffbf8000000.
173 // We use 0x3ffffffff000 as the mask so that we only "pollute" half of the
174 // address space. In the unlikely case where fragmentation would become an
175 // issue, the kernel will still have another half to use.
176 // A a bit-wise "and" won't bias our random distribution.
177 random_address &= 0x3ffffffff000ULL;
178 return reinterpret_cast<void*>(random_address);
179 #else
180 return NULL;
jar (doing other things) 2013/01/30 02:29:13 nit: With if's (and certainly #if), it is much eas
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
181 #endif // ASLR_IS_SUPPORTED
182 }
183
103 } // Anonymous namespace to avoid name conflicts on "CheckAddressBits". 184 } // Anonymous namespace to avoid name conflicts on "CheckAddressBits".
104 185
105 COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*), 186 COMPILE_ASSERT(kAddressBits <= 8 * sizeof(void*),
106 address_bits_larger_than_pointer_size); 187 address_bits_larger_than_pointer_size);
107 188
108 // Structure for discovering alignment 189 // Structure for discovering alignment
109 union MemoryAligner { 190 union MemoryAligner {
110 void* p; 191 void* p;
111 double d; 192 double d;
112 size_t s; 193 size_t s;
(...skipping 19 matching lines...) Expand all
132 EnvToInt("TCMALLOC_DEVMEM_LIMIT", 0), 213 EnvToInt("TCMALLOC_DEVMEM_LIMIT", 0),
133 "Physical memory limit location in MB for /dev/mem allocation." 214 "Physical memory limit location in MB for /dev/mem allocation."
134 " Setting this to 0 means no limit."); 215 " Setting this to 0 means no limit.");
135 DEFINE_bool(malloc_skip_sbrk, 216 DEFINE_bool(malloc_skip_sbrk,
136 EnvToBool("TCMALLOC_SKIP_SBRK", false), 217 EnvToBool("TCMALLOC_SKIP_SBRK", false),
137 "Whether sbrk can be used to obtain memory."); 218 "Whether sbrk can be used to obtain memory.");
138 DEFINE_bool(malloc_skip_mmap, 219 DEFINE_bool(malloc_skip_mmap,
139 EnvToBool("TCMALLOC_SKIP_MMAP", false), 220 EnvToBool("TCMALLOC_SKIP_MMAP", false),
140 "Whether mmap can be used to obtain memory."); 221 "Whether mmap can be used to obtain memory.");
141 222
223 DEFINE_bool(malloc_random_allocator,
224 EnvToBool("TCMALLOC_ASLR",
225 #if defined(ASLR_IS_SUPPORTED)
jar (doing other things) 2013/01/30 02:29:13 As noted, this is always true here :-(.
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
226 true),
jar (doing other things) 2013/01/30 02:29:13 nit: breaking coded fragments (single short lines)
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
227 #else
228 false),
229 #endif
230 "Whether to randomize the address space via mmap().");
231
142 // static allocators 232 // static allocators
143 class SbrkSysAllocator : public SysAllocator { 233 class SbrkSysAllocator : public SysAllocator {
144 public: 234 public:
145 SbrkSysAllocator() : SysAllocator() { 235 SbrkSysAllocator() : SysAllocator() {
146 } 236 }
147 void* Alloc(size_t size, size_t *actual_size, size_t alignment); 237 void* Alloc(size_t size, size_t *actual_size, size_t alignment);
148 }; 238 };
149 static char sbrk_space[sizeof(SbrkSysAllocator)]; 239 static char sbrk_space[sizeof(SbrkSysAllocator)];
150 240
151 class MmapSysAllocator : public SysAllocator { 241 class MmapSysAllocator : public SysAllocator {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 // Ask for extra memory if alignment > pagesize 387 // Ask for extra memory if alignment > pagesize
298 size_t extra = 0; 388 size_t extra = 0;
299 if (alignment > pagesize) { 389 if (alignment > pagesize) {
300 extra = alignment - pagesize; 390 extra = alignment - pagesize;
301 } 391 }
302 392
303 // Note: size + extra does not overflow since: 393 // Note: size + extra does not overflow since:
304 // size + alignment < (1<<NBITS). 394 // size + alignment < (1<<NBITS).
305 // and extra <= alignment 395 // and extra <= alignment
306 // therefore size + extra < (1<<NBITS) 396 // therefore size + extra < (1<<NBITS)
307 void* result = mmap(NULL, size + extra, 397 void* address_hint = NULL;
398 if (FLAGS_malloc_random_allocator) {
399 address_hint = GetRandomAddrHint();
400 }
401 void* result = mmap(address_hint, size + extra,
308 PROT_READ|PROT_WRITE, 402 PROT_READ|PROT_WRITE,
309 MAP_PRIVATE|MAP_ANONYMOUS, 403 MAP_PRIVATE|MAP_ANONYMOUS,
310 -1, 0); 404 -1, 0);
311 if (result == reinterpret_cast<void*>(MAP_FAILED)) { 405 if (result == reinterpret_cast<void*>(MAP_FAILED)) {
312 return NULL; 406 return NULL;
313 } 407 }
314 408
315 // Adjust the return memory so it is aligned 409 // Adjust the return memory so it is aligned
316 uintptr_t ptr = reinterpret_cast<uintptr_t>(result); 410 uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
317 size_t adjust = 0; 411 size_t adjust = 0;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 failed_[i] = false; 532 failed_[i] = false;
439 } 533 }
440 return NULL; 534 return NULL;
441 } 535 }
442 536
443 static bool system_alloc_inited = false; 537 static bool system_alloc_inited = false;
444 void InitSystemAllocators(void) { 538 void InitSystemAllocators(void) {
445 MmapSysAllocator *mmap = new (mmap_space) MmapSysAllocator(); 539 MmapSysAllocator *mmap = new (mmap_space) MmapSysAllocator();
446 SbrkSysAllocator *sbrk = new (sbrk_space) SbrkSysAllocator(); 540 SbrkSysAllocator *sbrk = new (sbrk_space) SbrkSysAllocator();
447 541
542 DefaultSysAllocator *sdef = new (default_space) DefaultSysAllocator();
543
544 // Unfortunately, this code runs before flags are initialized. So
545 // we can't use FLAGS_malloc_random_allocator.
546 #if defined(ASLR_IS_SUPPORTED)
547 // Our only random allocator is mmap.
548 sdef->SetChildAllocator(mmap, 0, mmap_name);
jar (doing other things) 2013/01/30 02:29:13 Instead of moving line at 455 up to line 542 above
jln (very slow on Chromium) 2013/01/30 02:52:13 Done.
549 #else
448 // In 64-bit debug mode, place the mmap allocator first since it 550 // In 64-bit debug mode, place the mmap allocator first since it
449 // allocates pointers that do not fit in 32 bits and therefore gives 551 // allocates pointers that do not fit in 32 bits and therefore gives
450 // us better testing of code's 64-bit correctness. It also leads to 552 // us better testing of code's 64-bit correctness. It also leads to
451 // less false negatives in heap-checking code. (Numbers are less 553 // less false negatives in heap-checking code. (Numbers are less
452 // likely to look like pointers and therefore the conservative gc in 554 // likely to look like pointers and therefore the conservative gc in
453 // the heap-checker is less likely to misinterpret a number as a 555 // the heap-checker is less likely to misinterpret a number as a
454 // pointer). 556 // pointer).
455 DefaultSysAllocator *sdef = new (default_space) DefaultSysAllocator();
456 if (kDebugMode && sizeof(void*) > 4) { 557 if (kDebugMode && sizeof(void*) > 4) {
457 sdef->SetChildAllocator(mmap, 0, mmap_name); 558 sdef->SetChildAllocator(mmap, 0, mmap_name);
458 sdef->SetChildAllocator(sbrk, 1, sbrk_name); 559 sdef->SetChildAllocator(sbrk, 1, sbrk_name);
jar (doing other things) 2013/01/30 02:29:13 Why is this line not included in the new ASLR code
jln (very slow on Chromium) 2013/01/30 02:52:13 At first, I thought we didn't want a fallback to t
459 } else { 560 } else {
460 sdef->SetChildAllocator(sbrk, 0, sbrk_name); 561 sdef->SetChildAllocator(sbrk, 0, sbrk_name);
461 sdef->SetChildAllocator(mmap, 1, mmap_name); 562 sdef->SetChildAllocator(mmap, 1, mmap_name);
462 } 563 }
564 #endif // ASLR_IS_SUPPORTED
463 sys_alloc = sdef; 565 sys_alloc = sdef;
464 } 566 }
465 567
466 void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, 568 void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
467 size_t alignment) { 569 size_t alignment) {
468 // Discard requests that overflow 570 // Discard requests that overflow
469 if (size + alignment < size) return NULL; 571 if (size + alignment < size) return NULL;
470 572
471 SpinLockHolder lock_holder(&spinlock); 573 SpinLockHolder lock_holder(&spinlock);
472 574
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 } 642 }
541 } 643 }
542 #endif 644 #endif
543 } 645 }
544 646
545 void TCMalloc_SystemCommit(void* start, size_t length) { 647 void TCMalloc_SystemCommit(void* start, size_t length) {
546 // Nothing to do here. TCMalloc_SystemRelease does not alter pages 648 // Nothing to do here. TCMalloc_SystemRelease does not alter pages
547 // such that they need to be re-committed before they can be used by the 649 // such that they need to be re-committed before they can be used by the
548 // application. 650 // application.
549 } 651 }
OLDNEW
« no previous file with comments | « base/security_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698