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
11namespace {
12
13class 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
25static 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
35template <typename T> bool ConvertScalarInput(
36    struct NaClApp* nap,
37    uint32_t user_ptr,
38    T* value) {
39  if (user_ptr) {
40    uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T));
41    if (temp != kNaClBadAddress) {
42      *value = *reinterpret_cast<T volatile*>(temp);
43      return true;
44    }
45  }
46  return false;
47}
48
49template <typename T> bool ConvertScalarOutput(
50    struct NaClApp* nap,
51    uint32_t user_ptr,
52    T volatile** sys_ptr) {
53  if (user_ptr) {
54    uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T));
55    if (temp != kNaClBadAddress) {
56      *sys_ptr = reinterpret_cast<T volatile*>(temp);
57      return true;
58    }
59  }
60  *sys_ptr = 0; // Paranoia.
61  return false;
62}
63
64template <typename T> bool ConvertScalarInOut(
65    struct NaClApp* nap,
66    uint32_t user_ptr,
67    bool optional,
68    T* value,
69    T volatile** sys_ptr) {
70  if (user_ptr) {
71    uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T));
72    if (temp != kNaClBadAddress) {
73      T volatile* converted = reinterpret_cast<T volatile*>(temp);
74      *sys_ptr = converted;
75      *value = *converted;
76      return true;
77    }
78  } else if (optional) {
79    *sys_ptr = 0;
80    *value = static_cast<T>(0); // Paranoia.
81    return true;
82  }
83  *sys_ptr = 0; // Paranoia.
84  *value = static_cast<T>(0); // Paranoia.
85  return false;
86}
87
88template <typename T> bool ConvertArray(
89    struct NaClApp* nap,
90    uint32_t user_ptr,
91    uint32_t length,
92    size_t element_size,
93    bool optional,
94    T** sys_ptr) {
95  if (user_ptr) {
96    uintptr_t temp = NaClUserToSysAddrArray(nap, user_ptr, length,
97                                            element_size);
98    if (temp != kNaClBadAddress) {
99      *sys_ptr = reinterpret_cast<T*>(temp);
100      return true;
101    }
102  } else if (optional) {
103    *sys_ptr = 0;
104    return true;
105  }
106  return false;
107}
108
109template <typename T> bool ConvertBytes(
110    struct NaClApp* nap,
111    uint32_t user_ptr,
112    uint32_t length,
113    bool optional,
114    T** sys_ptr) {
115  if (user_ptr) {
116    uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, length);
117    if (temp != kNaClBadAddress) {
118      *sys_ptr = reinterpret_cast<T*>(temp);
119      return true;
120    }
121  } else if (optional) {
122    *sys_ptr = 0;
123    return true;
124  }
125  return false;
126}
127
128// TODO(ncbray): size validation and complete copy.
129// TODO(ncbray): ensure non-null / missized structs are covered by a test case.
130template <typename T> bool ConvertStruct(
131    struct NaClApp* nap,
132    uint32_t user_ptr,
133    bool optional,
134    T** sys_ptr) {
135  if (user_ptr) {
136    uintptr_t temp = NaClUserToSysAddrRange(nap, user_ptr, sizeof(T));
137    if (temp != kNaClBadAddress) {
138      *sys_ptr = reinterpret_cast<T*>(temp);
139      return true;
140    }
141  } else if (optional) {
142    *sys_ptr = 0;
143    return true;
144  }
145  return false;
146}
147
148} // namespace
149
150#endif // MOJO_NACL_MOJO_SYSCALL_INTERNAL_H_
151