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 0 : struct NaClApp *nap) {
36 0 : NaClLog(4, "Entered NaClDescPostMessageCtor\n");
37 0 : NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *) NULL;
38 0 : if (!NaClDescCtor(&self->base)) {
39 0 : NaClLog(4, "Leaving NaClDescPostMessageCtor: failed\n");
40 0 : return 0;
41 : }
42 0 : self->nap = nap;
43 0 : self->error = 0;
44 0 : NACL_VTBL(NaClRefCount, self) =
45 : (struct NaClRefCountVtbl const *) &kNaClDescPostMessageVtbl;
46 0 : NaClLog(4, " Write vfptr = %"NACL_PRIxPTR"\n",
47 : (uintptr_t) NACL_VTBL(NaClDesc, self)->Write);
48 0 : NaClLog(4, "Leaving NaClDescPostMessageCtor: success\n");
49 0 : return 1;
50 : }
51 :
52 0 : static void NaClDescPostMessageDtor(struct NaClRefCount *vself) {
53 0 : struct NaClDescPostMessage *self = (struct NaClDescPostMessage *) vself;
54 :
55 0 : NaClLog(4, "Entered NaClDescPostMessageDtor\n");
56 0 : self->nap = NULL;
57 0 : NACL_VTBL(NaClRefCount, vself) =
58 : (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
59 0 : (*NACL_VTBL(NaClRefCount, vself)->Dtor)(vself);
60 0 : NaClLog(4, "Leaving NaClDescPostMessageDtor\n");
61 0 : }
62 :
63 : static ssize_t NaClDescPostMessageWrite(struct NaClDesc *vself,
64 : void const *buf,
65 0 : size_t len) {
66 0 : struct NaClDescPostMessage *self = (struct NaClDescPostMessage *) vself;
67 : NaClSrpcError rpc_result;
68 0 : int num_written = 0;
69 0 : ssize_t rv = -NACL_ABI_EIO;
70 :
71 0 : NaClLog(4, "Entered NaClDescPostMessageWrite(..., %"NACL_PRIuS")\n", len);
72 0 : if (0 != self->error) {
73 0 : return self->error;
74 : }
75 0 : NaClXMutexLock(&self->nap->mu);
76 0 : if (NACL_REVERSE_CHANNEL_INITIALIZED !=
77 : self->nap->reverse_channel_initialization_state) {
78 0 : 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 0 : rpc_result = NaClSrpcInvokeBySignature(&self->nap->reverse_channel,
85 : NACL_REVERSE_CONTROL_POST_MESSAGE,
86 : len,
87 : buf,
88 : &num_written);
89 0 : 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 0 : rv = -NACL_ABI_EIO;
95 : /*
96 : * make this error permanent; other negative errno returns are
97 : * considered transient.
98 : */
99 0 : self->error = rv;
100 : } else {
101 0 : rv = (ssize_t) num_written;
102 : }
103 0 : NaClXMutexUnlock(&self->nap->mu);
104 0 : NaClLog(4, "Leaving NaClDescPostMessageWrite (%"NACL_PRIuS")\n", rv);
105 0 : return rv;
106 : }
107 :
108 : static int NaClDescPostMessageFstat(struct NaClDesc *vself,
109 0 : struct nacl_abi_stat *statbuf) {
110 : UNREFERENCED_PARAMETER(vself);
111 :
112 0 : memset(statbuf, 0, sizeof *statbuf);
113 0 : statbuf->nacl_abi_st_ino = NACL_FAKE_INODE_NUM;
114 0 : statbuf->nacl_abi_st_mode = (NACL_ABI_S_IFCHR | NACL_ABI_S_IWUSR);
115 0 : statbuf->nacl_abi_st_nlink = 1;
116 0 : statbuf->nacl_abi_st_uid = -1;
117 0 : statbuf->nacl_abi_st_gid = -1;
118 0 : return 0;
119 : }
120 :
121 : static struct NaClDescVtbl const kNaClDescPostMessageVtbl = {
122 : {
123 : NaClDescPostMessageDtor,
124 : },
125 : NaClDescMapNotImplemented,
126 : NaClDescUnmapUnsafeNotImplemented,
127 : NaClDescUnmapNotImplemented,
128 : NaClDescReadNotImplemented,
129 : NaClDescPostMessageWrite,
130 : NaClDescSeekNotImplemented,
131 : NaClDescIoctlNotImplemented,
132 : NaClDescPostMessageFstat,
133 : NaClDescGetdentsNotImplemented,
134 : NACL_DESC_DEVICE_POSTMESSAGE,
135 : NaClDescExternalizeSizeNotImplemented,
136 : NaClDescExternalizeNotImplemented,
137 : NaClDescLockNotImplemented,
138 : NaClDescTryLockNotImplemented,
139 : NaClDescUnlockNotImplemented,
140 : NaClDescWaitNotImplemented,
141 : NaClDescTimedWaitAbsNotImplemented,
142 : NaClDescSignalNotImplemented,
143 : NaClDescBroadcastNotImplemented,
144 : NaClDescSendMsgNotImplemented,
145 : NaClDescRecvMsgNotImplemented,
146 : NaClDescConnectAddrNotImplemented,
147 : NaClDescAcceptConnNotImplemented,
148 : NaClDescPostNotImplemented,
149 : NaClDescSemWaitNotImplemented,
150 : NaClDescGetValueNotImplemented,
151 : };
|