1 : // Copyright (c) 2012 The Native Client 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 : #include <limits>
6 : #include <new>
7 : #include "native_client/src/include/portability.h"
8 : #include "native_client/src/include/portability_string.h"
9 : #include "native_client/src/public/imc_types.h"
10 : #include "native_client/src/shared/imc/nacl_imc_c.h"
11 : #include "native_client/src/shared/platform/nacl_check.h"
12 : #include "native_client/src/shared/platform/nacl_log.h"
13 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
14 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
15 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
16 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
17 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
18 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
19 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
20 : #include "native_client/src/trusted/desc/nacl_desc_quota.h"
21 : #include "native_client/src/trusted/desc/nacl_desc_rng.h"
22 : #include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
23 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
24 : #include "native_client/src/trusted/desc/nrd_xfer.h"
25 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
26 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
27 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
28 :
29 : // TODO(polina): follow the style guide and replace "nhdp" and "ndiodp" with
30 : // "host_desc" and "io_desc"
31 :
32 : namespace {
33 :
34 14 : struct NaClDesc* OpenHostFileCommon(const char* fname, int flags, int mode) {
35 14 : struct NaClHostDesc* nhdp =
36 14 : reinterpret_cast<struct NaClHostDesc*>(calloc(1, sizeof(*nhdp)));
37 14 : if (NULL == nhdp) {
38 0 : return NULL;
39 : }
40 14 : if (0 != NaClHostDescOpen(nhdp, fname, flags, mode)) {
41 0 : free(nhdp);
42 0 : return NULL;
43 : }
44 14 : struct NaClDescIoDesc* ndiodp = NaClDescIoDescMake(nhdp);
45 14 : if (NULL == ndiodp) {
46 0 : if (0 != NaClHostDescClose(nhdp)) {
47 0 : NaClLog(LOG_FATAL, "OpenHostFileCommon: NaClHostDescClose failed\n");
48 0 : }
49 0 : free(nhdp);
50 0 : return NULL;
51 : }
52 14 : return reinterpret_cast<struct NaClDesc*>(ndiodp);
53 14 : }
54 :
55 0 : struct NaClDesc* MakeQuotaCommon(const uint8_t* file_id,
56 0 : struct NaClDesc* desc) {
57 0 : NaClDescQuota* ndqp =
58 0 : reinterpret_cast<NaClDescQuota*>(calloc(1, sizeof *ndqp));
59 0 : if ((NULL == ndqp) || !NaClDescQuotaCtor(ndqp, desc, file_id, NULL)) {
60 0 : free(ndqp);
61 0 : return NULL;
62 : }
63 0 : return reinterpret_cast<struct NaClDesc*>(ndqp);
64 0 : }
65 :
66 : } // namespace
67 :
68 : namespace nacl {
69 :
70 : // Descriptor creation and manipulation sometimes requires additional
71 : // state. Therefore, we create an object that encapsulates that
72 : // state.
73 : class DescWrapperCommon {
74 : friend class DescWrapperFactory;
75 :
76 : public:
77 : typedef uint32_t RefCountType;
78 :
79 : // Inform clients that the object was successfully initialized.
80 55 : bool is_initialized() const { return is_initialized_; }
81 :
82 : // Manipulate reference count
83 : DescWrapperCommon* Ref() {
84 : // TODO(sehr): replace with a reference count class when we have one.
85 124 : NaClXMutexLock(&ref_count_mu_);
86 124 : if (std::numeric_limits<RefCountType>::max() == ref_count_) {
87 0 : NaClLog(LOG_FATAL, "DescWrapperCommon ref count overflow\n");
88 0 : }
89 124 : ++ref_count_;
90 124 : NaClXMutexUnlock(&ref_count_mu_);
91 124 : return this;
92 : }
93 :
94 : void Unref() {
95 134 : NaClXMutexLock(&ref_count_mu_);
96 134 : if (0 == ref_count_) {
97 0 : NaClLog(LOG_FATAL, "DescWrapperCommon ref count already zero\n");
98 0 : }
99 134 : --ref_count_;
100 134 : bool destroy = (0 == ref_count_);
101 134 : NaClXMutexUnlock(&ref_count_mu_);
102 134 : if (destroy) {
103 102 : delete this;
104 34 : }
105 134 : }
106 :
107 : private:
108 52 : DescWrapperCommon() : is_initialized_(false), ref_count_(1) {
109 52 : NaClXMutexCtor(&ref_count_mu_);
110 104 : }
111 34 : ~DescWrapperCommon() {
112 34 : NaClMutexDtor(&ref_count_mu_);
113 68 : }
114 :
115 : // Set up the state. Returns true on success.
116 : bool Init();
117 :
118 : // Boolean to indicate the object was successfully initialized.
119 : bool is_initialized_;
120 : // The reference count and the mutex to protect it.
121 : RefCountType ref_count_;
122 : struct NaClMutex ref_count_mu_;
123 :
124 : DISALLOW_COPY_AND_ASSIGN(DescWrapperCommon);
125 : };
126 :
127 : bool DescWrapperCommon::Init() {
128 : // Successfully initialized.
129 52 : is_initialized_ = true;
130 52 : return true;
131 : }
132 :
133 : DescWrapperFactory::DescWrapperFactory() {
134 208 : common_data_ = new(std::nothrow) DescWrapperCommon();
135 52 : if (NULL == common_data_) {
136 0 : return;
137 : }
138 52 : if (!common_data_->Init()) {
139 0 : delete common_data_;
140 0 : common_data_ = NULL;
141 0 : }
142 104 : }
143 :
144 39 : DescWrapperFactory::~DescWrapperFactory() {
145 39 : if (NULL != common_data_) {
146 39 : common_data_->Unref();
147 39 : }
148 78 : }
149 :
150 0 : int DescWrapperFactory::MakeBoundSock(DescWrapper* pair[2]) {
151 0 : CHECK(common_data_->is_initialized());
152 :
153 0 : struct NaClDesc* descs[2] = { NULL, NULL };
154 0 : DescWrapper* tmp_pair[2] = { NULL, NULL };
155 :
156 0 : int ret = NaClCommonDescMakeBoundSock(descs);
157 0 : if (0 != ret) {
158 0 : return ret;
159 : }
160 0 : tmp_pair[0] = new(std::nothrow) DescWrapper(common_data_, descs[0]);
161 0 : if (NULL == tmp_pair[0]) {
162 0 : goto cleanup;
163 : }
164 0 : descs[0] = NULL; // DescWrapper took ownership of descs[0].
165 0 : tmp_pair[1] = new(std::nothrow) DescWrapper(common_data_, descs[1]);
166 0 : if (NULL == tmp_pair[1]) {
167 0 : goto cleanup;
168 : }
169 0 : descs[1] = NULL; // DescWrapper took ownership of descs[1].
170 0 : pair[0] = tmp_pair[0];
171 0 : pair[1] = tmp_pair[1];
172 0 : return 0;
173 :
174 : cleanup:
175 0 : NaClDescSafeUnref(descs[0]);
176 0 : NaClDescSafeUnref(descs[1]);
177 0 : delete tmp_pair[0];
178 0 : delete tmp_pair[1];
179 0 : return -1;
180 0 : }
181 :
182 34 : DescWrapper* DescWrapperFactory::MakeImcSock(NaClHandle handle) {
183 34 : struct NaClDescImcDesc* desc =
184 34 : reinterpret_cast<NaClDescImcDesc*>(calloc(1, sizeof *desc));
185 34 : if (NULL == desc) {
186 0 : return NULL;
187 : }
188 34 : if (!NaClDescImcDescCtor(desc, handle)) {
189 0 : free(desc);
190 0 : return NULL;
191 : }
192 :
193 34 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
194 34 : }
195 :
196 0 : DescWrapper* DescWrapperFactory::ImportShmHandle(NaClHandle handle,
197 0 : size_t size) {
198 0 : struct NaClDesc *desc = NaClDescImcShmMake(handle, size);
199 0 : if (desc == NULL) {
200 0 : return NULL;
201 : }
202 0 : return MakeGenericCleanup(desc);
203 0 : }
204 :
205 0 : DescWrapper* DescWrapperFactory::ImportSyncSocketHandle(NaClHandle handle) {
206 0 : struct NaClDesc *desc = NaClDescSyncSocketMake(handle);
207 0 : if (desc == NULL) {
208 0 : return NULL;
209 : }
210 0 : return MakeGenericCleanup(desc);
211 0 : }
212 :
213 0 : DescWrapper* DescWrapperFactory::MakeGeneric(struct NaClDesc* desc) {
214 0 : CHECK(common_data_->is_initialized());
215 0 : return new(std::nothrow) DescWrapper(common_data_, desc);
216 0 : }
217 :
218 :
219 55 : DescWrapper* DescWrapperFactory::MakeGenericCleanup(struct NaClDesc* desc) {
220 165 : CHECK(common_data_->is_initialized());
221 220 : DescWrapper* wrapper = new(std::nothrow) DescWrapper(common_data_, desc);
222 55 : if (NULL != wrapper) {
223 55 : return wrapper;
224 : }
225 0 : NaClDescSafeUnref(desc);
226 0 : return NULL;
227 55 : }
228 :
229 0 : int DescWrapperFactory::MakeSocketPair(DescWrapper* pair[2]) {
230 0 : CHECK(common_data_->is_initialized());
231 0 : struct NaClDesc* descs[2] = { NULL, NULL };
232 0 : DescWrapper* tmp_pair[2] = { NULL, NULL };
233 :
234 0 : int ret = NaClCommonDescSocketPair(descs);
235 0 : if (0 != ret) {
236 0 : return ret;
237 : }
238 0 : tmp_pair[0] = new(std::nothrow) DescWrapper(common_data_, descs[0]);
239 0 : if (NULL == tmp_pair[0]) {
240 0 : goto cleanup;
241 : }
242 0 : descs[0] = NULL; // DescWrapper took ownership of descs[0].
243 0 : tmp_pair[1] = new(std::nothrow) DescWrapper(common_data_, descs[1]);
244 0 : if (NULL == tmp_pair[1]) {
245 0 : goto cleanup;
246 : }
247 0 : descs[1] = NULL; // DescWrapper took ownership of descs[1].
248 0 : pair[0] = tmp_pair[0];
249 0 : pair[1] = tmp_pair[1];
250 0 : return 0;
251 :
252 : cleanup:
253 0 : NaClDescSafeUnref(descs[0]);
254 0 : NaClDescSafeUnref(descs[1]);
255 0 : delete tmp_pair[0];
256 0 : delete tmp_pair[1];
257 0 : return -1;
258 0 : }
259 :
260 0 : DescWrapper* DescWrapperFactory::MakeFileDesc(int host_os_desc, int mode) {
261 0 : struct NaClDesc* desc = NaClDescIoDescFromDescAllocCtor(host_os_desc, mode);
262 0 : if (NULL == desc) {
263 0 : return NULL;
264 : }
265 0 : return MakeGenericCleanup(desc);
266 0 : }
267 :
268 0 : DescWrapper* DescWrapperFactory::MakeFileDescQuota(int host_os_desc,
269 0 : int mode,
270 0 : const uint8_t* file_id) {
271 0 : struct NaClDesc* desc = NaClDescIoDescFromDescAllocCtor(host_os_desc, mode);
272 0 : if (NULL == desc) {
273 0 : return NULL;
274 : }
275 0 : struct NaClDesc* desc_quota = MakeQuotaCommon(file_id, desc);
276 0 : if (desc_quota == NULL) {
277 0 : NaClDescSafeUnref(desc);
278 0 : return NULL;
279 : }
280 0 : return MakeGenericCleanup(desc_quota);
281 0 : }
282 :
283 14 : DescWrapper* DescWrapperFactory::OpenHostFile(const char* fname,
284 14 : int flags,
285 14 : int mode) {
286 14 : struct NaClDesc* desc = OpenHostFileCommon(fname, flags, mode);
287 14 : if (NULL == desc) {
288 0 : return NULL;
289 : }
290 14 : return MakeGenericCleanup(desc);
291 14 : }
292 :
293 0 : DescWrapper* DescWrapperFactory::OpenHostFileQuota(const char* fname,
294 0 : int flags,
295 0 : int mode,
296 0 : const uint8_t* file_id) {
297 0 : struct NaClDesc* desc = OpenHostFileCommon(fname, flags, mode);
298 0 : if (NULL == desc) {
299 0 : return NULL;
300 : }
301 0 : struct NaClDesc* desc_quota = MakeQuotaCommon(file_id, desc);
302 0 : if (NULL == desc_quota) {
303 0 : NaClDescSafeUnref(desc);
304 0 : return NULL;
305 : }
306 0 : return MakeGenericCleanup(desc_quota);
307 0 : }
308 :
309 : DescWrapper* DescWrapperFactory::OpenRng() {
310 0 : struct NaClDescRng* nhrp =
311 0 : reinterpret_cast<struct NaClDescRng*>(calloc(1, sizeof(*nhrp)));
312 0 : if (NULL == nhrp) {
313 0 : return NULL;
314 : }
315 0 : if (!NaClDescRngCtor(nhrp)) {
316 0 : free(nhrp);
317 0 : return NULL;
318 : }
319 :
320 0 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(nhrp));
321 0 : }
322 :
323 : DescWrapper* DescWrapperFactory::MakeInvalid() {
324 0 : struct NaClDescInvalid *desc =
325 0 : const_cast<NaClDescInvalid*>(NaClDescInvalidMake());
326 0 : if (NULL == desc) {
327 0 : return NULL;
328 : }
329 :
330 0 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
331 0 : }
332 :
333 248 : DescWrapper::DescWrapper(DescWrapperCommon* common_data,
334 248 : struct NaClDesc* desc)
335 124 : : common_data_(common_data), desc_(desc) {
336 : // DescWrapper takes ownership of desc from caller, so no Ref call here.
337 124 : if (NULL != common_data_) {
338 124 : common_data_->Ref();
339 124 : }
340 248 : }
341 :
342 95 : DescWrapper::~DescWrapper() {
343 95 : if (NULL != common_data_) {
344 95 : common_data_->Unref();
345 95 : }
346 95 : NaClDescSafeUnref(desc_);
347 95 : desc_ = NULL;
348 190 : }
349 :
350 0 : ssize_t DescWrapper::Read(void* buf, size_t len) {
351 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
352 : Read(desc_, buf, len);
353 : }
354 :
355 0 : ssize_t DescWrapper::Write(const void* buf, size_t len) {
356 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
357 : Write(desc_, buf, len);
358 : }
359 :
360 0 : nacl_off64_t DescWrapper::Seek(nacl_off64_t offset, int whence) {
361 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
362 : Seek(desc_,
363 : offset,
364 : whence);
365 : }
366 :
367 0 : int DescWrapper::Fstat(struct nacl_abi_stat* statbuf) {
368 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
369 : Fstat(desc_, statbuf);
370 : }
371 :
372 : int DescWrapper::Close() {
373 0 : NaClRefCountUnref(&desc_->base);
374 0 : return 0;
375 : }
376 :
377 0 : ssize_t DescWrapper::Getdents(void* dirp, size_t count) {
378 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
379 : Getdents(desc_,
380 : dirp,
381 : count);
382 : }
383 :
384 : int DescWrapper::Lock() {
385 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
386 : Lock(desc_);
387 : }
388 :
389 : int DescWrapper::TryLock() {
390 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
391 : TryLock(desc_);
392 : }
393 :
394 : int DescWrapper::Unlock() {
395 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
396 : Unlock(desc_);
397 : }
398 :
399 0 : int DescWrapper::Wait(DescWrapper* mutex) {
400 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
401 : Wait(desc_, mutex->desc_);
402 : }
403 :
404 0 : int DescWrapper::TimedWaitAbs(DescWrapper* mutex,
405 0 : struct nacl_abi_timespec* ts) {
406 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
407 : TimedWaitAbs(desc_,
408 : mutex->desc_,
409 : ts);
410 : }
411 :
412 : int DescWrapper::Signal() {
413 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
414 : Signal(desc_);
415 : }
416 :
417 : int DescWrapper::Broadcast() {
418 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
419 : Broadcast(desc_);
420 : }
421 :
422 0 : ssize_t DescWrapper::SendMsg(const MsgHeader* dgram, int flags) {
423 0 : struct NaClImcTypedMsgHdr header;
424 0 : ssize_t ret = -NACL_ABI_ENOMEM;
425 0 : nacl_abi_size_t diov_length = dgram->iov_length;
426 0 : nacl_abi_size_t ddescv_length = dgram->ndescv_length;
427 0 : nacl_abi_size_t i;
428 :
429 : // Initialize to allow simple cleanups.
430 0 : header.ndescv = NULL;
431 : // Allocate and copy IOV.
432 0 : if (NACL_ABI_SIZE_T_MAX / sizeof(NaClImcMsgIoVec) <= diov_length) {
433 0 : goto cleanup;
434 : }
435 : header.iov = reinterpret_cast<NaClImcMsgIoVec*>(
436 0 : calloc(diov_length, sizeof(*(header.iov))));
437 0 : if (NULL == header.iov) {
438 0 : goto cleanup;
439 : }
440 0 : header.iov_length = diov_length;
441 0 : for (i = 0; i < dgram->iov_length; ++i) {
442 0 : header.iov[i].base = dgram->iov[i].base;
443 0 : header.iov[i].length = dgram->iov[i].length;
444 0 : }
445 : // Allocate and copy the descriptor vector, removing DescWrappers.
446 0 : if (NACL_HANDLE_COUNT_MAX < dgram->ndescv_length) {
447 0 : goto cleanup;
448 : }
449 0 : if (NACL_ABI_SIZE_T_MAX / sizeof(header.ndescv[0]) <= ddescv_length) {
450 0 : goto cleanup;
451 : }
452 : header.ndescv = reinterpret_cast<NaClDesc**>(
453 0 : calloc(ddescv_length, sizeof(*(header.ndescv))));
454 0 : if (NULL == header.iov) {
455 0 : goto cleanup;
456 : }
457 0 : header.ndesc_length = ddescv_length;
458 0 : for (i = 0; i < dgram->ndescv_length; ++i) {
459 0 : header.ndescv[i] = dgram->ndescv[i]->desc_;
460 0 : }
461 : // Send the message.
462 0 : ret = NACL_VTBL(NaClDesc, desc_)->SendMsg(desc_, &header, flags);
463 :
464 : cleanup:
465 0 : free(header.ndescv);
466 0 : free(header.iov);
467 0 : return ret;
468 : }
469 :
470 20 : ssize_t DescWrapper::RecvMsg(MsgHeader* dgram, int flags,
471 20 : struct NaClDescQuotaInterface *quota_interface) {
472 20 : struct NaClImcTypedMsgHdr header;
473 20 : ssize_t ret = -NACL_ABI_ENOMEM;
474 20 : nacl_abi_size_t diov_length = dgram->iov_length;
475 20 : nacl_abi_size_t ddescv_length = dgram->ndescv_length;
476 20 : nacl_abi_size_t i;
477 :
478 : // Initialize to allow simple cleanups.
479 20 : header.iov = NULL;
480 20 : header.ndescv = NULL;
481 360 : for (i = 0; i < dgram->ndescv_length; ++i) {
482 160 : dgram->ndescv[i] = NULL;
483 160 : }
484 :
485 : // Allocate and copy the IOV.
486 20 : if (NACL_ABI_SIZE_T_MAX / sizeof(NaClImcMsgIoVec) <= diov_length) {
487 0 : goto cleanup;
488 : }
489 : header.iov = reinterpret_cast<NaClImcMsgIoVec*>(
490 20 : calloc(diov_length, sizeof(*(header.iov))));
491 20 : if (NULL == header.iov) {
492 0 : goto cleanup;
493 : }
494 20 : header.iov_length = diov_length;
495 80 : for (i = 0; i < dgram->iov_length; ++i) {
496 20 : header.iov[i].base = dgram->iov[i].base;
497 20 : header.iov[i].length = dgram->iov[i].length;
498 20 : }
499 : // Allocate and copy the descriptor vector.
500 20 : if (NACL_HANDLE_COUNT_MAX < dgram->ndescv_length) {
501 0 : goto cleanup;
502 : }
503 20 : if (NACL_ABI_SIZE_T_MAX / sizeof(header.ndescv[0]) <= ddescv_length) {
504 0 : goto cleanup;
505 : }
506 : header.ndescv = reinterpret_cast<NaClDesc**>(
507 20 : calloc(ddescv_length, sizeof(*(header.ndescv))));
508 20 : if (NULL == header.ndescv) {
509 0 : goto cleanup;
510 : }
511 20 : header.ndesc_length = ddescv_length;
512 : // Receive the message.
513 20 : ret = NACL_VTBL(NaClDesc, desc_)->RecvMsg(desc_, &header, flags,
514 : quota_interface);
515 20 : if (ret < 0) {
516 0 : goto cleanup;
517 : }
518 20 : dgram->ndescv_length = header.ndesc_length;
519 20 : dgram->flags = header.flags;
520 : // Copy the descriptors, creating new DescWrappers around them.
521 120 : for (i = 0; i < header.ndesc_length; ++i) {
522 160 : dgram->ndescv[i] =
523 : new(std::nothrow) DescWrapper(common_data_, header.ndescv[i]);
524 40 : if (NULL == dgram->ndescv[i]) {
525 0 : goto cleanup;
526 : }
527 40 : }
528 20 : free(header.ndescv);
529 20 : free(header.iov);
530 20 : return ret;
531 :
532 : cleanup:
533 0 : for (i = 0; i < ddescv_length; ++i) {
534 0 : delete dgram->ndescv[i];
535 0 : }
536 0 : free(header.ndescv);
537 0 : free(header.iov);
538 0 : return ret;
539 20 : }
540 :
541 : DescWrapper* DescWrapper::Connect() {
542 29 : struct NaClDesc* connected_desc;
543 29 : int rv = reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
544 : ConnectAddr(desc_,
545 : &connected_desc);
546 29 : if (0 != rv) {
547 : // Connect failed.
548 0 : return NULL;
549 : }
550 116 : DescWrapper* wrapper =
551 : new(std::nothrow) DescWrapper(common_data_, connected_desc);
552 29 : if (NULL == wrapper) {
553 0 : NaClDescUnref(connected_desc);
554 0 : }
555 29 : return wrapper;
556 29 : }
557 :
558 : DescWrapper* DescWrapper::Accept() {
559 0 : struct NaClDesc* connected_desc;
560 0 : int rv = reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
561 : AcceptConn(desc_, &connected_desc);
562 0 : if (0 != rv) {
563 : // Accept failed.
564 0 : return NULL;
565 : }
566 0 : DescWrapper* wrapper =
567 : new(std::nothrow) DescWrapper(common_data_, connected_desc);
568 0 : if (NULL == wrapper) {
569 0 : NaClDescUnref(connected_desc);
570 0 : }
571 0 : return wrapper;
572 0 : }
573 :
574 : int DescWrapper::Post() {
575 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
576 : Post(desc_);
577 : }
578 :
579 : int DescWrapper::SemWait() {
580 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
581 : SemWait(desc_);
582 : }
583 :
584 : int DescWrapper::GetValue() {
585 0 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
586 : GetValue(desc_);
587 : }
588 :
589 : } // namespace nacl
|