| 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 <type_traits> | |
| 9 | |
| 10 #include "native_client/src/trusted/service_runtime/nacl_copy.h" | |
| 11 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 class ScopedCopyLock { | |
| 16 public: | |
| 17 explicit ScopedCopyLock(struct NaClApp* nap) : nap_(nap) { | |
| 18 NaClCopyTakeLock(nap_); | |
| 19 } | |
| 20 ~ScopedCopyLock() { NaClCopyDropLock(nap_); } | |
| 21 | |
| 22 private: | |
| 23 struct NaClApp* nap_; | |
| 24 }; | |
| 25 | |
| 26 static inline uintptr_t NaClUserToSysAddrArray(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(void volatile* dst, | |
| 46 const void* src, | |
| 47 size_t n) { | |
| 48 char volatile* c_dst = static_cast<char volatile*>(dst); | |
| 49 const char* c_src = static_cast<const char*>(src); | |
| 50 for (size_t i = 0; i < n; i++) { | |
| 51 c_dst[i] = c_src[i]; | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 template <typename T> | |
| 56 bool ConvertPointerInput(struct NaClApp* nap, uint32_t user_ptr, T** value) { | |
| 57 if (user_ptr) { | |
| 58 uintptr_t temp = NaClUserToSysAddr(nap, user_ptr); | |
| 59 if (temp != kNaClBadAddress) { | |
| 60 *value = reinterpret_cast<T*>(temp); | |
| 61 return true; | |
| 62 } | |
| 63 } else { | |
| 64 *value = nullptr; | |
| 65 return true; | |
| 66 } | |
| 67 *value = nullptr; // Paranoia. | |
| 68 return false; | |
| 69 } | |
| 70 | |
| 71 template <typename T> | |
| 72 bool ConvertPointerInOut(struct NaClApp* nap, | |
| 73 uint32_t user_ptr, | |
| 74 bool optional, | |
| 75 T** value, | |
| 76 uint32_t volatile** sys_ptr) { | |
| 77 if (user_ptr) { | |
| 78 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(uint32_t)); | |
| 79 if (temp != kNaClBadAddress) { | |
| 80 uint32_t volatile* converted_ptr = | |
| 81 reinterpret_cast<uint32_t volatile*>(temp); | |
| 82 uint32_t raw_value = *converted_ptr; | |
| 83 if (!raw_value) { | |
| 84 *sys_ptr = converted_ptr; | |
| 85 *value = nullptr; | |
| 86 return true; | |
| 87 } | |
| 88 uintptr_t temp = NaClUserToSysAddr(nap, raw_value); | |
| 89 if (temp != kNaClBadAddress) { | |
| 90 *sys_ptr = converted_ptr; | |
| 91 *value = reinterpret_cast<T*>(temp); | |
| 92 return true; | |
| 93 } | |
| 94 } | |
| 95 } else if (optional) { | |
| 96 *sys_ptr = nullptr; | |
| 97 *value = nullptr; // Paranoia. | |
| 98 return true; | |
| 99 } | |
| 100 *sys_ptr = nullptr; // Paranoia. | |
| 101 *value = nullptr; // Paranoia. | |
| 102 return false; | |
| 103 } | |
| 104 | |
| 105 template <typename T> | |
| 106 void CopyOutPointer(struct NaClApp* nap, T* value, uint32_t volatile* sys_ptr) { | |
| 107 if (value) { | |
| 108 // Will kill the process if value if the pointer does not lie in the | |
| 109 // sandbox. | |
| 110 uintptr_t temp = NaClSysToUser(nap, reinterpret_cast<uintptr_t>(value)); | |
| 111 *sys_ptr = static_cast<uint32_t>(temp); | |
| 112 } else { | |
| 113 *sys_ptr = 0; | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 template <typename T> | |
| 118 bool ConvertScalarInput(struct NaClApp* nap, uint32_t user_ptr, T* value) { | |
| 119 static_assert(!std::is_pointer<T>::value, "do not use for pointer types"); | |
| 120 if (user_ptr) { | |
| 121 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
| 122 if (temp != kNaClBadAddress) { | |
| 123 *value = *reinterpret_cast<T volatile*>(temp); | |
| 124 return true; | |
| 125 } | |
| 126 } | |
| 127 return false; | |
| 128 } | |
| 129 | |
| 130 template <typename T> | |
| 131 bool ConvertScalarOutput(struct NaClApp* nap, | |
| 132 uint32_t user_ptr, | |
| 133 bool optional, | |
| 134 T volatile** sys_ptr) { | |
| 135 static_assert(!std::is_pointer<T>::value, "do not use for pointer types"); | |
| 136 if (user_ptr) { | |
| 137 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
| 138 if (temp != kNaClBadAddress) { | |
| 139 *sys_ptr = reinterpret_cast<T volatile*>(temp); | |
| 140 return true; | |
| 141 } | |
| 142 } else if (optional) { | |
| 143 *sys_ptr = 0; | |
| 144 return true; | |
| 145 } | |
| 146 *sys_ptr = 0; // Paranoia. | |
| 147 return false; | |
| 148 } | |
| 149 | |
| 150 template <typename T> | |
| 151 bool ConvertScalarInOut(struct NaClApp* nap, | |
| 152 uint32_t user_ptr, | |
| 153 bool optional, | |
| 154 T* value, | |
| 155 T volatile** sys_ptr) { | |
| 156 static_assert(!std::is_pointer<T>::value, "do not use for pointer types"); | |
| 157 if (user_ptr) { | |
| 158 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
| 159 if (temp != kNaClBadAddress) { | |
| 160 T volatile* converted = reinterpret_cast<T volatile*>(temp); | |
| 161 *sys_ptr = converted; | |
| 162 *value = *converted; | |
| 163 return true; | |
| 164 } | |
| 165 } else if (optional) { | |
| 166 *sys_ptr = 0; | |
| 167 *value = static_cast<T>(0); // Paranoia. | |
| 168 return true; | |
| 169 } | |
| 170 *sys_ptr = 0; // Paranoia. | |
| 171 *value = static_cast<T>(0); // Paranoia. | |
| 172 return false; | |
| 173 } | |
| 174 | |
| 175 template <typename T> | |
| 176 bool ConvertArray(struct NaClApp* nap, | |
| 177 uint32_t user_ptr, | |
| 178 uint32_t length, | |
| 179 size_t element_size, | |
| 180 bool optional, | |
| 181 T** sys_ptr) { | |
| 182 if (user_ptr) { | |
| 183 uintptr_t temp = | |
| 184 NaClUserToSysAddrArray(nap, user_ptr, length, element_size); | |
| 185 if (temp != kNaClBadAddress) { | |
| 186 *sys_ptr = reinterpret_cast<T*>(temp); | |
| 187 return true; | |
| 188 } | |
| 189 } else if (optional) { | |
| 190 *sys_ptr = 0; | |
| 191 return true; | |
| 192 } | |
| 193 return false; | |
| 194 } | |
| 195 | |
| 196 template <typename T> | |
| 197 bool ConvertBytes(struct NaClApp* nap, | |
| 198 uint32_t user_ptr, | |
| 199 uint32_t length, | |
| 200 bool optional, | |
| 201 T** sys_ptr) { | |
| 202 if (user_ptr) { | |
| 203 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, length); | |
| 204 if (temp != kNaClBadAddress) { | |
| 205 *sys_ptr = reinterpret_cast<T*>(temp); | |
| 206 return true; | |
| 207 } | |
| 208 } else if (optional) { | |
| 209 *sys_ptr = 0; | |
| 210 return true; | |
| 211 } | |
| 212 return false; | |
| 213 } | |
| 214 | |
| 215 // TODO(ncbray): size validation and complete copy. | |
| 216 // TODO(ncbray): ensure non-null / missized structs are covered by a test case. | |
| 217 template <typename T> | |
| 218 bool ConvertExtensibleStructInput(struct NaClApp* nap, | |
| 219 uint32_t user_ptr, | |
| 220 bool optional, | |
| 221 T** sys_ptr) { | |
| 222 static_assert(!std::is_pointer<T>::value, "do not use for pointer types"); | |
| 223 if (user_ptr) { | |
| 224 uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T)); | |
| 225 if (temp != kNaClBadAddress) { | |
| 226 *sys_ptr = reinterpret_cast<T*>(temp); | |
| 227 return true; | |
| 228 } | |
| 229 } else if (optional) { | |
| 230 *sys_ptr = 0; | |
| 231 return true; | |
| 232 } | |
| 233 return false; | |
| 234 } | |
| 235 | |
| 236 } // namespace | |
| 237 | |
| 238 #endif // MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_ | |
| OLD | NEW |