OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2011 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 * Subclass of NaClDesc which passes write output data to the browser |
| 9 * using the reverse channel, to (eventually) show up as PostMessage |
| 10 * data. |
| 11 * |
| 12 * A NaClDescPostMessage object pretends to be a character device, so |
| 13 * that I/O packages that fstat to determine buffering strategy will |
| 14 * work correctly. The only other syscall that it implements is |
| 15 * write, and the data is sent through the reverse channel interface |
| 16 * to the browser's JavaScript environment. |
| 17 */ |
| 18 |
| 19 #include <string.h> |
| 20 |
| 21 #include "native_client/src/trusted/service_runtime/nacl_desc_postmessage.h" |
| 22 |
| 23 #include "native_client/src/shared/platform/nacl_check.h" |
| 24 #include "native_client/src/shared/platform/nacl_sync.h" |
| 25 #include "native_client/src/shared/platform/nacl_sync_checked.h" |
| 26 #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h" |
| 27 #include "native_client/src/trusted/service_runtime/include/sys/errno.h" |
| 28 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
| 29 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| 30 |
| 31 |
| 32 static struct NaClDescVtbl const kNaClDescPostMessageVtbl; /* fwd */ |
| 33 |
| 34 int NaClDescPostMessageCtor(struct NaClDescPostMessage *self, |
| 35 struct NaClApp *nap) { |
| 36 NaClLog(4, "Entered NaClDescPostMessageCtor\n"); |
| 37 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *) NULL; |
| 38 if (!NaClDescCtor(&self->base)) { |
| 39 NaClLog(4, "Leaving NaClDescPostMessageCtor: failed\n"); |
| 40 return 0; |
| 41 } |
| 42 self->nap = nap; |
| 43 self->error = 0; |
| 44 NACL_VTBL(NaClRefCount, self) = |
| 45 (struct NaClRefCountVtbl const *) &kNaClDescPostMessageVtbl; |
| 46 NaClLog(4, " Write vfptr = %"NACL_PRIxPTR"\n", |
| 47 (uintptr_t) NACL_VTBL(NaClDesc, self)->Write); |
| 48 NaClLog(4, "Leaving NaClDescPostMessageCtor: success\n"); |
| 49 return 1; |
| 50 } |
| 51 |
| 52 static void NaClDescPostMessageDtor(struct NaClRefCount *vself) { |
| 53 struct NaClDescPostMessage *self = (struct NaClDescPostMessage *) vself; |
| 54 |
| 55 NaClLog(4, "Entered NaClDescPostMessageDtor\n"); |
| 56 self->nap = NULL; |
| 57 NACL_VTBL(NaClRefCount, vself) = |
| 58 (struct NaClRefCountVtbl const *) &kNaClDescVtbl; |
| 59 (*NACL_VTBL(NaClRefCount, vself)->Dtor)(vself); |
| 60 NaClLog(4, "Leaving NaClDescPostMessageDtor\n"); |
| 61 } |
| 62 |
| 63 static ssize_t NaClDescPostMessageWrite(struct NaClDesc *vself, |
| 64 void const *buf, |
| 65 size_t len) { |
| 66 struct NaClDescPostMessage *self = (struct NaClDescPostMessage *) vself; |
| 67 NaClSrpcError rpc_result; |
| 68 int num_written = 0; |
| 69 ssize_t rv = -NACL_ABI_EIO; |
| 70 |
| 71 NaClLog(4, "Entered NaClDescPostMessageWrite(..., %"NACL_PRIuS")\n", len); |
| 72 if (0 != self->error) { |
| 73 return self->error; |
| 74 } |
| 75 NaClXMutexLock(&self->nap->mu); |
| 76 if (NACL_REVERSE_CHANNEL_INITIALIZED != |
| 77 self->nap->reverse_channel_initialization_state) { |
| 78 NaClLog(LOG_FATAL, |
| 79 "NaClDescPostMessageWrite: Reverse channel not initialized\n"); |
| 80 } |
| 81 if (len > NACL_ABI_SIZE_T_MAX) { |
| 82 len = NACL_ABI_SIZE_T_MAX; /* fits in an int32_t */ |
| 83 } |
| 84 rpc_result = NaClSrpcInvokeBySignature(&self->nap->reverse_channel, |
| 85 NACL_REVERSE_CONTROL_POST_MESSAGE, |
| 86 len, |
| 87 buf, |
| 88 &num_written); |
| 89 if (NACL_SRPC_RESULT_OK != rpc_result || num_written > (int) len) { |
| 90 /* |
| 91 * A conforming interface implementation could return an errno, |
| 92 * but should never return a larger value. |
| 93 */ |
| 94 rv = -NACL_ABI_EIO; |
| 95 /* |
| 96 * make this error permanent; other negative errno returns are |
| 97 * considered transient. |
| 98 */ |
| 99 self->error = rv; |
| 100 goto error_exit; |
| 101 } |
| 102 rv = (ssize_t) num_written; |
| 103 error_exit: |
| 104 NaClXMutexUnlock(&self->nap->mu); |
| 105 NaClLog(4, "Leaving NaClDescPostMessageWrite (%"NACL_PRIuS")\n", rv); |
| 106 return rv; |
| 107 } |
| 108 |
| 109 static int NaClDescPostMessageFstat(struct NaClDesc *vself, |
| 110 struct nacl_abi_stat *statbuf) { |
| 111 UNREFERENCED_PARAMETER(vself); |
| 112 |
| 113 memset(statbuf, 0, sizeof *statbuf); |
| 114 statbuf->nacl_abi_st_ino = NACL_FAKE_INODE_NUM; |
| 115 statbuf->nacl_abi_st_mode = (NACL_ABI_S_IFCHR | NACL_ABI_S_IWUSR); |
| 116 statbuf->nacl_abi_st_nlink = 1; |
| 117 statbuf->nacl_abi_st_uid = -1; |
| 118 statbuf->nacl_abi_st_gid = -1; |
| 119 return 0; |
| 120 } |
| 121 |
| 122 static struct NaClDescVtbl const kNaClDescPostMessageVtbl = { |
| 123 { |
| 124 NaClDescPostMessageDtor, |
| 125 }, |
| 126 NaClDescMapNotImplemented, |
| 127 NaClDescUnmapUnsafeNotImplemented, |
| 128 NaClDescUnmapNotImplemented, |
| 129 NaClDescReadNotImplemented, |
| 130 NaClDescPostMessageWrite, |
| 131 NaClDescSeekNotImplemented, |
| 132 NaClDescIoctlNotImplemented, |
| 133 NaClDescPostMessageFstat, |
| 134 NaClDescGetdentsNotImplemented, |
| 135 NACL_DESC_DEVICE_POSTMESSAGE, |
| 136 NaClDescExternalizeSizeNotImplemented, |
| 137 NaClDescExternalizeNotImplemented, |
| 138 NaClDescLockNotImplemented, |
| 139 NaClDescTryLockNotImplemented, |
| 140 NaClDescUnlockNotImplemented, |
| 141 NaClDescWaitNotImplemented, |
| 142 NaClDescTimedWaitAbsNotImplemented, |
| 143 NaClDescSignalNotImplemented, |
| 144 NaClDescBroadcastNotImplemented, |
| 145 NaClDescSendMsgNotImplemented, |
| 146 NaClDescRecvMsgNotImplemented, |
| 147 NaClDescConnectAddrNotImplemented, |
| 148 NaClDescAcceptConnNotImplemented, |
| 149 NaClDescPostNotImplemented, |
| 150 NaClDescSemWaitNotImplemented, |
| 151 NaClDescGetValueNotImplemented, |
| 152 }; |
OLD | NEW |