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.
5 #ifndef MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_
6 #define MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_
8 #include "native_client/src/trusted/service_runtime/nacl_copy.h"
9 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
13 class ScopedCopyLock
{
15 explicit ScopedCopyLock(struct NaClApp
* nap
) : nap_(nap
) {
16 NaClCopyTakeLock(nap_
);
19 NaClCopyDropLock(nap_
);
25 static inline uintptr_t NaClUserToSysAddrArray(
30 // TODO(ncbray): overflow checking
31 size_t range
= count
* size
;
32 return NaClUserToSysAddrRange(nap
, uaddr
, range
);
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(
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
++) {
56 template <typename T
> bool ConvertScalarInput(
61 uintptr_t temp
= NaClUserToSysAddrRange(nap
, user_ptr
, sizeof(T
));
62 if (temp
!= kNaClBadAddress
) {
63 *value
= *reinterpret_cast<T
volatile*>(temp
);
70 template <typename T
> bool ConvertScalarOutput(
74 T
volatile** sys_ptr
) {
76 uintptr_t temp
= NaClUserToSysAddrRange(nap
, user_ptr
, sizeof(T
));
77 if (temp
!= kNaClBadAddress
) {
78 *sys_ptr
= reinterpret_cast<T
volatile*>(temp
);
81 } else if (optional
) {
85 *sys_ptr
= 0; // Paranoia.
89 template <typename T
> bool ConvertScalarInOut(
94 T
volatile** sys_ptr
) {
96 uintptr_t temp
= NaClUserToSysAddrRange(nap
, user_ptr
, sizeof(T
));
97 if (temp
!= kNaClBadAddress
) {
98 T
volatile* converted
= reinterpret_cast<T
volatile*>(temp
);
103 } else if (optional
) {
105 *value
= static_cast<T
>(0); // Paranoia.
108 *sys_ptr
= 0; // Paranoia.
109 *value
= static_cast<T
>(0); // Paranoia.
113 template <typename T
> bool ConvertArray(
121 uintptr_t temp
= NaClUserToSysAddrArray(nap
, user_ptr
, length
,
123 if (temp
!= kNaClBadAddress
) {
124 *sys_ptr
= reinterpret_cast<T
*>(temp
);
127 } else if (optional
) {
134 template <typename T
> bool ConvertBytes(
141 uintptr_t temp
= NaClUserToSysAddrRange(nap
, user_ptr
, length
);
142 if (temp
!= kNaClBadAddress
) {
143 *sys_ptr
= reinterpret_cast<T
*>(temp
);
146 } else if (optional
) {
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(
161 uintptr_t temp
= NaClUserToSysAddrRange(nap
, user_ptr
, sizeof(T
));
162 if (temp
!= kNaClBadAddress
) {
163 *sys_ptr
= reinterpret_cast<T
*>(temp
);
166 } else if (optional
) {
175 #endif // MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_