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/service_runtime/include/sys/fcntl.h"
18 : #include "native_client/src/trusted/service_runtime/nacl_desc_postmessage.h"
19 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
20 :
21 : struct NaClDesc *NaClResourceOpen(struct NaClResource *self,
22 : char const *resource_locator,
23 : int nacl_flags,
24 0 : int mode) {
25 : size_t ix;
26 0 : size_t default_ix = ~(size_t) 0; /* greater than self->num_schemes */
27 : size_t prefix_len;
28 0 : int allow_debug = 0;
29 :
30 0 : NaClLog(4, "NaClResourceOpen(*,\"%s\",0x%x,0%o)\n",
31 : resource_locator, nacl_flags, mode);
32 0 : prefix_len = strlen(NACL_RESOURCE_DEBUG_WARNING);
33 0 : if (strncmp(resource_locator, NACL_RESOURCE_DEBUG_WARNING,
34 : prefix_len) == 0) {
35 0 : allow_debug = 1;
36 0 : resource_locator += prefix_len;
37 : }
38 :
39 0 : for (ix = 0; ix < self->num_schemes; ++ix) {
40 0 : if (self->schemes[ix].default_scheme) {
41 0 : default_ix = ix;
42 : }
43 0 : prefix_len = strlen(self->schemes[ix].scheme_prefix);
44 0 : NaClLog(4, " prefix \"%s\"\n", self->schemes[ix].scheme_prefix);
45 0 : if (0 == strncmp(self->schemes[ix].scheme_prefix, resource_locator,
46 : prefix_len)) {
47 0 : char const *rest = resource_locator + prefix_len;
48 0 : NaClLog(4, " prefix match at %"NACL_PRIuS", rest \"%s\".\n", ix, rest);
49 0 : return (*self->schemes[ix].Open)(self, rest,
50 : nacl_flags, mode, allow_debug);
51 : }
52 : }
53 0 : if (default_ix < self->num_schemes) {
54 0 : NaClLog(4, " trying default scheme %"NACL_PRIuS".\n", default_ix);
55 0 : return (*self->schemes[default_ix].Open)(self, resource_locator,
56 : nacl_flags, mode, allow_debug);
57 : }
58 0 : NaClLog(4, " no match, and no default scheme to try.");
59 0 : return NULL;
60 : }
61 :
62 : int NaClResourceCtor(struct NaClResource *self,
63 : struct NaClResourceSchemes const *scheme_tbl,
64 19 : size_t num_schemes) {
65 19 : self->schemes = scheme_tbl;
66 19 : self->num_schemes = num_schemes;
67 19 : return 1;
68 : }
69 :
70 : /* --------------------------------------------------------------------------
71 : *
72 : * Subclass of NaClResource
73 : *
74 : * --------------------------------------------------------------------------
75 : */
76 :
77 : int NaClResourceNaClAppCtor(struct NaClResourceNaClApp *self,
78 : struct NaClResourceSchemes const *scheme_tbl,
79 : size_t num_schemes,
80 19 : struct NaClApp *nap) {
81 19 : NaClLog(4,
82 : ("NaClResourceNaClAppCtor, scheme_tbl 0x%"NACL_PRIxPTR","
83 : " size %"NACL_PRIuS".\n"),
84 : (uintptr_t) scheme_tbl, num_schemes);
85 19 : if (!NaClResourceCtor(&self->base, scheme_tbl, num_schemes)) {
86 0 : return 0;
87 : }
88 19 : self->nap = nap;
89 19 : return 1;
90 : }
91 :
92 : static struct NaClDesc *NaClResourceNaClAppFileOpen(
93 : struct NaClResource *vself,
94 : char const *resource_locator,
95 : int nacl_flags,
96 : int mode,
97 0 : int allow_debug) {
98 0 : struct NaClResourceNaClApp *self = (struct NaClResourceNaClApp *) vself;
99 0 : struct NaClHostDesc *hd = NULL;
100 0 : struct NaClDescIoDesc *did = NULL;
101 0 : struct NaClDesc *rv = NULL;
102 :
103 : /*
104 : * Functionality-wise, we're startup phase-independent; we can
105 : * always try to open a file; however, initialization requires that
106 : * file opens occur only early, in NACl_RESOURCE_PHASE_START.
107 : */
108 : UNREFERENCED_PARAMETER(allow_debug);
109 0 : if (self->nap->resource_phase != NACL_RESOURCE_PHASE_START) {
110 0 : return NULL;
111 : }
112 0 : hd = malloc(sizeof *hd);
113 0 : did = malloc(sizeof *did);
114 0 : if (NULL == hd || NULL == did) {
115 : goto done;
116 : }
117 0 : NaClLog(4,
118 : ("NaClResourceNaClAppFileOpen: invoking NaClHostDescOpen on"
119 : " %s, flags 0x%x, mode 0%o\n"),
120 : resource_locator, nacl_flags, mode);
121 0 : if (0 != NaClHostDescOpen(hd, resource_locator, nacl_flags, mode)) {
122 0 : NaClLog(LOG_INFO,
123 : "NaClResourceNaClAppFileOpen: NaClHostDescOpen failed\n");
124 0 : goto done;
125 : }
126 0 : if (!NaClDescIoDescCtor(did, hd)) {
127 0 : NaClLog(LOG_INFO,
128 : "NaClResourceNaClAppFileOpen: NaClDescIoDescCtor failed\n");
129 0 : (void) NaClHostDescClose(hd);
130 0 : goto done;
131 : }
132 0 : hd = NULL; /* ownership passed into did */
133 0 : rv = (struct NaClDesc *) did; /* success */
134 0 : did = NULL;
135 0 : done:
136 0 : free(hd);
137 0 : free(did);
138 0 : NaClLog(4, "NaClResourceNaClAppFileOpen returning 0x%"NACL_PRIxPTR"\n",
139 : (uintptr_t) rv);
140 0 : return rv;
141 : }
142 :
143 : /*
144 : * We don't bother to make it a singleton postmessage device. Thread
145 : * safety is handled when the device object gets the lock to use the
146 : * reverse channel.
147 : */
148 : static struct NaClDesc *NaClResourceNaClAppDevOpen(
149 : struct NaClResource *vself,
150 : char const *resource_locator,
151 : int nacl_flags,
152 : int mode,
153 0 : int allow_debug) {
154 0 : struct NaClResourceNaClApp *self = (struct NaClResourceNaClApp *) vself;
155 0 : struct NaClDescPostMessage *ndpm = NULL;
156 :
157 0 : if (self->nap->resource_phase != NACL_RESOURCE_PHASE_REV_CHAN
158 : || !allow_debug) {
159 0 : return NULL;
160 : }
161 :
162 0 : if (0 == strcmp(resource_locator, NACL_RESOURCE_DEV_POSTMESSAGE_LOCATOR)) {
163 : /* disallow O_RDONLY or O_RDWR */
164 0 : if ((NACL_ABI_O_ACCMODE & nacl_flags) != NACL_ABI_O_WRONLY) {
165 0 : return NULL;
166 : }
167 : /* allow O_CREAT, O_APPEND, and O_TRUNC */
168 : UNREFERENCED_PARAMETER(mode); /* ignored; O_CREAT doesn't create. */
169 :
170 0 : ndpm = malloc(sizeof *ndpm);
171 0 : if (NULL != ndpm) {
172 0 : if (!NaClDescPostMessageCtor(ndpm, self->nap)) {
173 0 : free(ndpm);
174 0 : ndpm = NULL;
175 : }
176 : }
177 0 : if (NULL == ndpm) {
178 0 : NaClLog(LOG_ERROR,
179 : "NaClResourceNaClAppDevOpen(%s) failed\n",
180 : resource_locator);
181 : }
182 : }
183 0 : return (struct NaClDesc *) ndpm;
184 : }
185 :
186 : int NaClResourceNaClAppInit(struct NaClResourceNaClApp *rp,
187 19 : struct NaClApp *nap) {
188 : static struct NaClResourceSchemes const schemes[] = {
189 : {
190 : NACL_RESOURCE_FILE_PREFIX,
191 : 1, /* default scheme */
192 : NaClResourceNaClAppFileOpen,
193 : }, {
194 : NACL_RESOURCE_DEV_PREFIX,
195 : 0, /* not default scheme */
196 : NaClResourceNaClAppDevOpen,
197 : },
198 : };
199 :
200 19 : NaClLog(4, "NaClResourceNaClAppInit -- Ctor with default schemes\n");
201 19 : return NaClResourceNaClAppCtor(rp, schemes, NACL_ARRAY_SIZE(schemes), nap);
202 : }
|