1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "wtf/AddressSpaceRandomization.h"
8 #include "wtf/PageAllocator.h"
9 #include "wtf/SpinLock.h"
22 // This is the same PRNG as used by tcmalloc for mapping address randomness;
23 // see http://burtleburtle.net/bob/rand/smallprng.html
33 #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
35 uint32_t ranvalInternal(ranctx
* x
)
37 uint32_t e
= x
->a
- rot(x
->b
, 27);
38 x
->a
= x
->b
^ rot(x
->c
, 17);
47 uint32_t ranval(ranctx
* x
)
49 spinLockLock(&x
->lock
);
50 if (UNLIKELY(!x
->initialized
)) {
51 x
->initialized
= true;
53 uint32_t seed
= static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&c
));
57 pid
= GetCurrentProcessId();
60 usec
= static_cast<uint32_t>(st
.wMilliseconds
* 1000);
62 pid
= static_cast<uint32_t>(getpid());
65 usec
= static_cast<uint32_t>(tv
.tv_usec
);
70 x
->b
= x
->c
= x
->d
= seed
;
71 for (int i
= 0; i
< 20; ++i
) {
72 (void) ranvalInternal(x
);
75 uint32_t ret
= ranvalInternal(x
);
76 spinLockUnlock(&x
->lock
);
80 static struct ranctx s_ranctx
;
84 // Calculates a random preferred mapping address. In calculating an
85 // address, we balance good ASLR against not fragmenting the address
87 void* getRandomPageBase()
90 random
= static_cast<uintptr_t>(ranval(&s_ranctx
));
93 random
|= static_cast<uintptr_t>(ranval(&s_ranctx
));
94 // This address mask gives a low liklihood of address space collisions.
95 // We handle the situation gracefully if there is a collision.
97 // 64-bit Windows has a bizarrely small 8TB user address space.
98 // Allocates in the 1-5TB region.
99 // TODO(cevans): I think Win 8.1 has 47-bits like Linux.
100 random
&= 0x3ffffffffffUL
;
101 random
+= 0x10000000000UL
;
103 // Linux and OS X support the full 47-bit user space of x64 processors.
104 random
&= 0x3fffffffffffUL
;
107 // ARM64 on Linux has 39-bit user space.
108 random
&= 0x3fffffffffUL
;
109 random
+= 0x1000000000UL
;
110 #else // !CPU(X86_64) && !CPU(ARM64)
111 // This is a good range on Windows, Linux and Mac.
112 // Allocates in the 0.5-1.5GB region.
113 random
&= 0x3fffffff;
114 random
+= 0x20000000;
115 #endif // CPU(X86_64)
116 random
&= kPageAllocationGranularityBaseMask
;
117 return reinterpret_cast<void*>(random
);