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