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.
8 * NaCl Service Runtime. I/O Descriptor / Handle abstraction.
11 #ifndef NATIVE_CLIENT_SRC_TRUSTED_DESC_NACL_DESC_BASE_H_
12 #define NATIVE_CLIENT_SRC_TRUSTED_DESC_NACL_DESC_BASE_H_
15 #include <sys/types.h>
18 #include "native_client/src/include/nacl_base.h"
19 #include "native_client/src/include/portability.h"
21 #include "native_client/src/public/desc_metadata_types.h"
24 #include "native_client/src/shared/imc/nacl_imc_c.h"
26 /* for nacl_off64_t */
27 #include "native_client/src/shared/platform/nacl_host_desc.h"
28 #include "native_client/src/shared/platform/nacl_sync.h"
30 #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
36 struct nacl_abi_timespec;
37 struct NaClDescEffector;
38 struct NaClDescQuotaInterface;
39 struct NaClImcTypedMsgHdr;
40 struct NaClMessageHeader;
43 * Externalization / internalization state, used by
44 * Externalize/Internalize functions. Externalize convert the
45 * descriptor represented by the self (this) object to an entry in the
46 * handles table in a NaClMessageHeader, and the Internalize function
47 * is a factory that takes a dgram and NaClDescXferState and
48 * constructs a vector of NaClDesc objects.
50 * This is essentially a pair of input/output iterators. The *_end
51 * values are not needed during externalization, since the SendMsg
52 * code will have queried ExternalizeSize to ensure that there is
53 * enough space. During internalization, however, we try to be more
54 * paranoid and check that we do not overrun our buffers.
56 * NB: we must assume that the NaClHandle values passed are the right
57 * type; if not, it is possible to violate invariant properties
58 * required by the various subclasses of NaClDesc.
60 struct NaClDescXferState {
62 * In/out value, used for both serialization and deserialization.
63 * The Externalize method read/write type tags that are part of the
64 * message header as well as data-based capabilities in a
65 * self-describing format.
68 char *byte_buffer_end;
71 * In/out value. Next handle to work on.
73 NaClHandle *next_handle;
74 NaClHandle *handle_buffer_end;
77 enum NaClDescTypeTag {
82 NACL_DESC_CONN_CAP_FD,
83 NACL_DESC_BOUND_SOCKET,
84 NACL_DESC_CONNECTED_SOCKET,
90 NACL_DESC_SYNC_SOCKET,
91 NACL_DESC_TRANSFERABLE_DATA_SOCKET,
95 NACL_DESC_DEVICE_POSTMESSAGE,
99 * Add new NaClDesc subclasses here.
101 * NB: when we add new tag types, NaClDescInternalize[] **MUST**
102 * also be updated to add new internalization functions.
105 #define NACL_DESC_TYPE_MAX (NACL_DESC_NULL + 1)
106 #define NACL_DESC_TYPE_END_TAG (0xff)
108 struct NaClInternalRealHeader {
109 uint32_t xfer_protocol_version;
110 uint32_t descriptor_data_bytes;
113 struct NaClInternalHeader {
114 struct NaClInternalRealHeader h;
116 * We add 0x10 here because pad must have at least one element.
117 * This unfortunately also means that if NaClInternalRealHeader is
118 * already a multiple of 16 in size, we will add in an unnecessary
119 * 16-byte pad. The preprocessor does not have access to sizeof
120 * information, so we cannot just get rid of the pad.
122 char pad[((sizeof(struct NaClInternalRealHeader) + 0x10) & ~0xf)
123 - sizeof(struct NaClInternalRealHeader)];
124 /* total size is a multiple of 16 bytes */
127 #define NACL_HANDLE_TRANSFER_PROTOCOL 0xd3c0de01
131 * Array of function pointers, indexed by NaClDescTypeTag, any one of
132 * which will extract an externalized representation of the NaClDesc
133 * subclass object from the message, as referenced via
134 * NaClDescXferState, and when successful return the internalized
135 * representation -- a newl created NaClDesc subclass object -- to the
136 * caller via an out parameter. Returns 0 on success, negative errno
139 * NB: we should have atomic failures. The caller is expected to
140 * allocate an array of NaClDesc pointers, and insert into the open
141 * file table of the receiving NaClApp (via the NaClDescEffector
142 * interface) only when all internalizations succeed. Since even the
143 * insertion can fail, the caller must keep track of the descriptor
144 * numbers in case it has to back out and report that the message is
147 * Also, when the NaClDesc object is constructed, the NaClHandle
148 * consumed (from the NaClDescXferState) MUST BE replaced with
149 * NACL_INVALID_HANDLE.
152 (*NaClDescInternalize[NACL_DESC_TYPE_MAX])(struct NaClDesc **,
153 struct NaClDescXferState *,
154 struct NaClDescQuotaInterface *);
156 extern char const *NaClDescTypeString(enum NaClDescTypeTag type_tag);
159 * The virtual function table for NaClDesc and its subclasses.
161 * This interface will change when non-blocking I/O and epoll is
165 struct NaClDescVtbl {
166 struct NaClRefCountVtbl vbase;
169 * Essentially mmap. Note that untrusted code should always use
170 * NACL_ABI_MAP_FIXED, sice NaClDesc object have no idea where the
171 * untrusted NaCl module's address space is located. When non-fixed
172 * mapping is used (by trusted code), the Map virtual function uses
173 * an address space hole algorithm that may be subject to race
174 * between two threads, and may thus fail. In all cases, if
175 * successful, the memory mapping may be unmapped at
176 * NACL_MAP_PAGESIZE granularities. (Trusted code should use
177 * UnmapUnsafe, since refilling the unmapped address space with
178 * inaccessible memory is probably not desirable.)
180 uintptr_t (*Map)(struct NaClDesc *vself,
181 struct NaClDescEffector *effp,
186 nacl_off64_t offset) NACL_WUR;
190 * UnmapUnsafe really unmaps and leaves a hole in the address space.
191 * It is intended for use by Map (through the effector interface) to
192 * clear out memory according to the memory object that is backing
193 * the memory, prior to putting new memory in place.
195 int (*UnmapUnsafe)(struct NaClDesc *vself,
197 size_t len) NACL_WUR;
200 ssize_t (*Read)(struct NaClDesc *vself,
202 size_t len) NACL_WUR;
204 ssize_t (*Write)(struct NaClDesc *vself,
206 size_t len) NACL_WUR;
208 nacl_off64_t (*Seek)(struct NaClDesc *vself,
210 int whence) NACL_WUR;
212 ssize_t (*PRead)(struct NaClDesc *vself,
215 nacl_off64_t offset) NACL_WUR;
217 ssize_t (*PWrite)(struct NaClDesc *vself,
220 nacl_off64_t offset) NACL_WUR;
223 * TODO(bsy): Need to figure out which requests we support, if any.
224 * Also, request determines arg size and whether it is an input or
227 int (*Ioctl)(struct NaClDesc *vself,
231 int (*Fstat)(struct NaClDesc *vself,
232 struct nacl_abi_stat *statbuf);
235 * Directory access support. Directories require support for getdents.
237 ssize_t (*Getdents)(struct NaClDesc *vself,
239 size_t count) NACL_WUR;
242 * Externalization queries this for how many data bytes and how many
243 * handles are needed to transfer the "this" or "self" descriptor
244 * via IMC. If the descriptor is not transferrable, this should
245 * return -NACL_ABI_EINVAL. Success is indicated by 0, and other
246 * kinds of failure should be the usual negative errno. Should
247 * never have to put the calling thread to sleep or otherwise
248 * manipulate thread or process state.
250 * The nbytes returned do not include any kind of type tag. The
251 * type tag overhead is computed by the MsgSend code, since tagging
252 * format need not be known by the per-descriptor externalization
255 int (*ExternalizeSize)(struct NaClDesc *vself,
257 size_t *nhandles) NACL_WUR;
260 * Externalize the "this" or "self" descriptor: this will take an
261 * IMC datagram object to which the Nrd will be appended, either as
262 * special control data or as a descriptor/handle to be passed to
263 * the recipient. Should never have to put the calling thread to
264 * sleep or otherwise manipulate thread or process state.
266 int (*Externalize)(struct NaClDesc *vself,
267 struct NaClDescXferState *xfer) NACL_WUR;
270 * Lock and similar syscalls cannot just indefintely block,
271 * since address space move will require that all other threads are
272 * stopped and in a known
274 int (*Lock)(struct NaClDesc *vself) NACL_WUR;
276 int (*TryLock)(struct NaClDesc *vself) NACL_WUR;
278 int (*Unlock)(struct NaClDesc *vself) NACL_WUR;
280 int (*Wait)(struct NaClDesc *vself,
281 struct NaClDesc *mutex) NACL_WUR;
283 int (*TimedWaitAbs)(struct NaClDesc *vself,
284 struct NaClDesc *mutex,
285 struct nacl_abi_timespec const *ts) NACL_WUR;
287 int (*Signal)(struct NaClDesc *vself) NACL_WUR;
289 int (*Broadcast)(struct NaClDesc *vself) NACL_WUR;
291 ssize_t (*SendMsg)(struct NaClDesc *vself,
292 const struct NaClImcTypedMsgHdr *nitmhp,
295 ssize_t (*RecvMsg)(struct NaClDesc *vself,
296 struct NaClImcTypedMsgHdr *nitmhp,
298 struct NaClDescQuotaInterface *quota_interface) NACL_WUR;
300 ssize_t (*LowLevelSendMsg)(struct NaClDesc *vself,
301 struct NaClMessageHeader const *dgram,
304 ssize_t (*LowLevelRecvMsg)(struct NaClDesc *vself,
305 struct NaClMessageHeader *dgram,
309 * ConnectAddr() and AcceptConn():
310 * On success, returns 0 and a descriptor via *result.
311 * On error, returns a negative errno value.
313 int (*ConnectAddr)(struct NaClDesc *vself,
314 struct NaClDesc **result) NACL_WUR;
316 int (*AcceptConn)(struct NaClDesc *vself,
317 struct NaClDesc **result) NACL_WUR;
319 int (*Post)(struct NaClDesc *vself) NACL_WUR;
321 int (*SemWait)(struct NaClDesc *vself) NACL_WUR;
323 int (*GetValue)(struct NaClDesc *vself) NACL_WUR;
326 * Descriptor attributes setters and getters. These are virtual
327 * functions because the NaClDescQuota subclass wraps other NaClDesc
328 * subclasses, and the quota descriptors should not have attributes
329 * separate from that of the wrapped descriptor -- the
330 * setters/getters of the NaClDescQuota just use the corresponding
331 * methods of the wrapped descriptor.
335 * Save a copy of the |metadata_size| bytes located at |metadata|
336 * with the descriptor |self|. The |metadata_type| argument should
337 * be a non-negative integer and should be unique for each use of
338 * the metadata interface. Only one set of metadata may be saved
339 * with a descriptor, and it is an error to try to set metadata on a
340 * descriptor which already has metadata.
342 * Syscall-style function: returns 0 for success and negated errno
343 * (-NACL_ABI_ENOMEM if memory allocation for making a copy of the
344 * metadata fails, -NACL_ABI_EPERM if metadata already set,
345 * -NACL_ABI_EINVAL of metadata_type is negative).
347 int (*SetMetadata)(struct NaClDesc *self,
348 int32_t metadata_type,
349 uint32_t metadata_num_bytes,
350 uint8_t const *metadata_bytes) NACL_WUR;
353 * GetMetadata writes at most |*metadata_buffer_num_bytes_in_out|
354 * bytes of the metadata associated with the descriptor using
355 * SetMetaData to the buffer located at |metadata_buffer|. It
356 * returns the metadata_type associated with the descriptor. On
357 * return, the value at |*metadata_buffer_num_bytes_in_out| contains
358 * the total number of bytes that would be written if there were no
359 * size limit, i.e., the actual number of bytes written if the
360 * buffer was large enough, or the number of bytes that would have
361 * been written if the buffer were not. Thus, on return, if the
362 * value is less than or equal to the original value at
363 * |*metadata_buffer_num_bytes_in_out|, the contents of
364 * |metadata_buffer| contains all of the metadata.
366 * To query the size of the metadata without doing any copying, call
367 * GetMetadata with |*metadata_buffer_num_bytes_in_out| equal to
368 * zero, in which case |metadata_buffer| can be NULL.
370 * Callers should always check the return value of GetMetadata to
371 * ensure that the metadata_type is the expected value. If the type
372 * is wrong, do not process the metadata -- treat the descriptor as
373 * if it has no metadata. To do otherwise would expose us to type
376 * Returns NACL_DESC_METADATA_NONE_TYPE if no metadata is associated
377 * with the descriptor.
379 int32_t (*GetMetadata)(struct NaClDesc *self,
380 uint32_t *metadata_buffer_num_bytes_in_out,
381 uint8_t *metadata_buffer) NACL_WUR;
384 void (*SetFlags)(struct NaClDesc *self,
387 uint32_t (*GetFlags)(struct NaClDesc *self);
390 * Inappropriate methods for the subclass will just return
395 * typeTag is one of the enumeration values from NaClDescTypeTag.
397 * This is not a class variable, since one must access it through an
398 * instance. Having a value in the vtable is not allowed in C++;
399 * instead, we would implement this as a const virtual function that
400 * returns the type tag, or RTTI which would typically be done via
401 * examining the vtable pointer. This is potentially cheaper, since
402 * one could choose bit patterns for the type tags that make
403 * subclass relationships easier to compute (we don't do this, since
404 * we only ever need exact type checks).
406 * We put this at the end of the vtable so that when we add new
407 * virtual functions above it, we are guaranteed to get a type
408 * mismatch if any subclass implemention did not have its vtable
409 * properly extended -- even when -Wmissing-field-initializers was
412 enum NaClDescTypeTag typeTag;
416 struct NaClRefCount base NACL_IS_REFCOUNT_SUBCLASS;
419 /* "public" flags -- settable by users of NaClDesc interface */
422 * It is okay to try to use this descriptor with PROT_EXEC in mmap.
423 * This is just a hint to the service runtime to try direct mmap --
424 * the validator cache can still disallow the operation.
426 #define NACL_DESC_FLAGS_MMAP_EXEC_OK 0x1000
428 /* private flags -- used internally by NaClDesc */
429 #define NACL_DESC_FLAGS_PUBLIC_MASK 0xffff
431 #define NACL_DESC_FLAGS_HAS_METADATA 0x10000
433 * We could have used two uint16_t variables too, but that just
434 * makes the serialization (externalization) and deserialization
435 * (internalization) more complex; here, only the SetFlags and
436 * GetFlags need to be messy.
438 * We do not encode the presence of metadata using metadata type, so
439 * we do not have to transfer the 4 type bytes when metadata is
440 * absent. Since the interface only allows setting the metadata
441 * once, we don't worry about
443 int32_t metadata_type;
444 uint32_t metadata_num_bytes;
449 * Placement new style ctor; creates w/ ref_count of 1.
451 * The subclasses' ctor must call this base class ctor during their
454 int NaClDescCtor(struct NaClDesc *ndp) NACL_WUR;
456 extern struct NaClDescVtbl const kNaClDescVtbl;
458 struct NaClDesc *NaClDescRef(struct NaClDesc *ndp);
460 /* when ref_count reaches zero, will call dtor and free */
461 void NaClDescUnref(struct NaClDesc *ndp);
464 * NaClDescSafeUnref is just like NaCDescUnref, except that ndp may be
465 * NULL (in which case this is a noop).
467 * Used in failure cleanup of initialization code, esp in Ctors that
470 void NaClDescSafeUnref(struct NaClDesc *ndp);
473 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES.
475 int NaClDescSetMetadata(struct NaClDesc *self,
476 int32_t metadata_type,
477 uint32_t metadata_num_bytes,
478 uint8_t const *metadata_bytes) NACL_WUR;
481 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES.
483 int32_t NaClDescGetMetadata(struct NaClDesc *self,
484 uint32_t *metadata_buffer_num_bytes_in_out,
485 uint8_t *metadata_buffer) NACL_WUR;
488 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES.
490 void NaClDescSetFlags(struct NaClDesc *self,
494 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES.
496 uint32_t NaClDescGetFlags(struct NaClDesc *self);
500 * Base class externalize functions; all subclass externalize
501 * functions should invoke these, up the class hierarchy, and add to
502 * the sizes or the NaClDescXferState.
504 int NaClDescExternalizeSize(struct NaClDesc *self,
508 int NaClDescExternalize(struct NaClDesc *self,
509 struct NaClDescXferState *xfer);
512 * The top level internalize interface are factories: they allocate
513 * space, then run the internalize-in-place ctor code. Ideally, these
514 * would be two separate functions -- the memory allocation could, in
515 * most cases, be simplified to be simply an attribute containing the
516 * desired memory size and a generic allocator used, though of course
517 * we would like to permit subclasses that contains variable size
518 * arrays (at end of struct), etc. For base (super) classes, the
519 * memory allocation is not necessary, since the subclass internalize
520 * function will have handled it.
522 int NaClDescInternalizeCtor(struct NaClDesc *vself,
523 struct NaClDescXferState *xfer);
527 * subclasses are in their own header files.
531 /* utility routines */
533 /* Unmap memory, leaving an unallocated hole in address space. */
534 void NaClDescUnmapUnsafe(struct NaClDesc *desc, void *addr, size_t length);
536 int32_t NaClAbiStatHostDescStatXlateCtor(struct nacl_abi_stat *dst,
537 nacl_host_stat_t const *src);
540 * The following two functions are not part of the exported public
543 * Read/write to a NaClHandle, much like how read/write syscalls work.
545 ssize_t NaClDescReadFromHandle(NaClHandle handle,
549 ssize_t NaClDescWriteToHandle(NaClHandle handle,
554 * Default functions for the vtable for when the functionality is
555 * inappropriate for the descriptor type -- they just return
558 void NaClDescDtorNotImplemented(struct NaClRefCount *vself);
560 uintptr_t NaClDescMapNotImplemented(struct NaClDesc *vself,
561 struct NaClDescEffector *effp,
566 nacl_off64_t offset);
569 int NaClDescUnmapUnsafeNotImplemented(struct NaClDesc *vself,
572 /* This is an initializer for use when defining NaClDescVtbl structs. */
573 # define NACL_DESC_UNMAP_NOT_IMPLEMENTED \
574 NaClDescUnmapUnsafeNotImplemented,
576 # define NACL_DESC_UNMAP_NOT_IMPLEMENTED /* empty */
579 ssize_t NaClDescReadNotImplemented(struct NaClDesc *vself,
583 ssize_t NaClDescWriteNotImplemented(struct NaClDesc *vself,
587 nacl_off64_t NaClDescSeekNotImplemented(struct NaClDesc *vself,
591 ssize_t NaClDescPReadNotImplemented(struct NaClDesc *vself,
594 nacl_off64_t offset);
596 ssize_t NaClDescPWriteNotImplemented(struct NaClDesc *vself,
599 nacl_off64_t offset);
601 int NaClDescIoctlNotImplemented(struct NaClDesc *vself,
605 int NaClDescFstatNotImplemented(struct NaClDesc *vself,
606 struct nacl_abi_stat *statbuf);
608 ssize_t NaClDescGetdentsNotImplemented(struct NaClDesc *vself,
612 int NaClDescExternalizeSizeNotImplemented(struct NaClDesc *vself,
616 int NaClDescExternalizeNotImplemented(struct NaClDesc *vself,
617 struct NaClDescXferState *xfer);
619 int NaClDescLockNotImplemented(struct NaClDesc *vself);
621 int NaClDescTryLockNotImplemented(struct NaClDesc *vself);
623 int NaClDescUnlockNotImplemented(struct NaClDesc *vself);
625 int NaClDescWaitNotImplemented(struct NaClDesc *vself,
626 struct NaClDesc *mutex);
628 int NaClDescTimedWaitAbsNotImplemented(struct NaClDesc *vself,
629 struct NaClDesc *mutex,
630 struct nacl_abi_timespec const *ts);
632 int NaClDescSignalNotImplemented(struct NaClDesc *vself);
634 int NaClDescBroadcastNotImplemented(struct NaClDesc *vself);
636 ssize_t NaClDescSendMsgNotImplemented(
637 struct NaClDesc *vself,
638 const struct NaClImcTypedMsgHdr *nitmhp,
641 ssize_t NaClDescRecvMsgNotImplemented(
642 struct NaClDesc *vself,
643 struct NaClImcTypedMsgHdr *nitmhp,
645 struct NaClDescQuotaInterface *quota_interface);
647 ssize_t NaClDescLowLevelSendMsgNotImplemented(
648 struct NaClDesc *vself,
649 struct NaClMessageHeader const *dgram,
652 ssize_t NaClDescLowLevelRecvMsgNotImplemented(
653 struct NaClDesc *vself,
654 struct NaClMessageHeader *dgram,
657 int NaClDescConnectAddrNotImplemented(struct NaClDesc *vself,
658 struct NaClDesc **out_desc);
660 int NaClDescAcceptConnNotImplemented(struct NaClDesc *vself,
661 struct NaClDesc **out_desc);
663 int NaClDescPostNotImplemented(struct NaClDesc *vself);
665 int NaClDescSemWaitNotImplemented(struct NaClDesc *vself);
667 int NaClDescGetValueNotImplemented(struct NaClDesc *vself);
669 int NaClDescInternalizeNotImplemented(
670 struct NaClDesc **out_desc,
671 struct NaClDescXferState *xfer,
672 struct NaClDescQuotaInterface *quota_interface);
675 int NaClSafeCloseNaClHandle(NaClHandle h);
677 int NaClDescIsSafeForMmap(struct NaClDesc *self);
679 void NaClDescMarkSafeForMmap(struct NaClDesc *self);
681 void NaClDescMarkUnsafeForMmap(struct NaClDesc *self);
683 struct NaClValidationCache;
685 int NaClDescValidationCacheResolve(
686 struct NaClDesc **desc_in_out,
687 struct NaClValidationCache *validation_cache);
692 #endif // NATIVE_CLIENT_SRC_TRUSTED_DESC_NACL_DESC_BASE_H_