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. 9 */ 10 11 #ifndef NATIVE_CLIENT_SRC_TRUSTED_DESC_NACL_DESC_BASE_H_ 12 #define NATIVE_CLIENT_SRC_TRUSTED_DESC_NACL_DESC_BASE_H_ 13 14 #include <limits.h> 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 18 #include "native_client/src/include/build_config.h" 19 #include "native_client/src/include/nacl_base.h" 20 #include "native_client/src/include/portability.h" 21 22 #include "native_client/src/public/nacl_desc.h" 23 24 /* For NaClHandle */ 25 #include "native_client/src/shared/imc/nacl_imc_c.h" 26 27 /* for nacl_off64_t */ 28 #include "native_client/src/shared/platform/nacl_host_desc.h" 29 #include "native_client/src/shared/platform/nacl_sync.h" 30 31 #include "native_client/src/trusted/desc/desc_metadata_types.h" 32 #include "native_client/src/trusted/nacl_base/nacl_refcount.h" 33 34 EXTERN_C_BEGIN 35 36 struct NaClDesc; 37 struct nacl_abi_stat; 38 struct nacl_abi_timespec; 39 struct NaClDescEffector; 40 struct NaClImcTypedMsgHdr; 41 struct NaClMessageHeader; 42 43 /* 44 * Externalization / internalization state, used by 45 * Externalize/Internalize functions. Externalize convert the 46 * descriptor represented by the self (this) object to an entry in the 47 * handles table in a NaClMessageHeader, and the Internalize function 48 * is a factory that takes a dgram and NaClDescXferState and 49 * constructs a vector of NaClDesc objects. 50 * 51 * This is essentially a pair of input/output iterators. The *_end 52 * values are not needed during externalization, since the SendMsg 53 * code will have queried ExternalizeSize to ensure that there is 54 * enough space. During internalization, however, we try to be more 55 * paranoid and check that we do not overrun our buffers. 56 * 57 * NB: we must assume that the NaClHandle values passed are the right 58 * type; if not, it is possible to violate invariant properties 59 * required by the various subclasses of NaClDesc. 60 */ 61 struct NaClDescXferState { 62 /* 63 * In/out value, used for both serialization and deserialization. 64 * The Externalize method read/write type tags that are part of the 65 * message header as well as data-based capabilities in a 66 * self-describing format. 67 */ 68 char *next_byte; 69 char *byte_buffer_end; 70 71 /* 72 * In/out value. Next handle to work on. 73 */ 74 NaClHandle *next_handle; 75 NaClHandle *handle_buffer_end; 76 }; 77 78 enum NaClDescTypeTag { 79 NACL_DESC_INVALID, 80 NACL_DESC_DIR, 81 NACL_DESC_HOST_IO, 82 NACL_DESC_CONN_CAP, 83 NACL_DESC_CONN_CAP_FD, 84 NACL_DESC_BOUND_SOCKET, 85 NACL_DESC_CONNECTED_SOCKET, 86 NACL_DESC_SHM, 87 NACL_DESC_SHM_MACH, 88 NACL_DESC_MUTEX, 89 NACL_DESC_CONDVAR, 90 NACL_DESC_SEMAPHORE, 91 NACL_DESC_SYNC_SOCKET, 92 NACL_DESC_TRANSFERABLE_DATA_SOCKET, 93 NACL_DESC_IMC_SOCKET, 94 NACL_DESC_QUOTA, 95 NACL_DESC_CUSTOM, 96 NACL_DESC_NULL 97 /* 98 * Add new NaClDesc subclasses here. 99 * 100 * NB: when we add new tag types, NaClDescInternalize[] **MUST** 101 * also be updated to add new internalization functions. 102 */ 103 }; 104 #define NACL_DESC_TYPE_MAX (NACL_DESC_NULL + 1) 105 #define NACL_DESC_TYPE_END_TAG (0xff) 106 107 struct NaClInternalRealHeader { 108 uint32_t xfer_protocol_version; 109 uint32_t descriptor_data_bytes; 110 }; 111 112 struct NaClInternalHeader { 113 struct NaClInternalRealHeader h; 114 /* 115 * We add 0x10 here because pad must have at least one element. 116 * This unfortunately also means that if NaClInternalRealHeader is 117 * already a multiple of 16 in size, we will add in an unnecessary 118 * 16-byte pad. The preprocessor does not have access to sizeof 119 * information, so we cannot just get rid of the pad. 120 */ 121 char pad[((sizeof(struct NaClInternalRealHeader) + 0x10) & ~0xf) 122 - sizeof(struct NaClInternalRealHeader)]; 123 /* total size is a multiple of 16 bytes */ 124 }; 125 126 #define NACL_HANDLE_TRANSFER_PROTOCOL 0xd3c0de01 127 /* incr from here */ 128 129 /* 130 * Array of function pointers, indexed by NaClDescTypeTag, any one of 131 * which will extract an externalized representation of the NaClDesc 132 * subclass object from the message, as referenced via 133 * NaClDescXferState, and when successful return the internalized 134 * representation -- a newl created NaClDesc subclass object -- to the 135 * caller via an out parameter. Returns 0 on success, negative errno 136 * value on failure. 137 * 138 * NB: we should have atomic failures. The caller is expected to 139 * allocate an array of NaClDesc pointers, and insert into the open 140 * file table of the receiving NaClApp (via the NaClDescEffector 141 * interface) only when all internalizations succeed. Since even the 142 * insertion can fail, the caller must keep track of the descriptor 143 * numbers in case it has to back out and report that the message is 144 * dropped. 145 * 146 * Also, when the NaClDesc object is constructed, the NaClHandle 147 * consumed (from the NaClDescXferState) MUST BE replaced with 148 * NACL_INVALID_HANDLE. 149 */ 150 extern int 151 (*NaClDescInternalize[NACL_DESC_TYPE_MAX])(struct NaClDesc **, 152 struct NaClDescXferState *); 153 154 extern char const *NaClDescTypeString(enum NaClDescTypeTag type_tag); 155 156 /* 157 * The virtual function table for NaClDesc and its subclasses. 158 * 159 * This interface will change when non-blocking I/O and epoll is 160 * added. 161 */ 162 163 struct NaClDescVtbl { 164 struct NaClRefCountVtbl vbase; 165 166 /* 167 * Essentially mmap. Note that untrusted code should always use 168 * NACL_ABI_MAP_FIXED, sice NaClDesc object have no idea where the 169 * untrusted NaCl module's address space is located. When non-fixed 170 * mapping is used (by trusted code), the Map virtual function uses 171 * an address space hole algorithm that may be subject to race 172 * between two threads, and may thus fail. In all cases, if 173 * successful, the memory mapping may be unmapped at 174 * NACL_MAP_PAGESIZE granularities. (Trusted code should use 175 * UnmapUnsafe, since refilling the unmapped address space with 176 * inaccessible memory is probably not desirable.) 177 */ 178 uintptr_t (*Map)(struct NaClDesc *vself, 179 struct NaClDescEffector *effp, 180 void *start_addr, 181 size_t len, 182 int prot, 183 int flags, 184 nacl_off64_t offset) NACL_WUR; 185 186 ssize_t (*Read)(struct NaClDesc *vself, 187 void *buf, 188 size_t len) NACL_WUR; 189 190 ssize_t (*Write)(struct NaClDesc *vself, 191 void const *buf, 192 size_t len) NACL_WUR; 193 194 nacl_off64_t (*Seek)(struct NaClDesc *vself, 195 nacl_off64_t offset, 196 int whence) NACL_WUR; 197 198 ssize_t (*PRead)(struct NaClDesc *vself, 199 void *buf, 200 size_t len, 201 nacl_off64_t offset) NACL_WUR; 202 203 ssize_t (*PWrite)(struct NaClDesc *vself, 204 void const *buf, 205 size_t len, 206 nacl_off64_t offset) NACL_WUR; 207 208 int (*Fstat)(struct NaClDesc *vself, 209 struct nacl_abi_stat *statbuf); 210 211 int (*Fchdir)(struct NaClDesc *vself) NACL_WUR; 212 213 int (*Fchmod)(struct NaClDesc *vself, 214 int mode) NACL_WUR; 215 216 int (*Fsync)(struct NaClDesc *vself) NACL_WUR; 217 218 int (*Fdatasync)(struct NaClDesc *vself) NACL_WUR; 219 220 int (*Ftruncate)(struct NaClDesc *vself, 221 nacl_abi_off_t length) NACL_WUR; 222 223 /* 224 * Directory access support. Directories require support for getdents. 225 */ 226 ssize_t (*Getdents)(struct NaClDesc *vself, 227 void *dirp, 228 size_t count) NACL_WUR; 229 230 /* 231 * Externalization queries this for how many data bytes and how many 232 * handles are needed to transfer the "this" or "self" descriptor 233 * via IMC. If the descriptor is not transferrable, this should 234 * return -NACL_ABI_EINVAL. Success is indicated by 0, and other 235 * kinds of failure should be the usual negative errno. Should 236 * never have to put the calling thread to sleep or otherwise 237 * manipulate thread or process state. 238 * 239 * The nbytes returned do not include any kind of type tag. The 240 * type tag overhead is computed by the MsgSend code, since tagging 241 * format need not be known by the per-descriptor externalization 242 * code. 243 */ 244 int (*ExternalizeSize)(struct NaClDesc *vself, 245 size_t *nbytes, 246 size_t *nhandles) NACL_WUR; 247 248 /* 249 * Externalize the "this" or "self" descriptor: this will take an 250 * IMC datagram object to which the Nrd will be appended, either as 251 * special control data or as a descriptor/handle to be passed to 252 * the recipient. Should never have to put the calling thread to 253 * sleep or otherwise manipulate thread or process state. 254 */ 255 int (*Externalize)(struct NaClDesc *vself, 256 struct NaClDescXferState *xfer) NACL_WUR; 257 258 /* 259 * Lock and similar syscalls cannot just indefintely block, 260 * since address space move will require that all other threads are 261 * stopped and in a known 262 */ 263 int (*Lock)(struct NaClDesc *vself) NACL_WUR; 264 265 int (*TryLock)(struct NaClDesc *vself) NACL_WUR; 266 267 int (*Unlock)(struct NaClDesc *vself) NACL_WUR; 268 269 int (*Wait)(struct NaClDesc *vself, 270 struct NaClDesc *mutex) NACL_WUR; 271 272 int (*TimedWaitAbs)(struct NaClDesc *vself, 273 struct NaClDesc *mutex, 274 struct nacl_abi_timespec const *ts) NACL_WUR; 275 276 int (*Signal)(struct NaClDesc *vself) NACL_WUR; 277 278 int (*Broadcast)(struct NaClDesc *vself) NACL_WUR; 279 280 ssize_t (*SendMsg)(struct NaClDesc *vself, 281 const struct NaClImcTypedMsgHdr *nitmhp, 282 int flags) NACL_WUR; 283 284 ssize_t (*RecvMsg)(struct NaClDesc *vself, 285 struct NaClImcTypedMsgHdr *nitmhp, 286 int flags) NACL_WUR; 287 288 ssize_t (*LowLevelSendMsg)(struct NaClDesc *vself, 289 struct NaClMessageHeader const *dgram, 290 int flags) NACL_WUR; 291 292 ssize_t (*LowLevelRecvMsg)(struct NaClDesc *vself, 293 struct NaClMessageHeader *dgram, 294 int flags) NACL_WUR; 295 296 /* 297 * ConnectAddr() and AcceptConn(): 298 * On success, returns 0 and a descriptor via *result. 299 * On error, returns a negative errno value. 300 */ 301 int (*ConnectAddr)(struct NaClDesc *vself, 302 struct NaClDesc **result) NACL_WUR; 303 304 int (*AcceptConn)(struct NaClDesc *vself, 305 struct NaClDesc **result) NACL_WUR; 306 307 int (*Post)(struct NaClDesc *vself) NACL_WUR; 308 309 int (*SemWait)(struct NaClDesc *vself) NACL_WUR; 310 311 int (*GetValue)(struct NaClDesc *vself) NACL_WUR; 312 313 /* 314 * Descriptor attributes setters and getters. These are virtual 315 * functions because the NaClDescQuota subclass wraps other NaClDesc 316 * subclasses, and the quota descriptors should not have attributes 317 * separate from that of the wrapped descriptor -- the 318 * setters/getters of the NaClDescQuota just use the corresponding 319 * methods of the wrapped descriptor. 320 */ 321 322 /* 323 * Save a copy of the |metadata_size| bytes located at |metadata| 324 * with the descriptor |self|. The |metadata_type| argument should 325 * be a non-negative integer and should be unique for each use of 326 * the metadata interface. Only one set of metadata may be saved 327 * with a descriptor, and it is an error to try to set metadata on a 328 * descriptor which already has metadata. 329 * 330 * Syscall-style function: returns 0 for success and negated errno 331 * (-NACL_ABI_ENOMEM if memory allocation for making a copy of the 332 * metadata fails, -NACL_ABI_EPERM if metadata already set, 333 * -NACL_ABI_EINVAL of metadata_type is negative). 334 */ 335 int (*SetMetadata)(struct NaClDesc *self, 336 int32_t metadata_type, 337 uint32_t metadata_num_bytes, 338 uint8_t const *metadata_bytes) NACL_WUR; 339 340 /* 341 * GetMetadata writes at most |*metadata_buffer_num_bytes_in_out| 342 * bytes of the metadata associated with the descriptor using 343 * SetMetaData to the buffer located at |metadata_buffer|. It 344 * returns the metadata_type associated with the descriptor. On 345 * return, the value at |*metadata_buffer_num_bytes_in_out| contains 346 * the total number of bytes that would be written if there were no 347 * size limit, i.e., the actual number of bytes written if the 348 * buffer was large enough, or the number of bytes that would have 349 * been written if the buffer were not. Thus, on return, if the 350 * value is less than or equal to the original value at 351 * |*metadata_buffer_num_bytes_in_out|, the contents of 352 * |metadata_buffer| contains all of the metadata. 353 * 354 * To query the size of the metadata without doing any copying, call 355 * GetMetadata with |*metadata_buffer_num_bytes_in_out| equal to 356 * zero, in which case |metadata_buffer| can be NULL. 357 * 358 * Callers should always check the return value of GetMetadata to 359 * ensure that the metadata_type is the expected value. If the type 360 * is wrong, do not process the metadata -- treat the descriptor as 361 * if it has no metadata. To do otherwise would expose us to type 362 * confusion attacks. 363 * 364 * Returns NACL_DESC_METADATA_NONE_TYPE if no metadata is associated 365 * with the descriptor. 366 */ 367 int32_t (*GetMetadata)(struct NaClDesc *self, 368 uint32_t *metadata_buffer_num_bytes_in_out, 369 uint8_t *metadata_buffer) NACL_WUR; 370 371 372 void (*SetFlags)(struct NaClDesc *self, 373 uint32_t flags); 374 375 uint32_t (*GetFlags)(struct NaClDesc *self); 376 377 int32_t (*Isatty)(struct NaClDesc *self); 378 379 /* 380 * Inappropriate methods for the subclass will just return 381 * -NACL_ABI_EINVAL. 382 */ 383 384 /* 385 * typeTag is one of the enumeration values from NaClDescTypeTag. 386 * 387 * This is not a class variable, since one must access it through an 388 * instance. Having a value in the vtable is not allowed in C++; 389 * instead, we would implement this as a const virtual function that 390 * returns the type tag, or RTTI which would typically be done via 391 * examining the vtable pointer. This is potentially cheaper, since 392 * one could choose bit patterns for the type tags that make 393 * subclass relationships easier to compute (we don't do this, since 394 * we only ever need exact type checks). 395 * 396 * We put this at the end of the vtable so that when we add new 397 * virtual functions above it, we are guaranteed to get a type 398 * mismatch if any subclass implemention did not have its vtable 399 * properly extended -- even when -Wmissing-field-initializers was 400 * omitted. 401 */ 402 enum NaClDescTypeTag typeTag; 403 }; 404 405 struct NaClDesc { 406 struct NaClRefCount base NACL_IS_REFCOUNT_SUBCLASS; 407 uint32_t flags; 408 409 /* "public" flags -- settable by users of NaClDesc interface */ 410 411 /* 412 * It is okay to try to use this descriptor with PROT_EXEC in mmap. 413 * This is just a hint to the service runtime to try direct mmap -- 414 * the validator cache can still disallow the operation. 415 */ 416 #define NACL_DESC_FLAGS_MMAP_EXEC_OK 0x1000 417 418 /* private flags -- used internally by NaClDesc */ 419 #define NACL_DESC_FLAGS_PUBLIC_MASK 0xffff 420 421 #define NACL_DESC_FLAGS_HAS_METADATA 0x10000 422 /* 423 * We could have used two uint16_t variables too, but that just 424 * makes the serialization (externalization) and deserialization 425 * (internalization) more complex; here, only the SetFlags and 426 * GetFlags need to be messy. 427 * 428 * We do not encode the presence of metadata using metadata type, so 429 * we do not have to transfer the 4 type bytes when metadata is 430 * absent. Since the interface only allows setting the metadata 431 * once, we don't worry about 432 */ 433 int32_t metadata_type; 434 uint32_t metadata_num_bytes; 435 uint8_t *metadata; 436 }; 437 438 /* 439 * Placement new style ctor; creates w/ ref_count of 1. 440 * 441 * The subclasses' ctor must call this base class ctor during their 442 * contruction. 443 */ 444 int NaClDescCtor(struct NaClDesc *ndp) NACL_WUR; 445 446 extern struct NaClDescVtbl const kNaClDescVtbl; 447 448 /* 449 * NaClDescSafeUnref is just like NaCDescUnref, except that ndp may be 450 * NULL (in which case this is a noop). 451 * 452 * Used in failure cleanup of initialization code, esp in Ctors that 453 * can fail. 454 */ 455 void NaClDescSafeUnref(struct NaClDesc *ndp); 456 457 /* 458 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES. 459 */ 460 int NaClDescSetMetadata(struct NaClDesc *self, 461 int32_t metadata_type, 462 uint32_t metadata_num_bytes, 463 uint8_t const *metadata_bytes) NACL_WUR; 464 465 /* 466 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES. 467 */ 468 int32_t NaClDescGetMetadata(struct NaClDesc *self, 469 uint32_t *metadata_buffer_num_bytes_in_out, 470 uint8_t *metadata_buffer) NACL_WUR; 471 472 /* 473 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES. 474 */ 475 void NaClDescSetFlags(struct NaClDesc *self, 476 uint32_t flags); 477 478 /* 479 * USE THE VIRTUAL FUNCTION. THIS DECLARATION IS FOR SUBCLASSES. 480 */ 481 uint32_t NaClDescGetFlags(struct NaClDesc *self); 482 483 int32_t NaClDescIsattyNotImplemented(struct NaClDesc *vself); 484 485 /* 486 * Base class externalize functions; all subclass externalize 487 * functions should invoke these, up the class hierarchy, and add to 488 * the sizes or the NaClDescXferState. 489 */ 490 int NaClDescExternalizeSize(struct NaClDesc *self, 491 size_t *nbytes, 492 size_t *nhandles); 493 494 int NaClDescExternalize(struct NaClDesc *self, 495 struct NaClDescXferState *xfer); 496 497 /* 498 * The top level internalize interface are factories: they allocate 499 * space, then run the internalize-in-place ctor code. Ideally, these 500 * would be two separate functions -- the memory allocation could, in 501 * most cases, be simplified to be simply an attribute containing the 502 * desired memory size and a generic allocator used, though of course 503 * we would like to permit subclasses that contains variable size 504 * arrays (at end of struct), etc. For base (super) classes, the 505 * memory allocation is not necessary, since the subclass internalize 506 * function will have handled it. 507 */ 508 int NaClDescInternalizeCtor(struct NaClDesc *vself, 509 struct NaClDescXferState *xfer); 510 511 512 /* 513 * subclasses are in their own header files. 514 */ 515 516 517 /* utility routines */ 518 519 int32_t NaClAbiStatHostDescStatXlateCtor(struct nacl_abi_stat *dst, 520 nacl_host_stat_t const *src); 521 522 /* 523 * The following two functions are not part of the exported public 524 * API. 525 * 526 * Read/write to a NaClHandle, much like how read/write syscalls work. 527 */ 528 ssize_t NaClDescReadFromHandle(NaClHandle handle, 529 void *buf, 530 size_t length); 531 532 ssize_t NaClDescWriteToHandle(NaClHandle handle, 533 void const *buf, 534 size_t length); 535 536 /* 537 * Default functions for the vtable for when the functionality is 538 * inappropriate for the descriptor type -- they just return 539 * -NACL_ABI_EINVAL 540 */ 541 void NaClDescDtorNotImplemented(struct NaClRefCount *vself); 542 543 uintptr_t NaClDescMapNotImplemented(struct NaClDesc *vself, 544 struct NaClDescEffector *effp, 545 void *start_addr, 546 size_t len, 547 int prot, 548 int flags, 549 nacl_off64_t offset); 550 551 ssize_t NaClDescReadNotImplemented(struct NaClDesc *vself, 552 void *buf, 553 size_t len); 554 555 ssize_t NaClDescWriteNotImplemented(struct NaClDesc *vself, 556 void const *buf, 557 size_t len); 558 559 nacl_off64_t NaClDescSeekNotImplemented(struct NaClDesc *vself, 560 nacl_off64_t offset, 561 int whence); 562 563 ssize_t NaClDescPReadNotImplemented(struct NaClDesc *vself, 564 void *buf, 565 size_t len, 566 nacl_off64_t offset); 567 568 ssize_t NaClDescPWriteNotImplemented(struct NaClDesc *vself, 569 void const *buf, 570 size_t len, 571 nacl_off64_t offset); 572 573 int NaClDescFstatNotImplemented(struct NaClDesc *vself, 574 struct nacl_abi_stat *statbuf); 575 576 int NaClDescFchdirNotImplemented(struct NaClDesc *vself); 577 578 int NaClDescFchmodNotImplemented(struct NaClDesc *vself, 579 int mode); 580 581 int NaClDescFsyncNotImplemented(struct NaClDesc *vself); 582 583 int NaClDescFdatasyncNotImplemented(struct NaClDesc *vself); 584 585 int NaClDescFtruncateNotImplemented(struct NaClDesc *vself, 586 nacl_abi_off_t length); 587 588 ssize_t NaClDescGetdentsNotImplemented(struct NaClDesc *vself, 589 void *dirp, 590 size_t count); 591 592 int NaClDescExternalizeSizeNotImplemented(struct NaClDesc *vself, 593 size_t *nbytes, 594 size_t *nhandles); 595 596 int NaClDescExternalizeNotImplemented(struct NaClDesc *vself, 597 struct NaClDescXferState *xfer); 598 599 int NaClDescLockNotImplemented(struct NaClDesc *vself); 600 601 int NaClDescTryLockNotImplemented(struct NaClDesc *vself); 602 603 int NaClDescUnlockNotImplemented(struct NaClDesc *vself); 604 605 int NaClDescWaitNotImplemented(struct NaClDesc *vself, 606 struct NaClDesc *mutex); 607 608 int NaClDescTimedWaitAbsNotImplemented(struct NaClDesc *vself, 609 struct NaClDesc *mutex, 610 struct nacl_abi_timespec const *ts); 611 612 int NaClDescSignalNotImplemented(struct NaClDesc *vself); 613 614 int NaClDescBroadcastNotImplemented(struct NaClDesc *vself); 615 616 ssize_t NaClDescSendMsgNotImplemented( 617 struct NaClDesc *vself, 618 const struct NaClImcTypedMsgHdr *nitmhp, 619 int flags); 620 621 ssize_t NaClDescRecvMsgNotImplemented( 622 struct NaClDesc *vself, 623 struct NaClImcTypedMsgHdr *nitmhp, 624 int flags); 625 626 ssize_t NaClDescLowLevelSendMsgNotImplemented( 627 struct NaClDesc *vself, 628 struct NaClMessageHeader const *dgram, 629 int flags); 630 631 ssize_t NaClDescLowLevelRecvMsgNotImplemented( 632 struct NaClDesc *vself, 633 struct NaClMessageHeader *dgram, 634 int flags); 635 636 int NaClDescConnectAddrNotImplemented(struct NaClDesc *vself, 637 struct NaClDesc **out_desc); 638 639 int NaClDescAcceptConnNotImplemented(struct NaClDesc *vself, 640 struct NaClDesc **out_desc); 641 642 int NaClDescPostNotImplemented(struct NaClDesc *vself); 643 644 int NaClDescSemWaitNotImplemented(struct NaClDesc *vself); 645 646 int NaClDescGetValueNotImplemented(struct NaClDesc *vself); 647 648 int NaClDescInternalizeNotImplemented( 649 struct NaClDesc **out_desc, 650 struct NaClDescXferState *xfer); 651 652 653 int NaClSafeCloseNaClHandle(NaClHandle h); 654 655 int NaClDescIsSafeForMmap(struct NaClDesc *self); 656 657 void NaClDescMarkSafeForMmap(struct NaClDesc *self); 658 659 EXTERN_C_END 660 661 #endif // NATIVE_CLIENT_SRC_TRUSTED_DESC_NACL_DESC_BASE_H_ 662