1 : /*
2 : * Copyright (c) 2010 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 :
8 : #include <windows.h>
9 :
10 : #include "native_client/src/shared/platform/nacl_find_addrsp.h"
11 :
12 : #include "native_client/src/include/nacl_base.h"
13 : #include "native_client/src/include/portability.h"
14 : #include "native_client/src/shared/platform/nacl_check.h"
15 : #include "native_client/src/shared/platform/nacl_global_secure_random.h"
16 : #include "native_client/src/shared/platform/nacl_log.h"
17 :
18 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
19 : /*
20 : * The x86-64 (currently) permits only a 48 bit virtual address space
21 : * (and requires that the upper 64-48=16 bits is sign extended from
22 : * bit 47). Additionally, (empirically) Windows 8 disallows addresses
23 : * with bits 44 and above set for user-space code. So instead of 48,
24 : * we get a maximum of 43 usable bits of virtual address.
25 : */
26 : # define NUM_USER_ADDRESS_BITS 43
27 : /*
28 : * Windows is P64 and not LP64
29 : */
30 : # define NACL_POINTER_SIZE 64
31 : #else
32 : # define NUM_USER_ADDRESS_BITS 31
33 : # define NACL_POINTER_SIZE 32
34 : #endif
35 :
36 :
37 : /* bool */
38 : int NaClFindAddressSpaceRandomized(uintptr_t *addr, size_t memory_size,
39 3 : int max_tries) {
40 : void *map_addr;
41 : int tries_remaining;
42 : /*
43 : * Mask for keeping the low order NUM_USER_ADDRESS_BITS of a randomly
44 : * generated address. VirtualAlloc will drop the low 16 bits for
45 : * MEM_RESERVE, so we do not need to mask those off.
46 : */
47 : uintptr_t addr_mask;
48 : uintptr_t suggested_addr;
49 :
50 3 : CHECK(max_tries >= 0);
51 : NaClLog(4,
52 : "NaClFindAddressSpaceRandomized: looking for %"NACL_PRIxS" bytes\n",
53 3 : memory_size);
54 :
55 : /* 64kB allocation size */
56 3 : addr_mask = ~(uintptr_t) 0;
57 : #if NACL_POINTER_SIZE > NUM_USER_ADDRESS_BITS
58 3 : addr_mask &= (((uintptr_t) 1 << NUM_USER_ADDRESS_BITS) - 1);
59 : #endif
60 :
61 3 : for (tries_remaining = max_tries; tries_remaining >= 0; --tries_remaining) {
62 3 : if (tries_remaining > 0) {
63 : /* Pick a random address for the first max_tries */
64 : #if NACL_POINTER_SIZE > 32
65 : suggested_addr = (((uintptr_t) NaClGlobalSecureRngUint32() << 32) |
66 : (uintptr_t) NaClGlobalSecureRngUint32());
67 : #else
68 0 : suggested_addr = ((uintptr_t) NaClGlobalSecureRngUint32());
69 : #endif
70 0 : suggested_addr &= addr_mask;
71 0 : } else {
72 : /* Give up picking randomly -- now just let the system pick */
73 3 : suggested_addr = 0;
74 : }
75 :
76 : NaClLog(4,
77 : ("NaClFindAddressSpaceRandomized: try %d: starting addr hint %"
78 : NACL_PRIxPTR"\n"),
79 : max_tries - tries_remaining,
80 3 : suggested_addr);
81 : map_addr = VirtualAlloc((void *) suggested_addr,
82 3 : memory_size, MEM_RESERVE, PAGE_READWRITE);
83 3 : if (NULL != map_addr) {
84 : /* success */
85 3 : break;
86 : }
87 0 : }
88 3 : if (NULL == map_addr) {
89 : NaClLog(LOG_ERROR,
90 : ("NaClFindAddressSpaceRandomized: VirtualAlloc failed looking for"
91 : " 0x%"NACL_PRIxS" bytes\n"),
92 0 : memory_size);
93 0 : return 0;
94 : }
95 3 : if (!VirtualFree(map_addr, 0, MEM_RELEASE)) {
96 : NaClLog(LOG_FATAL,
97 : ("NaClFindAddressSpaceRandomized: VirtualFree of VirtualAlloc"
98 : " result (0x%"NACL_PRIxPTR"failed, GetLastError %d.\n"),
99 : (uintptr_t) map_addr,
100 0 : GetLastError());
101 : }
102 : NaClLog(4,
103 : "NaClFindAddressSpaceRandomized: got addr %"NACL_PRIxPTR"\n",
104 3 : (uintptr_t) map_addr);
105 3 : *addr = (uintptr_t) map_addr;
106 3 : return 1;
107 3 : }
108 :
109 3 : int NaClFindAddressSpace(uintptr_t *addr, size_t memory_size) {
110 3 : return NaClFindAddressSpaceRandomized(addr, memory_size, 0);
111 3 : }
|