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 : * Connection capabilities.
10 : */
11 :
12 : #include <stdlib.h>
13 : #include <string.h>
14 :
15 : #include "native_client/src/include/portability.h"
16 : #include "native_client/src/include/nacl_macros.h"
17 :
18 : #include "native_client/src/shared/imc/nacl_imc_c.h"
19 : #include "native_client/src/shared/platform/nacl_log.h"
20 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
21 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
22 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
23 : #include "native_client/src/trusted/desc/nacl_desc_imc_bound_desc.h"
24 :
25 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
26 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
27 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
28 :
29 : static struct NaClDescVtbl const kNaClDescConnCapVtbl; /* fwd */
30 :
31 : /*
32 : * NaClDescConnCapSubclassCtor takes a memory region of at least the
33 : * size of a NaClDescConnCap in which construction of
34 : * NaClDescConnCap's superclass has already occurred, and construct
35 : * the remaining members (newly introduced by NaClDescConnCap). This
36 : * is needed by the *Internalize function.
37 : */
38 : static int NaClDescConnCapSubclassCtor(struct NaClDescConnCap *self,
39 2 : struct NaClSocketAddress const *nsap) {
40 2 : struct NaClDesc *basep = (struct NaClDesc *) self;
41 :
42 2 : self->cap = *nsap;
43 2 : basep->base.vtbl = (struct NaClRefCountVtbl const *) &kNaClDescConnCapVtbl;
44 2 : return 1;
45 2 : }
46 :
47 : int NaClDescConnCapCtor(struct NaClDescConnCap *self,
48 2 : struct NaClSocketAddress const *nsap) {
49 2 : struct NaClDesc *basep = (struct NaClDesc *) self;
50 : int rv;
51 :
52 2 : basep->base.vtbl = (struct NaClRefCountVtbl const *) NULL;
53 2 : if (!NaClDescCtor(basep)) {
54 0 : return 0;
55 : }
56 2 : rv = NaClDescConnCapSubclassCtor(self, nsap);
57 2 : if (!rv) {
58 : /* NaClDescConnCap construction failed, still a NaClDesc object */
59 0 : (*NACL_VTBL(NaClRefCount, basep)->Dtor)((struct NaClRefCount *) basep);
60 : /* not-an-object; caller frees */
61 : }
62 2 : return rv;
63 2 : }
64 :
65 0 : static void NaClDescConnCapDtor(struct NaClRefCount *vself) {
66 0 : vself->vtbl = (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
67 0 : (*vself->vtbl->Dtor)(vself);
68 : return;
69 0 : }
70 :
71 : static int NaClDescConnCapFstat(struct NaClDesc *vself,
72 0 : struct nacl_abi_stat *statbuf) {
73 : UNREFERENCED_PARAMETER(vself);
74 :
75 0 : memset(statbuf, 0, sizeof *statbuf);
76 0 : statbuf->nacl_abi_st_mode = NACL_ABI_S_IFSOCKADDR | NACL_ABI_S_IRWXU;
77 0 : return 0;
78 0 : }
79 :
80 : static int NaClDescConnCapExternalizeSize(struct NaClDesc *vself,
81 : size_t *nbytes,
82 0 : size_t *nhandles) {
83 : int rv;
84 :
85 : UNREFERENCED_PARAMETER(vself);
86 :
87 0 : rv = NaClDescExternalizeSize(vself, nbytes, nhandles);
88 0 : if (0 != rv) {
89 0 : return rv;
90 : }
91 :
92 0 : *nbytes += NACL_PATH_MAX;
93 :
94 0 : return 0;
95 0 : }
96 :
97 : static int NaClDescConnCapExternalize(struct NaClDesc *vself,
98 0 : struct NaClDescXferState *xfer) {
99 : struct NaClDescConnCap *self;
100 : int rv;
101 :
102 0 : rv = NaClDescExternalize(vself, xfer);
103 0 : if (0 != rv) {
104 0 : return rv;
105 : }
106 0 : self = (struct NaClDescConnCap *) vself;
107 0 : memcpy(xfer->next_byte, self->cap.path, NACL_PATH_MAX);
108 0 : xfer->next_byte += NACL_PATH_MAX;
109 :
110 0 : return 0;
111 0 : }
112 :
113 : int NaClDescConnCapConnectAddr(struct NaClDesc *vself,
114 2 : struct NaClDesc **out_desc) {
115 : /*
116 : * See NaClDescImcBoundDescAcceptConn code in
117 : * nacl_desc_imc_bound_desc.c
118 : */
119 : struct NaClDescConnCap *self;
120 : int retval;
121 : NaClHandle nh[2];
122 : size_t ix;
123 : struct NaClMessageHeader conn_msg;
124 : struct NaClDescImcDesc *peer;
125 :
126 2 : NaClLog(3, "Entered NaClDescConnCapConnectAddr\n");
127 2 : self = (struct NaClDescConnCap *) vself;
128 :
129 2 : peer = NULL;
130 2 : for (ix = 0; ix < NACL_ARRAY_SIZE(nh); ++ix) {
131 2 : nh[ix] = NACL_INVALID_HANDLE;
132 2 : }
133 :
134 2 : NaClLog(4, " socket address %.*s\n", NACL_PATH_MAX, self->cap.path);
135 :
136 2 : if (NULL == (peer = malloc(sizeof *peer))) {
137 0 : retval = -NACL_ABI_ENOMEM;
138 0 : goto cleanup;
139 : }
140 :
141 2 : if (0 != NaClSocketPair(nh)) {
142 0 : retval = -NACL_ABI_EMFILE;
143 0 : goto cleanup;
144 : }
145 :
146 2 : conn_msg.iov_length = 0;
147 2 : conn_msg.iov = NULL;
148 2 : conn_msg.handles = &nh[0];
149 2 : conn_msg.handle_count = 1; /* send nh[0], keep nh[1] */
150 2 : conn_msg.flags = 0;
151 :
152 2 : NaClLog(4, " sending connection message\n");
153 2 : if (-1 == NaClSendDatagramTo(&conn_msg, 0, &self->cap)) {
154 : NaClLog(LOG_ERROR, ("NaClDescConnCapConnectAddr:"
155 0 : " initial connect message could not be sent.\n"));
156 0 : retval = -NACL_ABI_EIO;
157 0 : goto cleanup;
158 : }
159 :
160 2 : (void) NaClClose(nh[0]);
161 2 : nh[0] = NACL_INVALID_HANDLE;
162 2 : NaClLog(4, " creating NaClDescImcDesc for local end of socketpair\n");
163 2 : if (!NaClDescImcDescCtor(peer, nh[1])) {
164 0 : retval = -NACL_ABI_EMFILE; /* TODO(bsy): is this the right errno? */
165 0 : goto cleanup;
166 : }
167 2 : nh[1] = NACL_INVALID_HANDLE;
168 :
169 2 : *out_desc = (struct NaClDesc *) peer;
170 2 : retval = 0;
171 :
172 : cleanup:
173 2 : if (retval < 0) {
174 0 : NaClLog(4, " error return; cleaning up\n");
175 0 : if (NACL_INVALID_HANDLE != nh[0])
176 0 : (void) NaClClose(nh[0]);
177 0 : if (NACL_INVALID_HANDLE != nh[1])
178 0 : (void) NaClClose(nh[1]);
179 : /* peer is not constructed, so we need only to free the memory */
180 0 : free(peer);
181 : }
182 2 : return retval;
183 2 : }
184 :
185 : static int NaClDescConnCapAcceptConn(struct NaClDesc *vself,
186 0 : struct NaClDesc **out_desc) {
187 : UNREFERENCED_PARAMETER(vself);
188 : UNREFERENCED_PARAMETER(out_desc);
189 :
190 0 : NaClLog(LOG_ERROR, "NaClDescConnCapAcceptConn: not IMC\n");
191 0 : return -NACL_ABI_EINVAL;
192 0 : }
193 :
194 : static struct NaClDescVtbl const kNaClDescConnCapVtbl = {
195 : {
196 : NaClDescConnCapDtor,
197 : },
198 : NaClDescMapNotImplemented,
199 : NACL_DESC_UNMAP_NOT_IMPLEMENTED
200 : NaClDescReadNotImplemented,
201 : NaClDescWriteNotImplemented,
202 : NaClDescSeekNotImplemented,
203 : NaClDescPReadNotImplemented,
204 : NaClDescPWriteNotImplemented,
205 : NaClDescConnCapFstat,
206 : NaClDescGetdentsNotImplemented,
207 : NaClDescConnCapExternalizeSize,
208 : NaClDescConnCapExternalize,
209 : NaClDescLockNotImplemented,
210 : NaClDescTryLockNotImplemented,
211 : NaClDescUnlockNotImplemented,
212 : NaClDescWaitNotImplemented,
213 : NaClDescTimedWaitAbsNotImplemented,
214 : NaClDescSignalNotImplemented,
215 : NaClDescBroadcastNotImplemented,
216 : NaClDescSendMsgNotImplemented,
217 : NaClDescRecvMsgNotImplemented,
218 : NaClDescLowLevelSendMsgNotImplemented,
219 : NaClDescLowLevelRecvMsgNotImplemented,
220 : NaClDescConnCapConnectAddr,
221 : NaClDescConnCapAcceptConn,
222 : NaClDescPostNotImplemented,
223 : NaClDescSemWaitNotImplemented,
224 : NaClDescGetValueNotImplemented,
225 : NaClDescSetMetadata,
226 : NaClDescGetMetadata,
227 : NaClDescSetFlags,
228 : NaClDescGetFlags,
229 : NaClDescIsattyNotImplemented,
230 : NACL_DESC_CONN_CAP,
231 : };
232 :
233 : int NaClDescConnCapInternalize(struct NaClDesc **out_desc,
234 : struct NaClDescXferState *xfer,
235 0 : struct NaClDescQuotaInterface *quota_interface) {
236 : int rv;
237 : struct NaClSocketAddress nsa;
238 : struct NaClDescConnCap *ndccp;
239 :
240 : UNREFERENCED_PARAMETER(quota_interface);
241 0 : rv = -NACL_ABI_EIO; /* catch-all */
242 :
243 0 : ndccp = malloc(sizeof *ndccp);
244 0 : if (NULL == ndccp) {
245 0 : rv = -NACL_ABI_ENOMEM;
246 0 : goto cleanup;
247 : }
248 0 : if (!NaClDescInternalizeCtor((struct NaClDesc *) ndccp, xfer)) {
249 0 : free(ndccp);
250 0 : ndccp = NULL;
251 0 : rv = -NACL_ABI_ENOMEM;
252 0 : goto cleanup;
253 : }
254 0 : if (xfer->next_byte + NACL_PATH_MAX > xfer->byte_buffer_end) {
255 0 : rv = -NACL_ABI_EIO;
256 0 : goto cleanup;
257 : }
258 0 : memcpy(nsa.path, xfer->next_byte, NACL_PATH_MAX);
259 0 : if (!NaClDescConnCapSubclassCtor(ndccp, &nsa)) {
260 0 : rv = -NACL_ABI_EIO;
261 0 : goto cleanup;
262 : }
263 0 : *out_desc = (struct NaClDesc *) ndccp;
264 0 : rv = 0;
265 0 : xfer->next_byte += NACL_PATH_MAX;
266 : cleanup:
267 0 : if (rv < 0) {
268 0 : NaClDescSafeUnref((struct NaClDesc *) ndccp);
269 : }
270 0 : return rv;
271 0 : }
|