1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * NaCl Service Runtime. I/O Descriptor / Handle abstraction. Memory
9 : * mapping using descriptors.
10 : */
11 :
12 : #include <stdlib.h>
13 : #include <string.h>
14 : #include <sys/types.h>
15 : #include <sys/stat.h>
16 :
17 : #include "native_client/src/include/portability.h"
18 : #include "native_client/src/include/nacl_platform.h"
19 :
20 : #include "native_client/src/public/desc_metadata_types.h"
21 :
22 : #include "native_client/src/shared/platform/nacl_host_desc.h"
23 : #include "native_client/src/shared/platform/nacl_log.h"
24 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
25 :
26 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
27 : #include "native_client/src/trusted/desc/nacl_desc_cond.h"
28 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
29 : #include "native_client/src/trusted/desc/nacl_desc_dir.h"
30 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
31 : #include "native_client/src/trusted/desc/nacl_desc_imc_bound_desc.h"
32 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
33 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
34 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
35 : #include "native_client/src/trusted/desc/nacl_desc_mutex.h"
36 : #include "native_client/src/trusted/desc/nacl_desc_null.h"
37 : #include "native_client/src/trusted/desc/nacl_desc_quota.h"
38 : #include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
39 :
40 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
41 :
42 : #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
43 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
44 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
45 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
46 : #include "native_client/src/trusted/service_runtime/sel_util.h"
47 :
48 : /*
49 : * This file contains base class code for NaClDesc.
50 : *
51 : * The implementation for following subclasses are elsewhere, but here
52 : * is an enumeration of them with a brief description:
53 : *
54 : * NaClDescIoDesc is the subclass that wraps host-OS descriptors
55 : * provided by NaClHostDesc (which gives an OS-independent abstraction
56 : * for host-OS descriptors).
57 : *
58 : * NaClDescImcDesc is the subclass that wraps IMC descriptors.
59 : *
60 : * NaClDescMutex and NaClDescCondVar are the subclasses that
61 : * wrap the non-transferrable synchronization objects.
62 : *
63 : * These NaClDesc objects are impure in that they know about the
64 : * virtual memory subsystem restriction of requiring mappings to occur
65 : * in NACL_MAP_PAGESIZE (64KB) chunks, so the Map and Unmap virtual
66 : * functions, at least, will enforce this restriction.
67 : */
68 :
69 : /*
70 : * TODO(bsy): remove when we put SIZE_T_MAX in a common header file.
71 : */
72 : #if !defined(SIZE_T_MAX)
73 : # define SIZE_T_MAX ((size_t) -1)
74 : #endif
75 :
76 6 : int NaClDescCtor(struct NaClDesc *ndp) {
77 : /* this should be a compile-time test */
78 6 : if (0 != (sizeof(struct NaClInternalHeader) & 0xf)) {
79 : NaClLog(LOG_FATAL,
80 : "Internal error. NaClInternalHeader size not a"
81 0 : " multiple of 16\n");
82 : }
83 6 : ndp->flags = 0;
84 6 : ndp->metadata_type = NACL_DESC_METADATA_NONE_TYPE;
85 6 : ndp->metadata_num_bytes = 0;
86 6 : ndp->metadata = NULL;
87 6 : return NaClRefCountCtor(&ndp->base);
88 6 : }
89 :
90 5 : static void NaClDescDtor(struct NaClRefCount *nrcp) {
91 5 : struct NaClDesc *ndp = (struct NaClDesc *) nrcp;
92 5 : free(ndp->metadata);
93 5 : ndp->metadata = NULL;
94 5 : nrcp->vtbl = &kNaClRefCountVtbl;
95 5 : (*nrcp->vtbl->Dtor)(nrcp);
96 5 : }
97 :
98 3 : struct NaClDesc *NaClDescRef(struct NaClDesc *ndp) {
99 3 : return (struct NaClDesc *) NaClRefCountRef(&ndp->base);
100 3 : }
101 :
102 5 : void NaClDescUnref(struct NaClDesc *ndp) {
103 5 : NaClRefCountUnref(&ndp->base);
104 5 : }
105 :
106 4 : void NaClDescSafeUnref(struct NaClDesc *ndp) {
107 4 : if (NULL != ndp) {
108 4 : NaClRefCountUnref(&ndp->base);
109 : }
110 4 : }
111 :
112 : int NaClDescExternalizeSize(struct NaClDesc *self,
113 : size_t *nbytes,
114 1 : size_t *nhandles) {
115 1 : *nbytes = sizeof self->flags;
116 1 : if (0 != (NACL_DESC_FLAGS_HAS_METADATA & self->flags)) {
117 : *nbytes += (sizeof self->metadata_type +
118 1 : sizeof self->metadata_num_bytes + self->metadata_num_bytes);
119 : }
120 1 : *nhandles = 0;
121 1 : return 0;
122 1 : }
123 :
124 : int NaClDescExternalize(struct NaClDesc *self,
125 1 : struct NaClDescXferState *xfer) {
126 1 : memcpy(xfer->next_byte, &self->flags, sizeof self->flags);
127 1 : xfer->next_byte += sizeof self->flags;
128 1 : if (0 != (NACL_DESC_FLAGS_HAS_METADATA & self->flags)) {
129 1 : memcpy(xfer->next_byte, &self->metadata_type, sizeof self->metadata_type);
130 1 : xfer->next_byte += sizeof self->metadata_type;
131 : memcpy(xfer->next_byte, &self->metadata_num_bytes,
132 1 : sizeof self->metadata_num_bytes);
133 1 : xfer->next_byte += sizeof self->metadata_num_bytes;
134 1 : memcpy(xfer->next_byte, self->metadata, self->metadata_num_bytes);
135 1 : xfer->next_byte += self->metadata_num_bytes;
136 : }
137 1 : return 0;
138 1 : }
139 :
140 : int NaClDescInternalizeCtor(struct NaClDesc *vself,
141 1 : struct NaClDescXferState *xfer) {
142 : int rv;
143 : char *nxt;
144 :
145 1 : rv = NaClDescCtor(vself);
146 1 : if (0 == rv) {
147 0 : return rv;
148 : }
149 1 : nxt = xfer->next_byte;
150 1 : if (nxt + sizeof vself->flags > xfer->byte_buffer_end) {
151 0 : rv = 0;
152 0 : goto done;
153 : }
154 1 : memcpy(&vself->flags, nxt, sizeof vself->flags);
155 1 : nxt += sizeof vself->flags;
156 1 : if (0 == (NACL_DESC_FLAGS_HAS_METADATA & vself->flags)) {
157 0 : xfer->next_byte = nxt;
158 0 : rv = 1;
159 0 : goto done;
160 : }
161 : if (nxt + sizeof vself->metadata_type + sizeof vself->metadata_num_bytes >
162 1 : xfer->byte_buffer_end) {
163 0 : rv = 0;
164 0 : goto done;
165 : }
166 1 : memcpy(&vself->metadata_type, nxt, sizeof vself->metadata_type);
167 1 : nxt += sizeof vself->metadata_type;
168 1 : memcpy(&vself->metadata_num_bytes, nxt, sizeof vself->metadata_num_bytes);
169 1 : nxt += sizeof vself->metadata_num_bytes;
170 1 : if (nxt + vself->metadata_num_bytes > xfer->byte_buffer_end) {
171 0 : rv = 0;
172 0 : goto done;
173 : }
174 1 : if (NULL == (vself->metadata = malloc(vself->metadata_num_bytes))) {
175 0 : rv = 0;
176 0 : goto done;
177 : }
178 1 : memcpy(vself->metadata, nxt, vself->metadata_num_bytes);
179 1 : nxt += vself->metadata_num_bytes;
180 1 : xfer->next_byte = nxt;
181 1 : rv = 1;
182 : done:
183 1 : if (!rv) {
184 0 : (*NACL_VTBL(NaClRefCount, vself)->Dtor)((struct NaClRefCount *) vself);
185 : }
186 1 : return rv;
187 1 : }
188 :
189 : int (*NaClDescInternalize[NACL_DESC_TYPE_MAX])(
190 : struct NaClDesc **,
191 : struct NaClDescXferState *,
192 : struct NaClDescQuotaInterface *) = {
193 : NaClDescInvalidInternalize,
194 : NaClDescInternalizeNotImplemented,
195 : NaClDescIoInternalize,
196 : #if NACL_WINDOWS
197 : NaClDescConnCapInternalize,
198 : NaClDescInternalizeNotImplemented,
199 : #else
200 : NaClDescInternalizeNotImplemented,
201 : NaClDescConnCapFdInternalize,
202 : #endif
203 : NaClDescInternalizeNotImplemented, /* bound sockets cannot be transferred */
204 : NaClDescInternalizeNotImplemented, /* connected abstract base class */
205 : NaClDescImcShmInternalize,
206 : NaClDescInternalizeNotImplemented, /* mutex */
207 : NaClDescInternalizeNotImplemented, /* condvar */
208 : NaClDescInternalizeNotImplemented, /* semaphore */
209 : NaClDescSyncSocketInternalize,
210 : NaClDescXferableDataDescInternalize,
211 : NaClDescInternalizeNotImplemented, /* imc socket */
212 : NaClDescQuotaInternalize, /* quota wrapper */
213 : NaClDescInternalizeNotImplemented, /* device: postmessage */
214 : NaClDescInternalizeNotImplemented, /* custom */
215 : NaClDescNullInternalize,
216 : };
217 :
218 0 : char const *NaClDescTypeString(enum NaClDescTypeTag type_tag) {
219 : /* default functions for the vtable - return NOT_IMPLEMENTED */
220 0 : switch (type_tag) {
221 : #define MAP(E) case E: do { return #E; } while (0)
222 0 : MAP(NACL_DESC_INVALID);
223 0 : MAP(NACL_DESC_DIR);
224 0 : MAP(NACL_DESC_HOST_IO);
225 0 : MAP(NACL_DESC_CONN_CAP);
226 0 : MAP(NACL_DESC_CONN_CAP_FD);
227 0 : MAP(NACL_DESC_BOUND_SOCKET);
228 0 : MAP(NACL_DESC_CONNECTED_SOCKET);
229 0 : MAP(NACL_DESC_SHM);
230 0 : MAP(NACL_DESC_MUTEX);
231 0 : MAP(NACL_DESC_CONDVAR);
232 0 : MAP(NACL_DESC_SEMAPHORE);
233 0 : MAP(NACL_DESC_SYNC_SOCKET);
234 0 : MAP(NACL_DESC_TRANSFERABLE_DATA_SOCKET);
235 0 : MAP(NACL_DESC_IMC_SOCKET);
236 0 : MAP(NACL_DESC_QUOTA);
237 0 : MAP(NACL_DESC_DEVICE_POSTMESSAGE);
238 0 : MAP(NACL_DESC_CUSTOM);
239 0 : MAP(NACL_DESC_NULL);
240 : }
241 0 : return "BAD TYPE TAG";
242 0 : }
243 :
244 :
245 0 : void NaClDescDtorNotImplemented(struct NaClRefCount *vself) {
246 : UNREFERENCED_PARAMETER(vself);
247 :
248 0 : NaClLog(LOG_FATAL, "Must implement a destructor!\n");
249 0 : }
250 :
251 : uintptr_t NaClDescMapNotImplemented(struct NaClDesc *vself,
252 : struct NaClDescEffector *effp,
253 : void *start_addr,
254 : size_t len,
255 : int prot,
256 : int flags,
257 0 : nacl_off64_t offset) {
258 : UNREFERENCED_PARAMETER(effp);
259 : UNREFERENCED_PARAMETER(start_addr);
260 : UNREFERENCED_PARAMETER(len);
261 : UNREFERENCED_PARAMETER(prot);
262 : UNREFERENCED_PARAMETER(flags);
263 : UNREFERENCED_PARAMETER(offset);
264 :
265 : NaClLog(LOG_ERROR,
266 : "Map method is not implemented for object of type %s\n",
267 : NaClDescTypeString(((struct NaClDescVtbl const *)
268 0 : vself->base.vtbl)->typeTag));
269 0 : return -NACL_ABI_EINVAL;
270 0 : }
271 :
272 : #if NACL_WINDOWS
273 : int NaClDescUnmapUnsafeNotImplemented(struct NaClDesc *vself,
274 : void *start_addr,
275 0 : size_t len) {
276 : UNREFERENCED_PARAMETER(start_addr);
277 : UNREFERENCED_PARAMETER(len);
278 :
279 : NaClLog(LOG_ERROR,
280 : "Map method is not implemented for object of type %s\n",
281 : NaClDescTypeString(((struct NaClDescVtbl const *)
282 0 : vself->base.vtbl)->typeTag));
283 0 : return -NACL_ABI_EINVAL;
284 0 : }
285 : #endif
286 :
287 : ssize_t NaClDescReadNotImplemented(struct NaClDesc *vself,
288 : void *buf,
289 0 : size_t len) {
290 : UNREFERENCED_PARAMETER(buf);
291 : UNREFERENCED_PARAMETER(len);
292 :
293 : NaClLog(LOG_ERROR,
294 : "Read method is not implemented for object of type %s\n",
295 : NaClDescTypeString(((struct NaClDescVtbl const *)
296 0 : vself->base.vtbl)->typeTag));
297 0 : return -NACL_ABI_EINVAL;
298 0 : }
299 :
300 : ssize_t NaClDescWriteNotImplemented(struct NaClDesc *vself,
301 : void const *buf,
302 0 : size_t len) {
303 : UNREFERENCED_PARAMETER(buf);
304 : UNREFERENCED_PARAMETER(len);
305 :
306 : NaClLog(LOG_ERROR,
307 : "Write method is not implemented for object of type %s\n",
308 : NaClDescTypeString(((struct NaClDescVtbl const *)
309 0 : vself->base.vtbl)->typeTag));
310 0 : return -NACL_ABI_EINVAL;
311 0 : }
312 :
313 : nacl_off64_t NaClDescSeekNotImplemented(struct NaClDesc *vself,
314 : nacl_off64_t offset,
315 0 : int whence) {
316 : UNREFERENCED_PARAMETER(offset);
317 : UNREFERENCED_PARAMETER(whence);
318 :
319 : NaClLog(LOG_ERROR,
320 : "Seek method is not implemented for object of type %s\n",
321 : NaClDescTypeString(((struct NaClDescVtbl const *)
322 0 : vself->base.vtbl)->typeTag));
323 0 : return -NACL_ABI_EINVAL;
324 0 : }
325 :
326 : ssize_t NaClDescPReadNotImplemented(struct NaClDesc *vself,
327 : void *buf,
328 : size_t len,
329 0 : nacl_off64_t offset) {
330 : UNREFERENCED_PARAMETER(buf);
331 : UNREFERENCED_PARAMETER(len);
332 : UNREFERENCED_PARAMETER(offset);
333 :
334 : NaClLog(LOG_ERROR,
335 : "PRead method is not implemented for object of type %s\n",
336 : NaClDescTypeString(((struct NaClDescVtbl const *)
337 0 : vself->base.vtbl)->typeTag));
338 0 : return -NACL_ABI_EINVAL;
339 0 : }
340 :
341 : ssize_t NaClDescPWriteNotImplemented(struct NaClDesc *vself,
342 : void const *buf,
343 : size_t len,
344 0 : nacl_off64_t offset) {
345 : UNREFERENCED_PARAMETER(buf);
346 : UNREFERENCED_PARAMETER(len);
347 : UNREFERENCED_PARAMETER(offset);
348 :
349 : NaClLog(LOG_ERROR,
350 : "PWrite method is not implemented for object of type %s\n",
351 : NaClDescTypeString(((struct NaClDescVtbl const *)
352 0 : vself->base.vtbl)->typeTag));
353 0 : return -NACL_ABI_EINVAL;
354 0 : }
355 :
356 : int NaClDescFstatNotImplemented(struct NaClDesc *vself,
357 0 : struct nacl_abi_stat *statbuf) {
358 : UNREFERENCED_PARAMETER(statbuf);
359 :
360 : NaClLog(LOG_ERROR,
361 : "Fstat method is not implemented for object of type %s\n",
362 : NaClDescTypeString(((struct NaClDescVtbl const *)
363 0 : vself->base.vtbl)->typeTag));
364 0 : return -NACL_ABI_EINVAL;
365 0 : }
366 :
367 : ssize_t NaClDescGetdentsNotImplemented(struct NaClDesc *vself,
368 : void *dirp,
369 0 : size_t count) {
370 : UNREFERENCED_PARAMETER(dirp);
371 : UNREFERENCED_PARAMETER(count);
372 :
373 : NaClLog(LOG_ERROR,
374 : "Getdents method is not implemented for object of type %s\n",
375 : NaClDescTypeString(((struct NaClDescVtbl const *)
376 0 : vself->base.vtbl)->typeTag));
377 0 : return -NACL_ABI_EINVAL;
378 0 : }
379 :
380 : int NaClDescExternalizeSizeNotImplemented(struct NaClDesc *vself,
381 : size_t *nbytes,
382 0 : size_t *nhandles) {
383 : UNREFERENCED_PARAMETER(nbytes);
384 : UNREFERENCED_PARAMETER(nhandles);
385 :
386 : NaClLog(LOG_ERROR,
387 : "ExternalizeSize method is not implemented for object of type %s\n",
388 : NaClDescTypeString(((struct NaClDescVtbl const *)
389 0 : vself->base.vtbl)->typeTag));
390 0 : return -NACL_ABI_EINVAL;
391 0 : }
392 :
393 : int NaClDescExternalizeNotImplemented(struct NaClDesc *vself,
394 0 : struct NaClDescXferState *xfer) {
395 : UNREFERENCED_PARAMETER(xfer);
396 :
397 : NaClLog(LOG_ERROR,
398 : "Externalize method is not implemented for object of type %s\n",
399 : NaClDescTypeString(((struct NaClDescVtbl const *)
400 0 : vself->base.vtbl)->typeTag));
401 0 : return -NACL_ABI_EINVAL;
402 0 : }
403 :
404 0 : int NaClDescLockNotImplemented(struct NaClDesc *vself) {
405 : NaClLog(LOG_ERROR,
406 : "Lock method is not implemented for object of type %s\n",
407 : NaClDescTypeString(((struct NaClDescVtbl const *)
408 0 : vself->base.vtbl)->typeTag));
409 0 : return -NACL_ABI_EINVAL;
410 0 : }
411 :
412 0 : int NaClDescTryLockNotImplemented(struct NaClDesc *vself) {
413 : NaClLog(LOG_ERROR,
414 : "TryLock method is not implemented for object of type %s\n",
415 : NaClDescTypeString(((struct NaClDescVtbl const *)
416 0 : vself->base.vtbl)->typeTag));
417 0 : return -NACL_ABI_EINVAL;
418 0 : }
419 :
420 0 : int NaClDescUnlockNotImplemented(struct NaClDesc *vself) {
421 : NaClLog(LOG_ERROR,
422 : "Unlock method is not implemented for object of type %s\n",
423 : NaClDescTypeString(((struct NaClDescVtbl const *)
424 0 : vself->base.vtbl)->typeTag));
425 0 : return -NACL_ABI_EINVAL;
426 0 : }
427 :
428 : int NaClDescWaitNotImplemented(struct NaClDesc *vself,
429 0 : struct NaClDesc *mutex) {
430 : UNREFERENCED_PARAMETER(mutex);
431 :
432 : NaClLog(LOG_ERROR,
433 : "Wait method is not implemented for object of type %s\n",
434 : NaClDescTypeString(((struct NaClDescVtbl const *)
435 0 : vself->base.vtbl)->typeTag));
436 0 : return -NACL_ABI_EINVAL;
437 0 : }
438 :
439 : int NaClDescTimedWaitAbsNotImplemented(struct NaClDesc *vself,
440 : struct NaClDesc *mutex,
441 0 : struct nacl_abi_timespec const *ts) {
442 : UNREFERENCED_PARAMETER(mutex);
443 : UNREFERENCED_PARAMETER(ts);
444 :
445 : NaClLog(LOG_ERROR,
446 : "TimedWaitAbs method is not implemented for object of type %s\n",
447 : NaClDescTypeString(((struct NaClDescVtbl const *)
448 0 : vself->base.vtbl)->typeTag));
449 0 : return -NACL_ABI_EINVAL;
450 0 : }
451 :
452 0 : int NaClDescSignalNotImplemented(struct NaClDesc *vself) {
453 : NaClLog(LOG_ERROR,
454 : "Signal method is not implemented for object of type %s\n",
455 : NaClDescTypeString(((struct NaClDescVtbl const *)
456 0 : vself->base.vtbl)->typeTag));
457 0 : return -NACL_ABI_EINVAL;
458 0 : }
459 :
460 0 : int NaClDescBroadcastNotImplemented(struct NaClDesc *vself) {
461 : NaClLog(LOG_ERROR,
462 : "Broadcast method is not implemented for object of type %s\n",
463 : NaClDescTypeString(((struct NaClDescVtbl const *)
464 0 : vself->base.vtbl)->typeTag));
465 0 : return -NACL_ABI_EINVAL;
466 0 : }
467 :
468 : ssize_t NaClDescSendMsgNotImplemented(
469 : struct NaClDesc *vself,
470 : const struct NaClImcTypedMsgHdr *nitmhp,
471 0 : int flags) {
472 : UNREFERENCED_PARAMETER(nitmhp);
473 : UNREFERENCED_PARAMETER(flags);
474 :
475 : NaClLog(LOG_ERROR,
476 : "SendMsg method is not implemented for object of type %s\n",
477 : NaClDescTypeString(((struct NaClDescVtbl const *)
478 0 : vself->base.vtbl)->typeTag));
479 0 : return -NACL_ABI_EINVAL;
480 0 : }
481 :
482 : ssize_t NaClDescRecvMsgNotImplemented(
483 : struct NaClDesc *vself,
484 : struct NaClImcTypedMsgHdr *nitmhp,
485 : int flags,
486 0 : struct NaClDescQuotaInterface *quota_interface) {
487 : UNREFERENCED_PARAMETER(nitmhp);
488 : UNREFERENCED_PARAMETER(flags);
489 : UNREFERENCED_PARAMETER(quota_interface);
490 :
491 : NaClLog(LOG_ERROR,
492 : "RecvMsg method is not implemented for object of type %s\n",
493 : NaClDescTypeString(((struct NaClDescVtbl const *)
494 0 : vself->base.vtbl)->typeTag));
495 0 : return -NACL_ABI_EINVAL;
496 0 : }
497 :
498 : ssize_t NaClDescLowLevelSendMsgNotImplemented(
499 : struct NaClDesc *vself,
500 : struct NaClMessageHeader const *dgram,
501 0 : int flags) {
502 : UNREFERENCED_PARAMETER(dgram);
503 : UNREFERENCED_PARAMETER(flags);
504 :
505 : NaClLog(LOG_ERROR,
506 : "LowLevelSendMsg method is not implemented for object of type %s\n",
507 : NaClDescTypeString(((struct NaClDescVtbl const *)
508 0 : vself->base.vtbl)->typeTag));
509 0 : return -NACL_ABI_EINVAL;
510 0 : }
511 :
512 : ssize_t NaClDescLowLevelRecvMsgNotImplemented(
513 : struct NaClDesc *vself,
514 : struct NaClMessageHeader *dgram,
515 0 : int flags) {
516 : UNREFERENCED_PARAMETER(dgram);
517 : UNREFERENCED_PARAMETER(flags);
518 :
519 : NaClLog(LOG_ERROR,
520 : "LowLevelRecvMsg method is not implemented for object of type %s\n",
521 : NaClDescTypeString(((struct NaClDescVtbl const *)
522 0 : vself->base.vtbl)->typeTag));
523 0 : return -NACL_ABI_EINVAL;
524 0 : }
525 :
526 : int NaClDescConnectAddrNotImplemented(struct NaClDesc *vself,
527 0 : struct NaClDesc **result) {
528 : UNREFERENCED_PARAMETER(result);
529 :
530 : NaClLog(LOG_ERROR,
531 : "ConnectAddr method is not implemented for object of type %s\n",
532 : NaClDescTypeString(((struct NaClDescVtbl const *)
533 0 : vself->base.vtbl)->typeTag));
534 0 : return -NACL_ABI_EINVAL;
535 0 : }
536 :
537 : int NaClDescAcceptConnNotImplemented(struct NaClDesc *vself,
538 0 : struct NaClDesc **result) {
539 : UNREFERENCED_PARAMETER(result);
540 :
541 : NaClLog(LOG_ERROR,
542 : "AcceptConn method is not implemented for object of type %s\n",
543 : NaClDescTypeString(((struct NaClDescVtbl const *)
544 0 : vself->base.vtbl)->typeTag));
545 0 : return -NACL_ABI_EINVAL;
546 0 : }
547 :
548 0 : int NaClDescPostNotImplemented(struct NaClDesc *vself) {
549 : NaClLog(LOG_ERROR,
550 : "Post method is not implemented for object of type %s\n",
551 : NaClDescTypeString(((struct NaClDescVtbl const *)
552 0 : vself->base.vtbl)->typeTag));
553 0 : return -NACL_ABI_EINVAL;
554 0 : }
555 :
556 0 : int NaClDescSemWaitNotImplemented(struct NaClDesc *vself) {
557 : NaClLog(LOG_ERROR,
558 : "SemWait method is not implemented for object of type %s\n",
559 : NaClDescTypeString(((struct NaClDescVtbl const *)
560 0 : vself->base.vtbl)->typeTag));
561 0 : return -NACL_ABI_EINVAL;
562 0 : }
563 :
564 0 : int NaClDescGetValueNotImplemented(struct NaClDesc *vself) {
565 : NaClLog(LOG_ERROR,
566 : "GetValue method is not implemented for object of type %s\n",
567 : NaClDescTypeString(((struct NaClDescVtbl const *)
568 0 : vself->base.vtbl)->typeTag));
569 0 : return -NACL_ABI_EINVAL;
570 0 : }
571 :
572 : int NaClDescInternalizeNotImplemented(
573 : struct NaClDesc **out_desc,
574 : struct NaClDescXferState *xfer,
575 0 : struct NaClDescQuotaInterface *quota_interface) {
576 : UNREFERENCED_PARAMETER(out_desc);
577 : UNREFERENCED_PARAMETER(xfer);
578 : UNREFERENCED_PARAMETER(quota_interface);
579 :
580 : NaClLog(LOG_ERROR,
581 0 : "Attempted transfer of non-transferable descriptor\n");
582 0 : return -NACL_ABI_EIO;
583 0 : }
584 :
585 0 : int NaClSafeCloseNaClHandle(NaClHandle h) {
586 0 : if (NACL_INVALID_HANDLE != h) {
587 0 : return NaClClose(h);
588 : }
589 0 : return 0;
590 0 : }
591 :
592 : int NaClDescSetMetadata(struct NaClDesc *self,
593 : int32_t metadata_type,
594 : uint32_t metadata_num_bytes,
595 1 : uint8_t const *metadata_bytes) {
596 1 : uint8_t *buffer = NULL;
597 : int rv;
598 :
599 1 : if (metadata_type < 0) {
600 0 : return -NACL_ABI_EINVAL;
601 : }
602 1 : buffer = malloc(metadata_num_bytes);
603 1 : if (NULL == buffer) {
604 0 : return -NACL_ABI_ENOMEM;
605 : }
606 :
607 1 : NaClRefCountLock(&self->base);
608 1 : if (0 != (self->flags & NACL_DESC_FLAGS_HAS_METADATA)) {
609 0 : rv = -NACL_ABI_EPERM;
610 0 : goto done;
611 : }
612 1 : memcpy(buffer, metadata_bytes, metadata_num_bytes);
613 1 : self->metadata_type = metadata_type;
614 1 : self->metadata_num_bytes = metadata_num_bytes;
615 1 : free(self->metadata);
616 1 : self->metadata = buffer;
617 1 : self->flags = self->flags | NACL_DESC_FLAGS_HAS_METADATA;
618 1 : rv = 0;
619 : done:
620 1 : NaClRefCountUnlock(&self->base);
621 1 : if (rv < 0) {
622 0 : free(buffer);
623 : }
624 1 : return rv;
625 1 : }
626 :
627 : int32_t NaClDescGetMetadata(struct NaClDesc *self,
628 : uint32_t *metadata_buffer_bytes_in_out,
629 1 : uint8_t *metadata_buffer) {
630 : int rv;
631 : uint32_t bytes_to_copy;
632 :
633 1 : NaClRefCountLock(&self->base);
634 1 : if (0 == (NACL_DESC_FLAGS_HAS_METADATA & self->flags)) {
635 0 : *metadata_buffer_bytes_in_out = 0;
636 0 : rv = NACL_DESC_METADATA_NONE_TYPE;
637 0 : goto done;
638 : }
639 1 : if (NACL_DESC_METADATA_NONE_TYPE == self->metadata_type) {
640 0 : *metadata_buffer_bytes_in_out = 0;
641 0 : rv = NACL_DESC_METADATA_NONE_TYPE;
642 0 : goto done;
643 : }
644 1 : bytes_to_copy = *metadata_buffer_bytes_in_out;
645 1 : if (bytes_to_copy > self->metadata_num_bytes) {
646 1 : bytes_to_copy = self->metadata_num_bytes;
647 : }
648 1 : if (NULL != metadata_buffer && 0 < bytes_to_copy) {
649 1 : memcpy(metadata_buffer, self->metadata, bytes_to_copy);
650 : }
651 1 : *metadata_buffer_bytes_in_out = self->metadata_num_bytes;
652 1 : rv = self->metadata_type;
653 : done:
654 1 : NaClRefCountUnlock(&self->base);
655 1 : return rv;
656 1 : }
657 :
658 : /*
659 : * Consider switching to atomic word operations. This should be
660 : * infrequent enought that it should not matter.
661 : */
662 : void NaClDescSetFlags(struct NaClDesc *self,
663 3 : uint32_t flags) {
664 3 : NaClRefCountLock(&self->base);
665 : self->flags = ((self->flags & ~NACL_DESC_FLAGS_PUBLIC_MASK) |
666 3 : (flags & NACL_DESC_FLAGS_PUBLIC_MASK));
667 3 : NaClRefCountUnlock(&self->base);
668 3 : }
669 :
670 0 : uint32_t NaClDescGetFlags(struct NaClDesc *self) {
671 : uint32_t rv;
672 0 : NaClRefCountLock(&self->base);
673 0 : rv = self->flags & NACL_DESC_FLAGS_PUBLIC_MASK;
674 0 : NaClRefCountUnlock(&self->base);
675 0 : return rv;
676 0 : }
677 :
678 0 : int NaClDescIsSafeForMmap(struct NaClDesc *self) {
679 0 : return 0 != (NaClDescGetFlags(self) & NACL_DESC_FLAGS_MMAP_EXEC_OK);
680 0 : }
681 :
682 0 : void NaClDescMarkSafeForMmap(struct NaClDesc *self) {
683 : NaClDescSetFlags(self,
684 0 : NACL_DESC_FLAGS_MMAP_EXEC_OK | NaClDescGetFlags(self));
685 0 : }
686 :
687 0 : int32_t NaClDescIsattyNotImplemented(struct NaClDesc *vself) {
688 : NaClLog(LOG_ERROR,
689 : "Isatty method is not implemented for object of type %s\n",
690 : NaClDescTypeString(((struct NaClDescVtbl const *)
691 0 : vself->base.vtbl)->typeTag));
692 0 : return -NACL_ABI_ENOTTY;
693 0 : }
694 :
695 : struct NaClDescVtbl const kNaClDescVtbl = {
696 : {
697 : NaClDescDtor,
698 : },
699 : NaClDescMapNotImplemented,
700 : NACL_DESC_UNMAP_NOT_IMPLEMENTED
701 : NaClDescReadNotImplemented,
702 : NaClDescWriteNotImplemented,
703 : NaClDescSeekNotImplemented,
704 : NaClDescPReadNotImplemented,
705 : NaClDescPWriteNotImplemented,
706 : NaClDescFstatNotImplemented,
707 : NaClDescGetdentsNotImplemented,
708 : NaClDescExternalizeSizeNotImplemented,
709 : NaClDescExternalizeNotImplemented,
710 : NaClDescLockNotImplemented,
711 : NaClDescTryLockNotImplemented,
712 : NaClDescUnlockNotImplemented,
713 : NaClDescWaitNotImplemented,
714 : NaClDescTimedWaitAbsNotImplemented,
715 : NaClDescSignalNotImplemented,
716 : NaClDescBroadcastNotImplemented,
717 : NaClDescSendMsgNotImplemented,
718 : NaClDescRecvMsgNotImplemented,
719 : NaClDescLowLevelSendMsgNotImplemented,
720 : NaClDescLowLevelRecvMsgNotImplemented,
721 : NaClDescConnectAddrNotImplemented,
722 : NaClDescAcceptConnNotImplemented,
723 : NaClDescPostNotImplemented,
724 : NaClDescSemWaitNotImplemented,
725 : NaClDescGetValueNotImplemented,
726 : NaClDescSetMetadata,
727 : NaClDescGetMetadata,
728 : NaClDescSetFlags,
729 : NaClDescGetFlags,
730 : NaClDescIsattyNotImplemented,
731 : (enum NaClDescTypeTag) -1, /* NaClDesc is an abstract base class */
732 : };
|