| 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 |