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 : #include <string.h>
8 :
9 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
10 :
11 : #include "native_client/src/include/nacl_base.h"
12 : #include "native_client/src/include/nacl_macros.h"
13 : #include "native_client/src/shared/platform/nacl_check.h"
14 : #include "native_client/src/shared/platform/nacl_log.h"
15 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
16 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
17 : #include "native_client/src/trusted/desc/nacl_desc_null.h"
18 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
19 : #include "native_client/src/trusted/service_runtime/nacl_desc_postmessage.h"
20 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
21 :
22 3 : struct NaClDesc *NaClResourceOpen(struct NaClResource *self,
23 3 : char const *resource_locator,
24 3 : int nacl_flags,
25 3 : int mode) {
26 3 : size_t ix;
27 3 : size_t default_ix = ~(size_t) 0; /* greater than self->num_schemes */
28 3 : size_t prefix_len;
29 3 : int allow_debug = 0;
30 :
31 3 : NaClLog(4, "NaClResourceOpen(*,\"%s\",0x%x,0%o)\n",
32 : resource_locator, nacl_flags, mode);
33 3 : prefix_len = strlen(NACL_RESOURCE_DEBUG_WARNING);
34 3 : if (strncmp(resource_locator, NACL_RESOURCE_DEBUG_WARNING,
35 : prefix_len) == 0) {
36 0 : allow_debug = 1;
37 0 : resource_locator += prefix_len;
38 0 : }
39 :
40 18 : for (ix = 0; ix < self->num_schemes; ++ix) {
41 6 : if (self->schemes[ix].default_scheme) {
42 3 : default_ix = ix;
43 3 : }
44 6 : prefix_len = strlen(self->schemes[ix].scheme_prefix);
45 6 : NaClLog(4, " prefix \"%s\"\n", self->schemes[ix].scheme_prefix);
46 6 : if (0 == strncmp(self->schemes[ix].scheme_prefix, resource_locator,
47 : prefix_len)) {
48 0 : char const *rest = resource_locator + prefix_len;
49 0 : NaClLog(4, " prefix match at %"NACL_PRIuS", rest \"%s\".\n", ix, rest);
50 0 : return (*self->schemes[ix].Open)(self, rest,
51 : nacl_flags, mode, allow_debug);
52 : }
53 6 : }
54 3 : if (default_ix < self->num_schemes) {
55 3 : NaClLog(4, " trying default scheme %"NACL_PRIuS".\n", default_ix);
56 3 : return (*self->schemes[default_ix].Open)(self, resource_locator,
57 : nacl_flags, mode, allow_debug);
58 : }
59 0 : NaClLog(4, " no match, and no default scheme to try.");
60 0 : return NULL;
61 3 : }
62 :
63 296 : int NaClResourceCtor(struct NaClResource *self,
64 296 : struct NaClResourceSchemes const *scheme_tbl,
65 296 : size_t num_schemes) {
66 296 : self->schemes = scheme_tbl;
67 296 : self->num_schemes = num_schemes;
68 296 : return 1;
69 : }
70 :
71 : /* --------------------------------------------------------------------------
72 : *
73 : * Subclass of NaClResource
74 : *
75 : * --------------------------------------------------------------------------
76 : */
77 :
78 296 : int NaClResourceNaClAppCtor(struct NaClResourceNaClApp *self,
79 296 : struct NaClResourceSchemes const *scheme_tbl,
80 296 : size_t num_schemes,
81 296 : struct NaClApp *nap) {
82 296 : NaClLog(4,
83 : ("NaClResourceNaClAppCtor, scheme_tbl 0x%"NACL_PRIxPTR","
84 : " size %"NACL_PRIuS".\n"),
85 : (uintptr_t) scheme_tbl, num_schemes);
86 296 : if (!NaClResourceCtor(&self->base, scheme_tbl, num_schemes)) {
87 0 : return 0;
88 : }
89 296 : self->nap = nap;
90 296 : return 1;
91 296 : }
92 :
93 : static struct NaClDesc *NaClResourceNullFactory(void) {
94 2 : struct NaClDescNull *null_desc = NULL;
95 :
96 1 : null_desc = malloc(sizeof *null_desc);
97 1 : if (NULL == null_desc) {
98 0 : return NULL;
99 : }
100 1 : if (!NaClDescNullCtor(null_desc)) {
101 0 : free(null_desc);
102 0 : null_desc = NULL;
103 0 : }
104 1 : return (struct NaClDesc *) null_desc;
105 1 : }
106 :
107 2 : static struct NaClDesc *NaClResourceFileFactory(char const *resource_locator,
108 2 : int nacl_flags,
109 2 : int mode) {
110 2 : struct NaClHostDesc *hd = NULL;
111 2 : struct NaClDescIoDesc *did = NULL;
112 2 : struct NaClDesc *rv = NULL;
113 :
114 2 : hd = malloc(sizeof *hd);
115 2 : did = malloc(sizeof *did);
116 4 : if (NULL == hd || NULL == did) {
117 0 : goto done;
118 : }
119 2 : NaClLog(4,
120 : ("NaClResourceFileFactory: invoking NaClHostDescOpen on"
121 : " %s, flags 0x%x, mode 0%o\n"),
122 : resource_locator, nacl_flags, mode);
123 2 : if (0 != NaClHostDescOpen(hd, resource_locator, nacl_flags, mode)) {
124 0 : NaClLog(LOG_INFO,
125 : "NaClResourceFileFactory: NaClHostDescOpen failed\n");
126 0 : goto done;
127 : }
128 2 : if (!NaClDescIoDescCtor(did, hd)) {
129 0 : NaClLog(LOG_INFO,
130 : "NaClResourceFileFactory: NaClDescIoDescCtor failed\n");
131 0 : if (0 != NaClHostDescClose(hd)) {
132 0 : NaClLog(LOG_FATAL, "NaClResourceFileFactory: NaClHostDescClose failed\n");
133 0 : }
134 0 : goto done;
135 : }
136 2 : hd = NULL; /* ownership passed into did */
137 2 : rv = (struct NaClDesc *) did; /* success */
138 2 : did = NULL;
139 : done:
140 2 : free(hd);
141 2 : free(did);
142 2 : return rv;
143 : }
144 :
145 : static struct NaClDesc *NaClResourceNaClAppFileOpen(
146 3 : struct NaClResource *vself,
147 3 : char const *resource_locator,
148 3 : int nacl_flags,
149 3 : int mode,
150 3 : int allow_debug) {
151 3 : struct NaClResourceNaClApp *self = (struct NaClResourceNaClApp *) vself;
152 3 : struct NaClDesc *rv = NULL;
153 :
154 : /*
155 : * Initialization order requires that file opens occur only early,
156 : * in NACl_RESOURCE_PHASE_START, because otherwise (in the OSX case)
157 : * the sandbox gets enabled after the reverse channel is set up, and
158 : * the ability to open files go away.
159 : */
160 6 : UNREFERENCED_PARAMETER(allow_debug);
161 3 : if (self->nap->resource_phase != NACL_RESOURCE_PHASE_START) {
162 0 : return NULL;
163 : }
164 3 : if (0 == strcmp(resource_locator, NACL_RESOURCE_FILE_DEV_NULL)) {
165 1 : rv = NaClResourceNullFactory();
166 1 : if (NULL == rv) {
167 0 : NaClLog(LOG_ERROR, "Could not create Null device. Redirect failed.\n");
168 0 : }
169 1 : } else {
170 2 : rv = NaClResourceFileFactory(resource_locator, nacl_flags, mode);
171 2 : if (NULL == rv) {
172 0 : NaClLog(LOG_ERROR, "Could not open file \"%s\". Redirect failed.\n",
173 : resource_locator);
174 0 : }
175 : }
176 3 : NaClLog(4, "NaClResourceNaClAppFileOpen returning 0x%"NACL_PRIxPTR"\n",
177 : (uintptr_t) rv);
178 3 : return rv;
179 3 : }
180 :
181 : /*
182 : * We don't bother to make it a singleton postmessage device. Thread
183 : * safety is handled when the device object gets the lock to use the
184 : * reverse channel.
185 : */
186 : static struct NaClDesc *NaClResourceNaClAppDevOpen(
187 0 : struct NaClResource *vself,
188 0 : char const *resource_locator,
189 0 : int nacl_flags,
190 0 : int mode,
191 0 : int allow_debug) {
192 0 : struct NaClResourceNaClApp *self = (struct NaClResourceNaClApp *) vself;
193 0 : struct NaClDescPostMessage *ndpm = NULL;
194 :
195 0 : if (self->nap->resource_phase != NACL_RESOURCE_PHASE_RUNTIME_HOST
196 : || !allow_debug) {
197 0 : return NULL;
198 : }
199 :
200 0 : if (0 == strcmp(resource_locator, NACL_RESOURCE_DEV_POSTMESSAGE_LOCATOR)) {
201 : /* disallow O_RDONLY or O_RDWR */
202 0 : if ((NACL_ABI_O_ACCMODE & nacl_flags) != NACL_ABI_O_WRONLY) {
203 0 : return NULL;
204 : }
205 : /* allow O_CREAT, O_APPEND, and O_TRUNC */
206 0 : UNREFERENCED_PARAMETER(mode); /* ignored; O_CREAT doesn't create. */
207 :
208 0 : ndpm = malloc(sizeof *ndpm);
209 0 : if (NULL != ndpm) {
210 0 : if (!NaClDescPostMessageCtor(ndpm, self->nap->runtime_host_interface)) {
211 0 : free(ndpm);
212 0 : ndpm = NULL;
213 0 : }
214 0 : }
215 0 : if (NULL == ndpm) {
216 0 : NaClLog(LOG_ERROR,
217 : "NaClResourceNaClAppDevOpen(%s) failed\n",
218 : resource_locator);
219 0 : }
220 0 : }
221 0 : return (struct NaClDesc *) ndpm;
222 0 : }
223 :
224 296 : int NaClResourceNaClAppInit(struct NaClResourceNaClApp *rp,
225 296 : struct NaClApp *nap) {
226 : static struct NaClResourceSchemes const schemes[] = {
227 : {
228 : NACL_RESOURCE_FILE_PREFIX,
229 : 1, /* default scheme */
230 : NaClResourceNaClAppFileOpen,
231 : }, {
232 : NACL_RESOURCE_DEV_PREFIX,
233 : 0, /* not default scheme */
234 : NaClResourceNaClAppDevOpen,
235 : },
236 : };
237 :
238 296 : NaClLog(4, "NaClResourceNaClAppInit -- Ctor with default schemes\n");
239 296 : return NaClResourceNaClAppCtor(rp, schemes, NACL_ARRAY_SIZE(schemes), nap);
240 : }
|