2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl Service Runtime. I/O Descriptor / Handle abstraction.
36 #ifndef NATIVE_CLIENT_SERVICE_RUNTIME_NACL_DESC_BASE_H_
37 #define NATIVE_CLIENT_SERVICE_RUNTIME_NACL_DESC_BASE_H_
40 /* defines PATH_MAX */
41 # include "native_client/include/nacl_base.h"
42 # include "native_client/include/portability.h"
44 #include "native_client/service_runtime/nacl_desc_effector.h"
46 #include "native_client/service_runtime/nacl_host_desc.h"
47 #include "native_client/service_runtime/nacl_host_dir.h"
48 #include "native_client/service_runtime/nacl_interruptible_condvar.h"
49 #include "native_client/service_runtime/nacl_interruptible_mutex.h"
50 #include "native_client/service_runtime/nacl_semaphore.h"
51 #include "native_client/service_runtime/nacl_sync.h"
53 #include "native_client/intermodule_comm/nacl_imc_c.h"
55 #include "native_client/service_runtime/include/sys/errno.h"
56 #include "native_client/service_runtime/include/sys/time.h"
64 * Externalization / internalization state, used by
65 * Externalize/Internalize functions. Externalize convert the
66 * descriptor represented by the self (this) object to an entry in the
67 * handles table in a NaClMessageHeader, and the Internalize function
68 * is a factory that takes a dgram and NaClDescXferState and
69 * constructs a vector of NaClDesc objects.
71 * This is essentially a pair of input/output iterators. The *_end
72 * values are not needed during externalization, since the SendMsg
73 * code will have queried ExternalizeSize to ensure that there is
74 * enough space. During internalization, however, we try to be more
75 * paranoid and check that we do not overrun our buffers.
77 * NB: we must assume that the NaClHandle values passed are the right
78 * type; if not, it is possible to violate invariant properties
79 * required by the various subclasses of NaClDesc.
81 struct NaClDescXferState
{
83 * In/out value, used for both serialization and deserialization.
84 * The Externalize method read/write type tags that are part of the
85 * message header as well as data-based capabilities in a
86 * self-describing format.
89 char *byte_buffer_end
;
92 * In/out value. Next handle to work on.
94 NaClHandle
*next_handle
;
95 NaClHandle
*handle_buffer_end
;
98 enum NaClDescTypeTag
{
102 NACL_DESC_BOUND_SOCKET
,
103 NACL_DESC_CONNECTED_SOCKET
,
109 * Add new NaCDesc subclasses here.
111 * NB: when we add new tag types, NaClDescInternalize[] **MUST**
112 * also be updated to add new internalization functions.
115 #define NACL_DESC_TYPE_MAX (NACL_DESC_SEMAPHORE+1)
116 #define NACL_DESC_TYPE_END_TAG (0xff)
118 struct NaClInternalRealHeader
{
119 uint32_t xfer_protocol_version
;
120 uint32_t descriptor_data_bytes
;
123 struct NaClInternalHeader
{
124 struct NaClInternalRealHeader h
;
126 * We add 0x10 here because pad must have at least one element.
127 * This unfortunately also means that if NaClInternalRealHeader is
128 * already a multiple of 16 in size, we will add in an unnecessary
129 * 16-byte pad. The preprocessor does not have access to sizeof
130 * information, so we cannot just get rid of the pad.
132 char pad
[((sizeof(struct NaClInternalRealHeader
) + 0x10) & ~0xf)
133 - sizeof(struct NaClInternalRealHeader
)];
134 /* total size is a multiple of 16 bytes */
137 #define NACL_HANDLE_TRANSFER_PROTOCOL 0xd3c0de00
141 * Array of function pointers, indexed by NaClDescTypeTag, any one of
142 * which will extract an externalized representation of the NaClDesc
143 * subclass object from the message, as referenced via
144 * NaClDescXferState, and when successful return the internalized
145 * representation -- a newl created NaClDesc subclass object -- to the
146 * caller via an out parameter. Returns 0 on success, negative errno
149 * NB: we should have atomic failures. The caller is expected to
150 * allocate an array of NaClDesc pointers, and insert into the open
151 * file table of the receiving NaClApp (via the NaClDescEffector
152 * interface) only when all internalizations succeed. Since even the
153 * insertion can fail, the caller must keep track of the descriptor
154 * numbers in case it has to back out and report that the message is
157 * Also, when the NaClDesc object is constructed, the NaClHandle
158 * consumed (from the NaClDescXferState) MUST BE replaced with
159 * NACL_INVALID_HANDLE.
161 extern int (*NaClDescInternalize
[NACL_DESC_TYPE_MAX
])(
163 struct NaClDescXferState
*);
166 * The virtual function table for NaClDesc and its subclasses.
168 * This interface will change when non-blocking I/O and epoll is
172 struct NaClDescVtbl
{
173 void (*Dtor
)(struct NaClDesc
*vself
);
174 int (*Map
)(struct NaClDesc
*vself
,
175 struct NaClDescEffector
*effp
,
182 * UnmapUnsafe really unmaps and leaves a hole in the address space.
183 * It is intended for use by Map (through the effector interface) to
184 * clear out memory according to the memory object that is backing
185 * the memory, prior to putting new memory in place. Should not
186 * invoke effp->vtbl->UpdateAddrMap.
188 int (*UnmapUnsafe
)(struct NaClDesc
*vself
,
189 struct NaClDescEffector
*effp
,
193 * Unmap is the version that removes the mapping but continues to
194 * hold the address space in reserve, preventing it from being used
195 * accidentally by other threads. (Address-space squatting.)
197 * Should invoke effp->vtbl->UpdateAddrMap.
199 int (*Unmap
)(struct NaClDesc
*vself
,
200 struct NaClDescEffector
*effp
,
203 ssize_t (*Read
)(struct NaClDesc
*vself
,
204 struct NaClDescEffector
*effp
,
207 ssize_t (*Write
)(struct NaClDesc
*vself
,
208 struct NaClDescEffector
*effp
,
211 int (*Seek
)(struct NaClDesc
*vself
,
212 struct NaClDescEffector
*effp
,
216 * TODO: Need to figure out which requests we support. Also,
217 * request determines arg size and whether it is an input or output arg!
219 int (*Ioctl
)(struct NaClDesc
*vself
,
220 struct NaClDescEffector
*effp
,
223 int (*Fstat
)(struct NaClDesc
*vself
,
224 struct NaClDescEffector
*effp
,
225 struct nacl_abi_stat
*statbuf
);
226 int (*Close
)(struct NaClDesc
*vself
,
227 struct NaClDescEffector
*effp
);
230 * Directory access support. Directories require support for getdents.
232 ssize_t (*Getdents
)(struct NaClDesc
*vself
,
233 struct NaClDescEffector
*effp
,
238 * typeTag is one of the enumeration values from NaClDescTypeTag.
240 * This is not a class variable, since one must access it through an
241 * instance. Having a value in the vtable is not allowed in C++;
242 * instead, we would implement this as a virtual function that
243 * returns the type tag, or RTTI which would typically be done via
244 * examining the vtable pointer.
246 enum NaClDescTypeTag typeTag
;
249 * Externalization queries this for how many data bytes and how many
250 * handles are needed to transfer the "this" or "self" descriptor
251 * via IMC. If the descriptor is not transferrable, this should
252 * return -NACL_ABI_EINVAL. Success is indicated by 0, and other
253 * kinds of failure should be the usual negative errno. Should
254 * never have to put the calling thread to sleep or otherwise
255 * manipulate thread or process state.
257 * The nbytes returned do not include any kind of type tag. The
258 * type tag overhead is computed by the MsgSend code, since tagging
259 * format need not be known by the per-descriptor externalization
262 int (*ExternalizeSize
)(struct NaClDesc
*vself
,
266 * Externalize the "this" or "self" descriptor: this will take an
267 * IMC datagram object to which the Nrd will be appended, either as
268 * special control data or as a descriptor/handle to be passed to
269 * the recipient. Should never have to put the calling thread to
270 * sleep or otherwise manipulate thread or process state.
272 int (*Externalize
)(struct NaClDesc
*vself
,
273 struct NaClDescXferState
*xfer
);
275 * Lock and similar syscalls cannot just indefintely block,
276 * since address space move will require that all other threads are
277 * stopped and in a known
279 int (*Lock
)(struct NaClDesc
*vself
,
280 struct NaClDescEffector
*effp
);
281 int (*TryLock
)(struct NaClDesc
*vself
,
282 struct NaClDescEffector
*effp
);
283 int (*Unlock
)(struct NaClDesc
*vself
,
284 struct NaClDescEffector
*effp
);
285 int (*Wait
)(struct NaClDesc
*vself
,
286 struct NaClDescEffector
*effp
,
287 struct NaClDesc
*mutex
);
288 int (*TimedWaitAbs
)(struct NaClDesc
*vself
,
289 struct NaClDescEffector
*effp
,
290 struct NaClDesc
*mutex
,
291 struct nacl_abi_timespec
*ts
);
292 int (*Signal
)(struct NaClDesc
*vself
,
293 struct NaClDescEffector
*effp
);
294 int (*Broadcast
)(struct NaClDesc
*vself
,
295 struct NaClDescEffector
*effp
);
297 int (*SendMsg
)(struct NaClDesc
*vself
,
298 struct NaClDescEffector
*effp
,
299 struct NaClMessageHeader
*dgram
,
301 int (*RecvMsg
)(struct NaClDesc
*vself
,
302 struct NaClDescEffector
*effp
,
303 struct NaClMessageHeader
*dgram
,
305 int (*ConnectAddr
)(struct NaClDesc
*vself
,
306 struct NaClDescEffector
*effp
);
307 int (*AcceptConn
)(struct NaClDesc
*vself
,
308 struct NaClDescEffector
*effp
);
309 int (*Post
)(struct NaClDesc
*vself
,
310 struct NaClDescEffector
*effp
);
311 int (*SemWait
)(struct NaClDesc
*vself
,
312 struct NaClDescEffector
*effp
);
313 int (*GetValue
)(struct NaClDesc
*vself
,
314 struct NaClDescEffector
*effp
);
316 * Inappropriate methods for the subclass will just return
322 struct NaClDescVtbl
const *vtbl
;
328 * Placement new style ctor; creates w/ ref_count of 1.
330 * The subclasses' ctor must call this base class ctor during their
333 int NaClDescCtor(struct NaClDesc
*ndp
);
335 /* Typically it is incorrect to call the dtor directly; see NaClDescUnref */
336 void NaClDescDtor(struct NaClDesc
*ndp
);
338 struct NaClDesc
*NaClDescRef(struct NaClDesc
*ndp
);
340 /* when ref_count reaches zero, will call dtor and free */
341 void NaClDescUnref(struct NaClDesc
*ndp
);
348 * Directory descriptors
350 extern struct NaClDescVtbl
const kNaClDescDirDescVtbl
;
352 struct NaClDescDirDesc
{
353 struct NaClDesc base
;
354 struct NaClHostDir
*hd
;
357 extern int NaClDescDirInternalize(struct NaClDesc
**baseptr
,
358 struct NaClDescXferState
*xfer
);
363 extern struct NaClDescVtbl
const kNaClDescIoDescVtbl
;
365 struct NaClDescIoDesc
{
366 struct NaClDesc base
;
368 * No locks are needed for accessing class members; NaClHostDesc
369 * should ensure thread safety, and uses are read-only.
371 * If we later added state that needs locking, beware lock order.
373 struct NaClHostDesc
*hd
;
376 extern int NaClDescIoInternalize(struct NaClDesc
**baseptr
,
377 struct NaClDescXferState
*xfer
);
379 extern struct NaClDescVtbl
const kNaClDescConnCapVtbl
;
382 * IMC socket addresses.
384 struct NaClDescConnCap
{
385 struct NaClDesc base
;
386 struct NaClSocketAddress cap
;
389 extern int NaClDescConnCapInternalize(struct NaClDesc
**baseptr
,
390 struct NaClDescXferState
*xfer
);
392 extern struct NaClDescVtbl
const kNaClDescImcBoundDescVtbl
;
397 struct NaClDescImcBoundDesc
{
398 struct NaClDesc base
;
402 extern int NaClDescImcBoundDescInternalize(struct NaClDesc
**baseptr
,
403 struct NaClDescXferState
*xfer
);
405 extern struct NaClDescVtbl
const kNaClDescImcDescVtbl
;
408 * IMC connected sockets.
410 struct NaClDescImcDesc
{
411 struct NaClDesc base
;
415 extern int NaClDescImcDescInternalize(struct NaClDesc
**baseptr
,
416 struct NaClDescXferState
*xfer
);
418 extern struct NaClDescVtbl
const kNaClDescImcShmVtbl
;
420 struct NaClDescImcShm
{
421 struct NaClDesc base
;
423 off_t size
; /* note off_t so struct stat compatible */
426 extern int NaClDescImcShmInternalize(struct NaClDesc
**baseptr
,
427 struct NaClDescXferState
*xfer
);
429 extern struct NaClDescVtbl
const kNaClDescMutexVtbl
;
431 struct NaClDescMutex
{
432 struct NaClDesc base
;
433 struct NaClIntrMutex mu
;
436 extern int NaClDescMutexInternalize(struct NaClDesc
**baseptr
,
437 struct NaClDescXferState
*xfer
);
439 extern struct NaClDescVtbl
const kNaClDescCondVarVtbl
;
441 struct NaClDescCondVar
{
442 struct NaClDesc base
;
443 struct NaClIntrCondVar cv
;
446 extern int NaClDescCondVarInternalize(struct NaClDesc
**baseptr
,
447 struct NaClDescXferState
*xfer
);
449 extern struct NaClDescVtbl
const kNaClDescSemaphoreVtbl
;
451 struct NaClDescSemaphore
{
452 struct NaClDesc base
;
453 struct NaClSemaphore sem
;
456 extern int NaClDescSemaphoreInternalize(struct NaClDesc
**baseptr
,
457 struct NaClDescXferState
*xfer
);
459 /* utility routines */
461 struct NaClDescIoDesc
*NaClDescIoDescMake(struct NaClHostDesc
*nhdp
);
463 /* in PLATFORM/nacl_desc.c */
464 void NaClDeallocAddrRange(uintptr_t addr
,
468 /* default functions for the vtable - return -NACL_ABI_EINVAL */
469 void NaClDescDtorNotImplemented(struct NaClDesc
*vself
);
471 int NaClDescMapNotImplemented(struct NaClDesc
*vself
,
472 struct NaClDescEffector
*effp
,
478 int NaClDescUnmapUnsafeNotImplemented(struct NaClDesc
*vself
,
479 struct NaClDescEffector
*effp
,
483 int NaClDescUnmapNotImplemented(struct NaClDesc
*vself
,
484 struct NaClDescEffector
*effp
,
487 ssize_t
NaClDescReadNotImplemented(struct NaClDesc
*vself
,
488 struct NaClDescEffector
*effp
,
491 ssize_t
NaClDescWriteNotImplemented(struct NaClDesc
*vself
,
492 struct NaClDescEffector
*effp
,
495 int NaClDescSeekNotImplemented(struct NaClDesc
*vself
,
496 struct NaClDescEffector
*effp
,
499 int NaClDescIoctlNotImplemented(struct NaClDesc
*vself
,
500 struct NaClDescEffector
*natp
,
503 int NaClDescFstatNotImplemented(struct NaClDesc
*vself
,
504 struct NaClDescEffector
*effp
,
505 struct nacl_abi_stat
*statbuf
);
506 int NaClDescCloseNotImplemented(struct NaClDesc
*vself
,
507 struct NaClDescEffector
*effp
);
509 ssize_t
NaClDescGetdentsNotImplemented(struct NaClDesc
*vself
,
510 struct NaClDescEffector
*effp
,
514 int NaClDescExternalizeSizeNotImplemented(struct NaClDesc
*vself
,
518 int NaClDescExternalizeNotImplemented(struct NaClDesc
*vself
,
519 struct NaClDescXferState
*xfer
);
521 int NaClDescLockNotImplemented(struct NaClDesc
*vself
,
522 struct NaClDescEffector
*effp
);
523 int NaClDescTryLockNotImplemented(struct NaClDesc
*vself
,
524 struct NaClDescEffector
*effp
);
525 int NaClDescUnlockNotImplemented(struct NaClDesc
*vself
,
526 struct NaClDescEffector
*effp
);
527 int NaClDescWaitNotImplemented(struct NaClDesc
*vself
,
528 struct NaClDescEffector
*effp
,
529 struct NaClDesc
*mutex
);
530 int NaClDescTimedWaitAbsNotImplemented(struct NaClDesc
*vself
,
531 struct NaClDescEffector
*effp
,
532 struct NaClDesc
*mutex
,
533 struct nacl_abi_timespec
*ts
);
534 int NaClDescSignalNotImplemented(struct NaClDesc
*vself
,
535 struct NaClDescEffector
*effp
);
536 int NaClDescBroadcastNotImplemented(struct NaClDesc
*vself
,
537 struct NaClDescEffector
*effp
);
539 int NaClDescSendMsgNotImplemented(struct NaClDesc
*vself
,
540 struct NaClDescEffector
*effp
,
541 struct NaClMessageHeader
*dgram
,
543 int NaClDescRecvMsgNotImplemented(struct NaClDesc
*vself
,
544 struct NaClDescEffector
*effp
,
545 struct NaClMessageHeader
*dgram
,
547 int NaClDescConnectAddrNotImplemented(struct NaClDesc
*vself
,
548 struct NaClDescEffector
*effp
);
549 int NaClDescAcceptConnNotImplemented(struct NaClDesc
*vself
,
550 struct NaClDescEffector
*effp
);
551 int NaClDescPostNotImplemented(struct NaClDesc
*vself
,
552 struct NaClDescEffector
*effp
);
553 int NaClDescSemWaitNotImplemented(struct NaClDesc
*vself
,
554 struct NaClDescEffector
*effp
);
555 int NaClDescGetValueNotImplemented(struct NaClDesc
*vself
,
556 struct NaClDescEffector
*effp
);
560 #endif /* NATIVE_CLIENT_SERVICE_RUNTIME_NACL_DESC_BASE_H_ */