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 3300 : int NaClDescCtor(struct NaClDesc *ndp) {
77 : /* this should be a compile-time test */
78 : if (0 != (sizeof(struct NaClInternalHeader) & 0xf)) {
79 : NaClLog(LOG_FATAL,
80 : "Internal error. NaClInternalHeader size not a"
81 : " multiple of 16\n");
82 : }
83 3300 : ndp->flags = 0;
84 3300 : ndp->metadata_type = NACL_DESC_METADATA_NONE_TYPE;
85 3300 : ndp->metadata_num_bytes = 0;
86 3300 : ndp->metadata = NULL;
87 3300 : return NaClRefCountCtor(&ndp->base);
88 : }
89 :
90 1182 : static void NaClDescDtor(struct NaClRefCount *nrcp) {
91 1182 : struct NaClDesc *ndp = (struct NaClDesc *) nrcp;
92 1182 : free(ndp->metadata);
93 1182 : ndp->metadata = NULL;
94 1182 : nrcp->vtbl = &kNaClRefCountVtbl;
95 1182 : (*nrcp->vtbl->Dtor)(nrcp);
96 1182 : }
97 :
98 85740 : struct NaClDesc *NaClDescRef(struct NaClDesc *ndp) {
99 85740 : return (struct NaClDesc *) NaClRefCountRef(&ndp->base);
100 : }
101 :
102 74727 : void NaClDescUnref(struct NaClDesc *ndp) {
103 74727 : NaClRefCountUnref(&ndp->base);
104 74727 : }
105 :
106 11410 : void NaClDescSafeUnref(struct NaClDesc *ndp) {
107 11410 : if (NULL != ndp) {
108 10163 : NaClRefCountUnref(&ndp->base);
109 : }
110 11410 : }
111 :
112 84 : int NaClDescExternalizeSize(struct NaClDesc *self,
113 : size_t *nbytes,
114 : size_t *nhandles) {
115 84 : *nbytes = sizeof self->flags;
116 84 : if (0 != (NACL_DESC_FLAGS_HAS_METADATA & self->flags)) {
117 54 : *nbytes += (sizeof self->metadata_type +
118 27 : sizeof self->metadata_num_bytes + self->metadata_num_bytes);
119 : }
120 84 : *nhandles = 0;
121 84 : return 0;
122 : }
123 :
124 84 : int NaClDescExternalize(struct NaClDesc *self,
125 : struct NaClDescXferState *xfer) {
126 84 : memcpy(xfer->next_byte, &self->flags, sizeof self->flags);
127 84 : xfer->next_byte += sizeof self->flags;
128 84 : if (0 != (NACL_DESC_FLAGS_HAS_METADATA & self->flags)) {
129 27 : memcpy(xfer->next_byte, &self->metadata_type, sizeof self->metadata_type);
130 27 : xfer->next_byte += sizeof self->metadata_type;
131 27 : memcpy(xfer->next_byte, &self->metadata_num_bytes,
132 : sizeof self->metadata_num_bytes);
133 27 : xfer->next_byte += sizeof self->metadata_num_bytes;
134 27 : memcpy(xfer->next_byte, self->metadata, self->metadata_num_bytes);
135 27 : xfer->next_byte += self->metadata_num_bytes;
136 : }
137 84 : return 0;
138 : }
139 :
140 110 : int NaClDescInternalizeCtor(struct NaClDesc *vself,
141 : struct NaClDescXferState *xfer) {
142 : int rv;
143 : char *nxt;
144 :
145 110 : rv = NaClDescCtor(vself);
146 110 : if (0 == rv) {
147 0 : return rv;
148 : }
149 110 : nxt = xfer->next_byte;
150 110 : if (nxt + sizeof vself->flags > xfer->byte_buffer_end) {
151 0 : rv = 0;
152 0 : goto done;
153 : }
154 110 : memcpy(&vself->flags, nxt, sizeof vself->flags);
155 110 : nxt += sizeof vself->flags;
156 110 : if (0 == (NACL_DESC_FLAGS_HAS_METADATA & vself->flags)) {
157 83 : xfer->next_byte = nxt;
158 83 : rv = 1;
159 83 : goto done;
160 : }
161 54 : if (nxt + sizeof vself->metadata_type + sizeof vself->metadata_num_bytes >
162 27 : xfer->byte_buffer_end) {
163 0 : rv = 0;
164 0 : goto done;
165 : }
166 27 : memcpy(&vself->metadata_type, nxt, sizeof vself->metadata_type);
167 27 : nxt += sizeof vself->metadata_type;
168 27 : memcpy(&vself->metadata_num_bytes, nxt, sizeof vself->metadata_num_bytes);
169 27 : nxt += sizeof vself->metadata_num_bytes;
170 27 : if (nxt + vself->metadata_num_bytes > xfer->byte_buffer_end) {
171 0 : rv = 0;
172 0 : goto done;
173 : }
174 27 : if (NULL == (vself->metadata = malloc(vself->metadata_num_bytes))) {
175 0 : rv = 0;
176 0 : goto done;
177 : }
178 27 : memcpy(vself->metadata, nxt, vself->metadata_num_bytes);
179 27 : nxt += vself->metadata_num_bytes;
180 27 : xfer->next_byte = nxt;
181 27 : rv = 1;
182 : done:
183 110 : if (!rv) {
184 0 : (*NACL_VTBL(NaClRefCount, vself)->Dtor)((struct NaClRefCount *) vself);
185 : }
186 110 : return rv;
187 : }
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 2 : char const *NaClDescTypeString(enum NaClDescTypeTag type_tag) {
219 : /* default functions for the vtable - return NOT_IMPLEMENTED */
220 2 : 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 1 : 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 1 : 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 : }
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 0 : 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 : 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 0 : 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 : }
271 :
272 : #if NACL_WINDOWS
273 : int NaClDescUnmapUnsafeNotImplemented(struct NaClDesc *vself,
274 : void *start_addr,
275 : 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 : vself->base.vtbl)->typeTag));
283 : return -NACL_ABI_EINVAL;
284 : }
285 : #endif
286 :
287 0 : ssize_t NaClDescReadNotImplemented(struct NaClDesc *vself,
288 : void *buf,
289 : size_t len) {
290 : UNREFERENCED_PARAMETER(buf);
291 : UNREFERENCED_PARAMETER(len);
292 :
293 0 : 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 : }
299 :
300 0 : ssize_t NaClDescWriteNotImplemented(struct NaClDesc *vself,
301 : void const *buf,
302 : size_t len) {
303 : UNREFERENCED_PARAMETER(buf);
304 : UNREFERENCED_PARAMETER(len);
305 :
306 0 : 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 : }
312 :
313 0 : nacl_off64_t NaClDescSeekNotImplemented(struct NaClDesc *vself,
314 : nacl_off64_t offset,
315 : int whence) {
316 : UNREFERENCED_PARAMETER(offset);
317 : UNREFERENCED_PARAMETER(whence);
318 :
319 0 : 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 : }
325 :
326 0 : ssize_t NaClDescPReadNotImplemented(struct NaClDesc *vself,
327 : void *buf,
328 : size_t len,
329 : nacl_off64_t offset) {
330 : UNREFERENCED_PARAMETER(buf);
331 : UNREFERENCED_PARAMETER(len);
332 : UNREFERENCED_PARAMETER(offset);
333 :
334 0 : 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 : }
340 :
341 0 : ssize_t NaClDescPWriteNotImplemented(struct NaClDesc *vself,
342 : void const *buf,
343 : size_t len,
344 : nacl_off64_t offset) {
345 : UNREFERENCED_PARAMETER(buf);
346 : UNREFERENCED_PARAMETER(len);
347 : UNREFERENCED_PARAMETER(offset);
348 :
349 0 : 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 : }
355 :
356 0 : int NaClDescFstatNotImplemented(struct NaClDesc *vself,
357 : struct nacl_abi_stat *statbuf) {
358 : UNREFERENCED_PARAMETER(statbuf);
359 :
360 0 : 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 : }
366 :
367 0 : ssize_t NaClDescGetdentsNotImplemented(struct NaClDesc *vself,
368 : void *dirp,
369 : size_t count) {
370 : UNREFERENCED_PARAMETER(dirp);
371 : UNREFERENCED_PARAMETER(count);
372 :
373 0 : 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 : }
379 :
380 2 : int NaClDescExternalizeSizeNotImplemented(struct NaClDesc *vself,
381 : size_t *nbytes,
382 : size_t *nhandles) {
383 : UNREFERENCED_PARAMETER(nbytes);
384 : UNREFERENCED_PARAMETER(nhandles);
385 :
386 2 : NaClLog(LOG_ERROR,
387 : "ExternalizeSize method is not implemented for object of type %s\n",
388 : NaClDescTypeString(((struct NaClDescVtbl const *)
389 2 : vself->base.vtbl)->typeTag));
390 2 : return -NACL_ABI_EINVAL;
391 : }
392 :
393 0 : int NaClDescExternalizeNotImplemented(struct NaClDesc *vself,
394 : struct NaClDescXferState *xfer) {
395 : UNREFERENCED_PARAMETER(xfer);
396 :
397 0 : 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 : }
403 :
404 0 : int NaClDescLockNotImplemented(struct NaClDesc *vself) {
405 0 : 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 : }
411 :
412 0 : int NaClDescTryLockNotImplemented(struct NaClDesc *vself) {
413 0 : 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 : }
419 :
420 0 : int NaClDescUnlockNotImplemented(struct NaClDesc *vself) {
421 0 : 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 : }
427 :
428 0 : int NaClDescWaitNotImplemented(struct NaClDesc *vself,
429 : struct NaClDesc *mutex) {
430 : UNREFERENCED_PARAMETER(mutex);
431 :
432 0 : 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 : }
438 :
439 0 : int NaClDescTimedWaitAbsNotImplemented(struct NaClDesc *vself,
440 : struct NaClDesc *mutex,
441 : struct nacl_abi_timespec const *ts) {
442 : UNREFERENCED_PARAMETER(mutex);
443 : UNREFERENCED_PARAMETER(ts);
444 :
445 0 : 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 : }
451 :
452 0 : int NaClDescSignalNotImplemented(struct NaClDesc *vself) {
453 0 : 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 : }
459 :
460 0 : int NaClDescBroadcastNotImplemented(struct NaClDesc *vself) {
461 0 : 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 : }
467 :
468 0 : ssize_t NaClDescSendMsgNotImplemented(
469 : struct NaClDesc *vself,
470 : const struct NaClImcTypedMsgHdr *nitmhp,
471 : int flags) {
472 : UNREFERENCED_PARAMETER(nitmhp);
473 : UNREFERENCED_PARAMETER(flags);
474 :
475 0 : 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 : }
481 :
482 0 : ssize_t NaClDescRecvMsgNotImplemented(
483 : struct NaClDesc *vself,
484 : struct NaClImcTypedMsgHdr *nitmhp,
485 : int flags,
486 : struct NaClDescQuotaInterface *quota_interface) {
487 : UNREFERENCED_PARAMETER(nitmhp);
488 : UNREFERENCED_PARAMETER(flags);
489 : UNREFERENCED_PARAMETER(quota_interface);
490 :
491 0 : 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 : }
497 :
498 0 : ssize_t NaClDescLowLevelSendMsgNotImplemented(
499 : struct NaClDesc *vself,
500 : struct NaClMessageHeader const *dgram,
501 : int flags) {
502 : UNREFERENCED_PARAMETER(dgram);
503 : UNREFERENCED_PARAMETER(flags);
504 :
505 0 : 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 : }
511 :
512 0 : ssize_t NaClDescLowLevelRecvMsgNotImplemented(
513 : struct NaClDesc *vself,
514 : struct NaClMessageHeader *dgram,
515 : int flags) {
516 : UNREFERENCED_PARAMETER(dgram);
517 : UNREFERENCED_PARAMETER(flags);
518 :
519 0 : 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 : }
525 :
526 0 : int NaClDescConnectAddrNotImplemented(struct NaClDesc *vself,
527 : struct NaClDesc **result) {
528 : UNREFERENCED_PARAMETER(result);
529 :
530 0 : 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 : }
536 :
537 0 : int NaClDescAcceptConnNotImplemented(struct NaClDesc *vself,
538 : struct NaClDesc **result) {
539 : UNREFERENCED_PARAMETER(result);
540 :
541 0 : 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 : }
547 :
548 0 : int NaClDescPostNotImplemented(struct NaClDesc *vself) {
549 0 : 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 : }
555 :
556 0 : int NaClDescSemWaitNotImplemented(struct NaClDesc *vself) {
557 0 : 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 : }
563 :
564 0 : int NaClDescGetValueNotImplemented(struct NaClDesc *vself) {
565 0 : 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 : }
571 :
572 0 : int NaClDescInternalizeNotImplemented(
573 : struct NaClDesc **out_desc,
574 : struct NaClDescXferState *xfer,
575 : struct NaClDescQuotaInterface *quota_interface) {
576 : UNREFERENCED_PARAMETER(out_desc);
577 : UNREFERENCED_PARAMETER(xfer);
578 : UNREFERENCED_PARAMETER(quota_interface);
579 :
580 0 : NaClLog(LOG_ERROR,
581 : "Attempted transfer of non-transferable descriptor\n");
582 0 : return -NACL_ABI_EIO;
583 : }
584 :
585 120 : int NaClSafeCloseNaClHandle(NaClHandle h) {
586 120 : if (NACL_INVALID_HANDLE != h) {
587 2 : return NaClClose(h);
588 : }
589 118 : return 0;
590 : }
591 :
592 37 : int NaClDescSetMetadata(struct NaClDesc *self,
593 : int32_t metadata_type,
594 : uint32_t metadata_num_bytes,
595 : uint8_t const *metadata_bytes) {
596 37 : uint8_t *buffer = NULL;
597 : int rv;
598 :
599 37 : if (metadata_type < 0) {
600 0 : return -NACL_ABI_EINVAL;
601 : }
602 37 : buffer = malloc(metadata_num_bytes);
603 37 : if (NULL == buffer) {
604 0 : return -NACL_ABI_ENOMEM;
605 : }
606 :
607 37 : NaClRefCountLock(&self->base);
608 37 : if (0 != (self->flags & NACL_DESC_FLAGS_HAS_METADATA)) {
609 0 : rv = -NACL_ABI_EPERM;
610 0 : goto done;
611 : }
612 37 : memcpy(buffer, metadata_bytes, metadata_num_bytes);
613 37 : self->metadata_type = metadata_type;
614 37 : self->metadata_num_bytes = metadata_num_bytes;
615 37 : free(self->metadata);
616 37 : self->metadata = buffer;
617 37 : self->flags = self->flags | NACL_DESC_FLAGS_HAS_METADATA;
618 37 : rv = 0;
619 : done:
620 37 : NaClRefCountUnlock(&self->base);
621 37 : if (rv < 0) {
622 0 : free(buffer);
623 : }
624 37 : return rv;
625 : }
626 :
627 340 : int32_t NaClDescGetMetadata(struct NaClDesc *self,
628 : uint32_t *metadata_buffer_bytes_in_out,
629 : uint8_t *metadata_buffer) {
630 : int rv;
631 : uint32_t bytes_to_copy;
632 :
633 340 : NaClRefCountLock(&self->base);
634 340 : if (0 == (NACL_DESC_FLAGS_HAS_METADATA & self->flags)) {
635 294 : *metadata_buffer_bytes_in_out = 0;
636 294 : rv = NACL_DESC_METADATA_NONE_TYPE;
637 294 : goto done;
638 : }
639 46 : 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 46 : bytes_to_copy = *metadata_buffer_bytes_in_out;
645 46 : if (bytes_to_copy > self->metadata_num_bytes) {
646 26 : bytes_to_copy = self->metadata_num_bytes;
647 : }
648 46 : if (NULL != metadata_buffer && 0 < bytes_to_copy) {
649 36 : memcpy(metadata_buffer, self->metadata, bytes_to_copy);
650 : }
651 46 : *metadata_buffer_bytes_in_out = self->metadata_num_bytes;
652 46 : rv = self->metadata_type;
653 : done:
654 340 : NaClRefCountUnlock(&self->base);
655 340 : return rv;
656 : }
657 :
658 : /*
659 : * Consider switching to atomic word operations. This should be
660 : * infrequent enought that it should not matter.
661 : */
662 1778 : void NaClDescSetFlags(struct NaClDesc *self,
663 : uint32_t flags) {
664 1778 : NaClRefCountLock(&self->base);
665 3556 : self->flags = ((self->flags & ~NACL_DESC_FLAGS_PUBLIC_MASK) |
666 1778 : (flags & NACL_DESC_FLAGS_PUBLIC_MASK));
667 1778 : NaClRefCountUnlock(&self->base);
668 1778 : }
669 :
670 888 : uint32_t NaClDescGetFlags(struct NaClDesc *self) {
671 : uint32_t rv;
672 888 : NaClRefCountLock(&self->base);
673 888 : rv = self->flags & NACL_DESC_FLAGS_PUBLIC_MASK;
674 888 : NaClRefCountUnlock(&self->base);
675 888 : return rv;
676 : }
677 :
678 840 : int NaClDescIsSafeForMmap(struct NaClDesc *self) {
679 840 : return 0 != (NaClDescGetFlags(self) & NACL_DESC_FLAGS_MMAP_EXEC_OK);
680 : }
681 :
682 2 : void NaClDescMarkSafeForMmap(struct NaClDesc *self) {
683 2 : NaClDescSetFlags(self,
684 2 : NACL_DESC_FLAGS_MMAP_EXEC_OK | NaClDescGetFlags(self));
685 2 : }
686 :
687 0 : int32_t NaClDescIsattyNotImplemented(struct NaClDesc *vself) {
688 0 : 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 : }
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 : };
|