1 : // Copyright (c) 2011 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 "base/shared_memory.h"
8 : #include "base/sync_socket.h"
9 : #include "native_client/src/include/portability.h"
10 : #include "native_client/src/include/portability_string.h"
11 : #include "native_client/src/shared/imc/nacl_imc.h"
12 : #include "native_client/src/shared/platform/nacl_check.h"
13 : #include "native_client/src/shared/platform/nacl_log.h"
14 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
15 : #if defined(NACL_LINUX)
16 : #include "native_client/src/trusted/desc/linux/nacl_desc_sysv_shm.h"
17 : #endif // defined(NACL_LINUX)
18 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
19 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
20 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
21 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
22 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
23 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
24 : #include "native_client/src/trusted/desc/nacl_desc_quota.h"
25 : #include "native_client/src/trusted/desc/nacl_desc_rng.h"
26 : #include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
27 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
28 : #include "native_client/src/trusted/desc/nrd_xfer.h"
29 : #include "native_client/src/trusted/desc/nrd_xfer_effector.h"
30 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
31 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
32 : #include "native_client/src/trusted/service_runtime/include/sys/nacl_imc_api.h"
33 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
34 :
35 : // TODO(polina): follow the style guide and replace "nhdp" and "ndiodp" with
36 : // "host_desc" and "io_desc"
37 :
38 : namespace {
39 13 : static const size_t kSizeTMax = std::numeric_limits<size_t>::max();
40 :
41 11 : struct NaClDesc* OpenHostFileCommon(const char* fname, int flags, int mode) {
42 : struct NaClHostDesc* nhdp =
43 11 : reinterpret_cast<struct NaClHostDesc*>(calloc(1, sizeof(*nhdp)));
44 11 : if (NULL == nhdp) {
45 0 : return NULL;
46 : }
47 11 : if (0 != NaClHostDescOpen(nhdp, fname, flags, mode)) {
48 0 : free(nhdp);
49 0 : return NULL;
50 : }
51 11 : struct NaClDescIoDesc* ndiodp = NaClDescIoDescMake(nhdp);
52 11 : if (NULL == ndiodp) {
53 0 : NaClHostDescClose(nhdp);
54 0 : free(nhdp);
55 0 : return NULL;
56 : }
57 11 : return reinterpret_cast<struct NaClDesc*>(ndiodp);
58 : }
59 :
60 0 : struct NaClDesc* ImportHostDescCommon(int host_os_desc, int mode) {
61 0 : NaClHostDesc* nhdp = NaClHostDescPosixMake(host_os_desc, mode);
62 0 : if (NULL == nhdp) {
63 0 : return NULL;
64 : }
65 0 : NaClDescIoDesc* ndiodp = NaClDescIoDescMake(nhdp);
66 0 : if (NULL == ndiodp) {
67 0 : NaClHostDescClose(nhdp);
68 0 : free(nhdp);
69 0 : return NULL;
70 : }
71 0 : return reinterpret_cast<struct NaClDesc*>(ndiodp);
72 : }
73 :
74 : struct NaClDesc* MakeQuotaCommon(const uint8_t* file_id,
75 0 : struct NaClDesc* desc) {
76 : NaClDescQuota* ndqp =
77 0 : reinterpret_cast<NaClDescQuota*>(calloc(1, sizeof *ndqp));
78 0 : if ((NULL == ndqp) || !NaClDescQuotaCtor(ndqp, desc, file_id, NULL)) {
79 0 : free(ndqp);
80 0 : return NULL;
81 : }
82 0 : return reinterpret_cast<struct NaClDesc*>(ndqp);
83 : }
84 :
85 : } // namespace
86 :
87 : namespace nacl {
88 :
89 : // Descriptor creation and manipulation sometimes requires additional state
90 : // (for instance, Effectors). Therefore, we create an object that encapsulates
91 : // that state.
92 : class DescWrapperCommon {
93 : friend class DescWrapperFactory;
94 :
95 : public:
96 : typedef uint32_t RefCountType;
97 :
98 : // Get a pointer to the effector.
99 40 : struct NaClDescEffector* effp() {
100 40 : return reinterpret_cast<struct NaClDescEffector*>(&eff_);
101 : }
102 :
103 : // Inform clients that the object was successfully initialized.
104 24 : bool is_initialized() const { return is_initialized_; }
105 :
106 : // Manipulate reference count
107 57 : DescWrapperCommon* Ref() {
108 : // TODO(sehr): replace with a reference count class when we have one.
109 57 : NaClXMutexLock(&ref_count_mu_);
110 57 : if (std::numeric_limits<RefCountType>::max() == ref_count_) {
111 0 : NaClLog(LOG_FATAL, "DescWrapperCommon ref count overflow\n");
112 : }
113 57 : ++ref_count_;
114 57 : NaClXMutexUnlock(&ref_count_mu_);
115 57 : return this;
116 : }
117 :
118 75 : void Unref() {
119 75 : NaClXMutexLock(&ref_count_mu_);
120 75 : if (0 == ref_count_) {
121 0 : NaClLog(LOG_FATAL, "DescWrapperCommon ref count already zero\n");
122 : }
123 75 : --ref_count_;
124 75 : bool destroy = (0 == ref_count_);
125 75 : NaClXMutexUnlock(&ref_count_mu_);
126 75 : if (destroy) {
127 20 : delete this;
128 : }
129 75 : }
130 :
131 : private:
132 22 : DescWrapperCommon() : is_initialized_(false), ref_count_(1) {
133 22 : NaClXMutexCtor(&ref_count_mu_);
134 22 : }
135 20 : ~DescWrapperCommon() {
136 20 : if (is_initialized_) {
137 20 : effp()->vtbl->Dtor(effp());
138 : }
139 20 : NaClMutexDtor(&ref_count_mu_);
140 20 : }
141 :
142 : // Set up the state. Returns true on success.
143 : bool Init();
144 :
145 : // Boolean to indicate the object was successfully initialized.
146 : bool is_initialized_;
147 : // Effector for transferring descriptors.
148 : struct NaClNrdXferEffector eff_;
149 : // The reference count and the mutex to protect it.
150 : RefCountType ref_count_;
151 : struct NaClMutex ref_count_mu_;
152 :
153 : DISALLOW_COPY_AND_ASSIGN(DescWrapperCommon);
154 : };
155 :
156 22 : bool DescWrapperCommon::Init() {
157 : // Set up the transfer effector.
158 22 : if (!NaClNrdXferEffectorCtor(&eff_)) {
159 0 : return false;
160 : }
161 : // Successfully initialized.
162 22 : is_initialized_ = true;
163 22 : return true;
164 : }
165 :
166 22 : DescWrapperFactory::DescWrapperFactory() {
167 22 : common_data_ = new(std::nothrow) DescWrapperCommon();
168 22 : if (NULL == common_data_) {
169 0 : return;
170 : }
171 22 : if (!common_data_->Init()) {
172 0 : delete common_data_;
173 0 : common_data_ = NULL;
174 : }
175 : }
176 :
177 20 : DescWrapperFactory::~DescWrapperFactory() {
178 20 : if (NULL != common_data_) {
179 20 : common_data_->Unref();
180 : }
181 20 : }
182 :
183 0 : int DescWrapperFactory::MakeBoundSock(DescWrapper* pair[2]) {
184 0 : CHECK(common_data_->is_initialized());
185 :
186 0 : struct NaClDesc* descs[2] = { NULL, NULL };
187 0 : DescWrapper* tmp_pair[2] = { NULL, NULL };
188 :
189 0 : int ret = NaClCommonDescMakeBoundSock(descs);
190 0 : if (0 != ret) {
191 0 : return ret;
192 : }
193 0 : tmp_pair[0] = new(std::nothrow) DescWrapper(common_data_, descs[0]);
194 0 : if (NULL == tmp_pair[0]) {
195 0 : goto cleanup;
196 : }
197 0 : descs[0] = NULL; // DescWrapper took ownership of descs[0].
198 0 : tmp_pair[1] = new(std::nothrow) DescWrapper(common_data_, descs[1]);
199 0 : if (NULL == tmp_pair[1]) {
200 0 : goto cleanup;
201 : }
202 0 : descs[1] = NULL; // DescWrapper took ownership of descs[1].
203 0 : pair[0] = tmp_pair[0];
204 0 : pair[1] = tmp_pair[1];
205 0 : return 0;
206 :
207 0 : cleanup:
208 0 : NaClDescSafeUnref(descs[0]);
209 0 : NaClDescSafeUnref(descs[1]);
210 0 : delete tmp_pair[0];
211 0 : delete tmp_pair[1];
212 0 : return -1;
213 : }
214 :
215 11 : DescWrapper* DescWrapperFactory::MakeImcSock(NaClHandle handle) {
216 : struct NaClDescImcDesc* desc =
217 11 : reinterpret_cast<NaClDescImcDesc*>(calloc(1, sizeof *desc));
218 11 : if (NULL == desc) {
219 0 : return NULL;
220 : }
221 11 : if (!NaClDescImcDescCtor(desc, handle)) {
222 0 : free(desc);
223 0 : return NULL;
224 : }
225 :
226 11 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
227 : }
228 :
229 0 : DescWrapper* DescWrapperFactory::MakeShm(size_t size) {
230 0 : CHECK(common_data_->is_initialized());
231 : // HACK: there's an inlining issue with this.
232 : // size_t rounded_size = NaClRoundAllocPage(size);
233 : size_t rounded_size =
234 : (size + NACL_MAP_PAGESIZE - 1) &
235 0 : ~static_cast<size_t>(NACL_MAP_PAGESIZE - 1);
236 : // TODO(sehr): fix the inlining issue.
237 0 : NaClHandle handle = CreateMemoryObject(rounded_size, /* executable= */ false);
238 0 : if (kInvalidHandle == handle) {
239 0 : return NULL;
240 : }
241 0 : return ImportShmHandle(handle, size);
242 : }
243 :
244 : DescWrapper* DescWrapperFactory::ImportShmHandle(NaClHandle handle,
245 0 : size_t size) {
246 : struct NaClDescImcShm* desc =
247 0 : reinterpret_cast<NaClDescImcShm*>(calloc(1, sizeof *desc));
248 0 : if (NULL == desc) {
249 0 : return NULL;
250 : }
251 0 : if (!NaClDescImcShmCtor(desc, handle, size)) {
252 0 : free(desc);
253 0 : return NULL;
254 : }
255 :
256 0 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
257 : }
258 :
259 0 : DescWrapper* DescWrapperFactory::ImportSyncSocketHandle(NaClHandle handle) {
260 : struct NaClDescSyncSocket* desc =
261 0 : static_cast<NaClDescSyncSocket*>(calloc(1, sizeof *desc));
262 0 : if (NULL == desc) {
263 0 : return NULL;
264 : }
265 0 : if (!NaClDescSyncSocketCtor(desc, handle)) {
266 0 : free(desc);
267 0 : return NULL;
268 : }
269 :
270 0 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
271 : }
272 :
273 : #if NACL_LINUX
274 : DescWrapper* DescWrapperFactory::ImportSysvShm(int key, size_t size) {
275 : if (kSizeTMax - NACL_PAGESIZE + 1 <= size) {
276 : // Avoid overflow when rounding to the nearest 4K and casting to
277 : // nacl_off64_t by preventing negative size.
278 : return NULL;
279 : }
280 : // HACK: there's an inlining issue with using NaClRoundPage. (See above.)
281 : // rounded_size = NaClRoundPage(size);
282 : size_t rounded_size =
283 : (size + NACL_PAGESIZE - 1) & ~static_cast<size_t>(NACL_PAGESIZE - 1);
284 : struct NaClDescSysvShm* desc =
285 : reinterpret_cast<NaClDescSysvShm*>(calloc(1, sizeof *desc));
286 : if (NULL == desc) {
287 : return NULL;
288 : }
289 :
290 : if (!NaClDescSysvShmImportCtor(desc,
291 : key,
292 : static_cast<nacl_off64_t>(rounded_size))) {
293 : // If rounded_size is negative due to overflow from rounding, it will be
294 : // rejected here by NaClDescSysvShmImportCtor.
295 : free(desc);
296 : return NULL;
297 : }
298 :
299 : return
300 : MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
301 : }
302 : #endif // NACL_LINUX
303 :
304 : #if defined(NACL_STANDALONE)
305 : DescWrapper* DescWrapperFactory::ImportPepperSharedMemory(intptr_t shm_int,
306 0 : size_t size) {
307 : // PepperSharedMemory is only present in the Chrome hookup.
308 : UNREFERENCED_PARAMETER(shm_int);
309 : UNREFERENCED_PARAMETER(size);
310 0 : return NULL;
311 : }
312 :
313 0 : DescWrapper* DescWrapperFactory::ImportPepper2DSharedMemory(intptr_t shm_int) {
314 : // Pepper2DSharedMemory is only present in the Chrome hookup.
315 : UNREFERENCED_PARAMETER(shm_int);
316 0 : return NULL;
317 : }
318 :
319 0 : DescWrapper* DescWrapperFactory::ImportPepperSync(intptr_t sync_int) {
320 : #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
321 0 : base::SyncSocket* sock = reinterpret_cast<base::SyncSocket*>(sync_int);
322 0 : struct NaClDescSyncSocket* ss_desc = NULL;
323 0 : DescWrapper* wrapper = NULL;
324 :
325 : ss_desc = static_cast<NaClDescSyncSocket*>(
326 0 : calloc(1, sizeof(*ss_desc)));
327 0 : if (NULL == ss_desc) {
328 : // TODO(sehr): Gotos are awful. Add a scoped_ptr variant that
329 : // invokes NaClDescSafeUnref.
330 0 : goto cleanup;
331 : }
332 0 : if (!NaClDescSyncSocketCtor(ss_desc, sock->handle())) {
333 0 : free(ss_desc);
334 0 : ss_desc = NULL;
335 0 : goto cleanup;
336 : }
337 0 : wrapper = new DescWrapper(common_data_, &ss_desc->base);
338 0 : if (NULL == wrapper) {
339 0 : goto cleanup;
340 : }
341 0 : ss_desc = NULL; // DescWrapper takes ownership of ss_desc.
342 0 : return wrapper;
343 :
344 0 : cleanup:
345 0 : NaClDescSafeUnref(&ss_desc->base);
346 0 : return NULL;
347 : #else
348 : UNREFERENCED_PARAMETER(sync_int);
349 : return NULL;
350 : #endif
351 : }
352 : #endif // NACL_STANDALONE
353 :
354 0 : DescWrapper* DescWrapperFactory::MakeGeneric(struct NaClDesc* desc) {
355 0 : CHECK(common_data_->is_initialized());
356 0 : return new(std::nothrow) DescWrapper(common_data_, desc);
357 : }
358 :
359 :
360 24 : DescWrapper* DescWrapperFactory::MakeGenericCleanup(struct NaClDesc* desc) {
361 24 : CHECK(common_data_->is_initialized());
362 24 : DescWrapper* wrapper = new(std::nothrow) DescWrapper(common_data_, desc);
363 24 : if (NULL != wrapper) {
364 24 : return wrapper;
365 : }
366 0 : NaClDescSafeUnref(desc);
367 0 : return NULL;
368 : }
369 :
370 0 : int DescWrapperFactory::MakeSocketPair(DescWrapper* pair[2]) {
371 0 : CHECK(common_data_->is_initialized());
372 0 : struct NaClDesc* descs[2] = { NULL, NULL };
373 0 : DescWrapper* tmp_pair[2] = { NULL, NULL };
374 :
375 0 : int ret = NaClCommonDescSocketPair(descs);
376 0 : if (0 != ret) {
377 0 : return ret;
378 : }
379 0 : tmp_pair[0] = new(std::nothrow) DescWrapper(common_data_, descs[0]);
380 0 : if (NULL == tmp_pair[0]) {
381 0 : goto cleanup;
382 : }
383 0 : descs[0] = NULL; // DescWrapper took ownership of descs[0].
384 0 : tmp_pair[1] = new(std::nothrow) DescWrapper(common_data_, descs[1]);
385 0 : if (NULL == tmp_pair[1]) {
386 0 : goto cleanup;
387 : }
388 0 : descs[1] = NULL; // DescWrapper took ownership of descs[1].
389 0 : pair[0] = tmp_pair[0];
390 0 : pair[1] = tmp_pair[1];
391 0 : return 0;
392 :
393 0 : cleanup:
394 0 : NaClDescSafeUnref(descs[0]);
395 0 : NaClDescSafeUnref(descs[1]);
396 0 : delete tmp_pair[0];
397 0 : delete tmp_pair[1];
398 0 : return -1;
399 : }
400 :
401 0 : DescWrapper* DescWrapperFactory::MakeFileDesc(int host_os_desc, int mode) {
402 0 : struct NaClDesc* desc = ImportHostDescCommon(host_os_desc, mode);
403 0 : if (NULL == desc) {
404 0 : return NULL;
405 : }
406 0 : return MakeGenericCleanup(desc);
407 : }
408 :
409 : DescWrapper* DescWrapperFactory::MakeFileDescQuota(int host_os_desc,
410 : int mode,
411 0 : const uint8_t* file_id) {
412 0 : struct NaClDesc* desc = ImportHostDescCommon(host_os_desc, mode);
413 0 : if (NULL == desc) {
414 0 : return NULL;
415 : }
416 0 : struct NaClDesc* desc_quota = MakeQuotaCommon(file_id, desc);
417 0 : if (desc_quota == NULL) {
418 0 : NaClDescSafeUnref(desc);
419 0 : return NULL;
420 : }
421 0 : return MakeGenericCleanup(desc_quota);
422 : }
423 :
424 : DescWrapper* DescWrapperFactory::OpenHostFile(const char* fname,
425 : int flags,
426 11 : int mode) {
427 11 : struct NaClDesc* desc = OpenHostFileCommon(fname, flags, mode);
428 11 : if (NULL == desc) {
429 0 : return NULL;
430 : }
431 11 : return MakeGenericCleanup(desc);
432 : }
433 :
434 : DescWrapper* DescWrapperFactory::OpenHostFileQuota(const char* fname,
435 : int flags,
436 : int mode,
437 0 : const uint8_t* file_id) {
438 0 : struct NaClDesc* desc = OpenHostFileCommon(fname, flags, mode);
439 0 : if (NULL == desc) {
440 0 : return NULL;
441 : }
442 0 : struct NaClDesc* desc_quota = MakeQuotaCommon(file_id, desc);
443 0 : if (NULL == desc_quota) {
444 0 : NaClDescSafeUnref(desc);
445 0 : return NULL;
446 : }
447 0 : return MakeGenericCleanup(desc_quota);
448 : }
449 :
450 0 : DescWrapper* DescWrapperFactory::OpenRng() {
451 : struct NaClDescRng* nhrp =
452 0 : reinterpret_cast<struct NaClDescRng*>(calloc(1, sizeof(*nhrp)));
453 0 : if (NULL == nhrp) {
454 0 : return NULL;
455 : }
456 0 : if (!NaClDescRngCtor(nhrp)) {
457 0 : free(nhrp);
458 0 : return NULL;
459 : }
460 :
461 0 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(nhrp));
462 : }
463 :
464 0 : DescWrapper* DescWrapperFactory::MakeInvalid() {
465 : struct NaClDescInvalid *desc =
466 0 : const_cast<NaClDescInvalid*>(NaClDescInvalidMake());
467 0 : if (NULL == desc) {
468 0 : return NULL;
469 : }
470 :
471 0 : return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
472 : }
473 :
474 : DescWrapper::DescWrapper(DescWrapperCommon* common_data,
475 57 : struct NaClDesc* desc)
476 57 : : common_data_(common_data), desc_(desc) {
477 : // DescWrapper takes ownership of desc from caller, so no Ref call here.
478 57 : if (NULL != common_data_) {
479 57 : common_data_->Ref();
480 : }
481 57 : }
482 :
483 55 : DescWrapper::~DescWrapper() {
484 55 : if (NULL != common_data_) {
485 55 : common_data_->Unref();
486 : }
487 55 : NaClDescSafeUnref(desc_);
488 55 : desc_ = NULL;
489 55 : }
490 :
491 0 : int DescWrapper::Map(void** addr, size_t* size) {
492 0 : return NaClDescMapDescriptor(desc_, common_data_->effp(), addr, size);
493 : }
494 :
495 0 : int DescWrapper::Unmap(void* start_addr, size_t len) {
496 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
497 : Unmap(desc_,
498 : common_data_->effp(),
499 0 : start_addr, len);
500 : }
501 :
502 0 : ssize_t DescWrapper::Read(void* buf, size_t len) {
503 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
504 0 : Read(desc_, buf, len);
505 : }
506 :
507 0 : ssize_t DescWrapper::Write(const void* buf, size_t len) {
508 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
509 0 : Write(desc_, buf, len);
510 : }
511 :
512 0 : nacl_off64_t DescWrapper::Seek(nacl_off64_t offset, int whence) {
513 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
514 : Seek(desc_,
515 : offset,
516 0 : whence);
517 : }
518 :
519 0 : int DescWrapper::Ioctl(int request, void* arg) {
520 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
521 0 : Ioctl(desc_, request, arg);
522 : }
523 :
524 0 : int DescWrapper::Fstat(struct nacl_abi_stat* statbuf) {
525 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
526 0 : Fstat(desc_, statbuf);
527 : }
528 :
529 0 : int DescWrapper::Close() {
530 0 : NaClRefCountUnref(&desc_->base);
531 0 : return 0;
532 : }
533 :
534 0 : ssize_t DescWrapper::Getdents(void* dirp, size_t count) {
535 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
536 : Getdents(desc_,
537 : dirp,
538 0 : count);
539 : }
540 :
541 0 : int DescWrapper::Lock() {
542 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
543 0 : Lock(desc_);
544 : }
545 :
546 0 : int DescWrapper::TryLock() {
547 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
548 0 : TryLock(desc_);
549 : }
550 :
551 0 : int DescWrapper::Unlock() {
552 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
553 0 : Unlock(desc_);
554 : }
555 :
556 0 : int DescWrapper::Wait(DescWrapper* mutex) {
557 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
558 0 : Wait(desc_, mutex->desc_);
559 : }
560 :
561 : int DescWrapper::TimedWaitAbs(DescWrapper* mutex,
562 0 : struct nacl_abi_timespec* ts) {
563 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
564 : TimedWaitAbs(desc_,
565 : mutex->desc_,
566 0 : ts);
567 : }
568 :
569 0 : int DescWrapper::Signal() {
570 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
571 0 : Signal(desc_);
572 : }
573 :
574 0 : int DescWrapper::Broadcast() {
575 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
576 0 : Broadcast(desc_);
577 : }
578 :
579 0 : ssize_t DescWrapper::SendMsg(const MsgHeader* dgram, int flags) {
580 : struct NaClImcTypedMsgHdr header;
581 0 : ssize_t ret = -NACL_ABI_ENOMEM;
582 0 : nacl_abi_size_t diov_length = dgram->iov_length;
583 0 : nacl_abi_size_t ddescv_length = dgram->ndescv_length;
584 : nacl_abi_size_t i;
585 :
586 : // Initialize to allow simple cleanups.
587 0 : header.ndescv = NULL;
588 : // Allocate and copy IOV.
589 0 : if (kSizeTMax / sizeof(NaClImcMsgIoVec) <= diov_length) {
590 0 : goto cleanup;
591 : }
592 : header.iov = reinterpret_cast<NaClImcMsgIoVec*>(
593 0 : calloc(diov_length, sizeof(*(header.iov))));
594 0 : if (NULL == header.iov) {
595 0 : goto cleanup;
596 : }
597 0 : header.iov_length = diov_length;
598 0 : for (i = 0; i < dgram->iov_length; ++i) {
599 0 : header.iov[i].base = dgram->iov[i].base;
600 0 : header.iov[i].length = dgram->iov[i].length;
601 : }
602 : // Allocate and copy the descriptor vector, removing DescWrappers.
603 0 : if (kHandleCountMax < dgram->ndescv_length) {
604 0 : goto cleanup;
605 : }
606 0 : if (kSizeTMax / sizeof(header.ndescv[0]) <= ddescv_length) {
607 0 : goto cleanup;
608 : }
609 : header.ndescv = reinterpret_cast<NaClDesc**>(
610 0 : calloc(ddescv_length, sizeof(*(header.ndescv))));
611 0 : if (NULL == header.iov) {
612 0 : goto cleanup;
613 : }
614 0 : header.ndesc_length = ddescv_length;
615 0 : for (i = 0; i < dgram->ndescv_length; ++i) {
616 0 : header.ndescv[i] = dgram->ndescv[i]->desc_;
617 : }
618 : // Send the message.
619 0 : ret = NaClImcSendTypedMessage(desc_, &header, flags);
620 :
621 0 : cleanup:
622 0 : free(header.ndescv);
623 0 : free(header.iov);
624 0 : return ret;
625 : }
626 :
627 : ssize_t DescWrapper::RecvMsg(MsgHeader* dgram, int flags,
628 11 : struct NaClDescQuotaInterface *quota_interface) {
629 : struct NaClImcTypedMsgHdr header;
630 11 : ssize_t ret = -NACL_ABI_ENOMEM;
631 11 : nacl_abi_size_t diov_length = dgram->iov_length;
632 11 : nacl_abi_size_t ddescv_length = dgram->ndescv_length;
633 : nacl_abi_size_t i;
634 :
635 : // Initialize to allow simple cleanups.
636 11 : header.ndescv = NULL;
637 99 : for (i = 0; i < dgram->ndescv_length; ++i) {
638 88 : dgram->ndescv[i] = NULL;
639 : }
640 :
641 : // Allocate and copy the IOV.
642 11 : if (kSizeTMax / sizeof(NaClImcMsgIoVec) <= diov_length) {
643 0 : goto cleanup;
644 : }
645 : header.iov = reinterpret_cast<NaClImcMsgIoVec*>(
646 11 : calloc(diov_length, sizeof(*(header.iov))));
647 11 : if (NULL == header.iov) {
648 0 : goto cleanup;
649 : }
650 11 : header.iov_length = diov_length;
651 22 : for (i = 0; i < dgram->iov_length; ++i) {
652 11 : header.iov[i].base = dgram->iov[i].base;
653 11 : header.iov[i].length = dgram->iov[i].length;
654 : }
655 : // Allocate and copy the descriptor vector.
656 11 : if (kHandleCountMax < dgram->ndescv_length) {
657 0 : goto cleanup;
658 : }
659 11 : if (kSizeTMax / sizeof(header.ndescv[0]) <= ddescv_length) {
660 0 : goto cleanup;
661 : }
662 : header.ndescv = reinterpret_cast<NaClDesc**>(
663 11 : calloc(ddescv_length, sizeof(*(header.ndescv))));
664 11 : if (NULL == header.ndescv) {
665 0 : goto cleanup;
666 : }
667 11 : header.ndesc_length = ddescv_length;
668 : // Receive the message.
669 11 : ret = NaClImcRecvTypedMessage(desc_, &header, flags, quota_interface);
670 11 : if (ret < 0) {
671 0 : goto cleanup;
672 : }
673 11 : dgram->ndescv_length = header.ndesc_length;
674 11 : dgram->flags = header.flags;
675 : // Copy the descriptors, creating new DescWrappers around them.
676 22 : for (i = 0; i < header.ndesc_length; ++i) {
677 : dgram->ndescv[i] =
678 11 : new(std::nothrow) DescWrapper(common_data_, header.ndescv[i]);
679 11 : if (NULL == dgram->ndescv[i]) {
680 0 : goto cleanup;
681 : }
682 : }
683 11 : free(header.ndescv);
684 11 : free(header.iov);
685 11 : return ret;
686 :
687 0 : cleanup:
688 0 : for (i = 0; i < ddescv_length; ++i) {
689 0 : delete dgram->ndescv[i];
690 : }
691 0 : free(header.ndescv);
692 0 : free(header.iov);
693 0 : return ret;
694 : }
695 :
696 22 : DescWrapper* DescWrapper::Connect() {
697 : struct NaClDesc* connected_desc;
698 : int rv = reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
699 : ConnectAddr(desc_,
700 22 : &connected_desc);
701 22 : if (0 != rv) {
702 : // Connect failed.
703 0 : return NULL;
704 : }
705 : DescWrapper* wrapper =
706 22 : new(std::nothrow) DescWrapper(common_data_, connected_desc);
707 22 : if (NULL == wrapper) {
708 0 : NaClDescUnref(connected_desc);
709 : }
710 22 : return wrapper;
711 : }
712 :
713 0 : DescWrapper* DescWrapper::Accept() {
714 : struct NaClDesc* connected_desc;
715 : int rv = reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
716 0 : AcceptConn(desc_, &connected_desc);
717 0 : if (0 != rv) {
718 : // Accept failed.
719 0 : return NULL;
720 : }
721 : DescWrapper* wrapper =
722 0 : new(std::nothrow) DescWrapper(common_data_, connected_desc);
723 0 : if (NULL == wrapper) {
724 0 : NaClDescUnref(connected_desc);
725 : }
726 0 : return wrapper;
727 : }
728 :
729 0 : int DescWrapper::Post() {
730 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
731 0 : Post(desc_);
732 : }
733 :
734 0 : int DescWrapper::SemWait() {
735 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
736 0 : SemWait(desc_);
737 : }
738 :
739 0 : int DescWrapper::GetValue() {
740 : return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
741 0 : GetValue(desc_);
742 : }
743 :
744 26 : } // namespace nacl
|