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