OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_ | |
6 #define MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_ | |
7 | |
8 #include "native_client/src/trusted/service_runtime/nacl_copy.h" | |
9 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | |
10 | |
11 namespace { | |
12 | |
13 class ScopedCopyLock { | |
14 public: | |
15 explicit ScopedCopyLock(struct NaClApp* nap) : nap_(nap) { | |
16 NaClCopyTakeLock(nap_); | |
17 } | |
18 ~ScopedCopyLock() { | |
19 NaClCopyDropLock(nap_); | |
20 } | |
21 private: | |
22 struct NaClApp* nap_; | |
23 }; | |
24 | |
25 static inline uintptr_t NaClUserToSysAddrArray( | |
26 struct NaClApp* nap, | |
27 uint32_t uaddr, | |
28 size_t count, | |
29 size_t size) { | |
30 // TODO(ncbray): overflow checking | |
31 size_t range = count * size; | |
32 return NaClUserToSysAddrRange(nap, uaddr, range); | |
33 } | |
34 | |
35 // We don't use plain-old memcpy because reads and writes to the untrusted | |
36 // address space from trusted code must be volatile. Non-volatile memory | |
37 // operations are dangerous because a compiler would be free to materialize a | |
38 // second load from the same memory address or materialize a load from a memory | |
39 // address that was stored, and assume the materialized load would return the | |
40 // same value as the previous load or store. Data races could cause the | |
41 // materialized load to return a different value, however, which could lead to | |
42 // time of check vs. time of use problems, or worse. For this binding code in | |
43 // particular, where memcpy is being called with a constant size, it is entirely | |
44 // conceivable the function will be inlined, unrolled, and optimized. | |
45 static inline void memcpy_volatile_out( | |
46 void volatile* dst, | |
47 const void* src, | |
48 size_t n) { | |
49 char volatile* c_dst = static_cast<char volatile*>(dst); | |
50 const char* c_src = static_cast<const char*>(src); | |
51 for (size_t i = 0; i < n; i++) { | |
52 c_dst[i] = c_src[i]; | |
53 } | |
54 } | |
55 | |
56 template <typename T> bool ConvertScalarInput( | |
57 struct NaClApp* nap, | |
58 uint32_t user_ptr, | |
59 T* value) { | |
60 if (user_ptr) { | |
61 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
62 if (temp != kNaClBadAddress) { | |
63 *value = *reinterpret_cast<T volatile*>(temp); | |
64 return true; | |
65 } | |
66 } | |
67 return false; | |
68 } | |
69 | |
70 template <typename T> bool ConvertScalarOutput( | |
71 struct NaClApp* nap, | |
72 uint32_t user_ptr, | |
73 bool optional, | |
74 T volatile** sys_ptr) { | |
75 if (user_ptr) { | |
76 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
77 if (temp != kNaClBadAddress) { | |
78 *sys_ptr = reinterpret_cast<T volatile*>(temp); | |
79 return true; | |
80 } | |
81 } else if (optional) { | |
82 *sys_ptr = 0; | |
83 return true; | |
84 } | |
85 *sys_ptr = 0; // Paranoia. | |
86 return false; | |
87 } | |
88 | |
89 template <typename T> bool ConvertScalarInOut( | |
90 struct NaClApp* nap, | |
91 uint32_t user_ptr, | |
92 bool optional, | |
93 T* value, | |
94 T volatile** sys_ptr) { | |
95 if (user_ptr) { | |
96 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
97 if (temp != kNaClBadAddress) { | |
98 T volatile* converted = reinterpret_cast<T volatile*>(temp); | |
99 *sys_ptr = converted; | |
100 *value = *converted; | |
101 return true; | |
102 } | |
103 } else if (optional) { | |
104 *sys_ptr = 0; | |
105 *value = static_cast<T>(0); // Paranoia. | |
106 return true; | |
107 } | |
108 *sys_ptr = 0; // Paranoia. | |
109 *value = static_cast<T>(0); // Paranoia. | |
110 return false; | |
111 } | |
112 | |
113 template <typename T> bool ConvertArray( | |
114 struct NaClApp* nap, | |
115 uint32_t user_ptr, | |
116 uint32_t length, | |
117 size_t element_size, | |
118 bool optional, | |
119 T** sys_ptr) { | |
120 if (user_ptr) { | |
121 uintptr_t temp = NaClUserToSysAddrArray(nap, user_ptr, length, | |
122 element_size); | |
123 if (temp != kNaClBadAddress) { | |
124 *sys_ptr = reinterpret_cast<T*>(temp); | |
125 return true; | |
126 } | |
127 } else if (optional) { | |
128 *sys_ptr = 0; | |
129 return true; | |
130 } | |
131 return false; | |
132 } | |
133 | |
134 template <typename T> bool ConvertBytes( | |
135 struct NaClApp* nap, | |
136 uint32_t user_ptr, | |
137 uint32_t length, | |
138 bool optional, | |
139 T** sys_ptr) { | |
140 if (user_ptr) { | |
141 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, length); | |
142 if (temp != kNaClBadAddress) { | |
143 *sys_ptr = reinterpret_cast<T*>(temp); | |
144 return true; | |
145 } | |
146 } else if (optional) { | |
147 *sys_ptr = 0; | |
148 return true; | |
149 } | |
150 return false; | |
151 } | |
152 | |
153 // TODO(ncbray): size validation and complete copy. | |
154 // TODO(ncbray): ensure non-null / missized structs are covered by a test case. | |
155 template <typename T> bool ConvertExtensibleStructInput( | |
156 struct NaClApp* nap, | |
157 uint32_t user_ptr, | |
158 bool optional, | |
159 T** sys_ptr) { | |
160 if (user_ptr) { | |
161 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
162 if (temp != kNaClBadAddress) { | |
163 *sys_ptr = reinterpret_cast<T*>(temp); | |
164 return true; | |
165 } | |
166 } else if (optional) { | |
167 *sys_ptr = 0; | |
168 return true; | |
169 } | |
170 return false; | |
171 } | |
172 | |
173 } // namespace | |
174 | |
175 #endif // MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_ | |
OLD | NEW |