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