2 * Copyright (c) 2013 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.
7 #include "native_client/src/trusted/service_runtime/sys_filename.h"
11 #include "native_client/src/shared/platform/nacl_host_desc.h"
12 #include "native_client/src/shared/platform/nacl_host_dir.h"
13 #include "native_client/src/trusted/desc/nacl_desc_dir.h"
14 #include "native_client/src/trusted/desc/nacl_desc_io.h"
15 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
16 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
17 #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
18 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
19 #include "native_client/src/trusted/service_runtime/nacl_copy.h"
20 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
21 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
25 * NaClOpenAclCheck: Is the NaCl app authorized to open this file? The
26 * return value is syscall return convention, so 0 is success and
27 * small negative numbers are negated errno values.
29 int32_t NaClOpenAclCheck(struct NaClApp *nap,
34 * TODO(bsy): provide some minimal authorization check, based on
35 * whether a debug flag is set; eventually provide a data-driven
36 * authorization configuration mechanism, perhaps persisted via
37 * gears. need GUI for user configuration, as well as designing an
38 * appropriate language (with sufficient expressiveness), however.
40 NaClLog(1, "NaClOpenAclCheck(0x%08"NACL_PRIxPTR", %s, 0%o, 0%o)\n",
41 (uintptr_t) nap, path, flags, mode);
42 if (3 < NaClLogGetVerbosity()) {
43 NaClLog(0, "O_ACCMODE: 0%o\n", flags & NACL_ABI_O_ACCMODE);
44 NaClLog(0, "O_RDONLY = %d\n", NACL_ABI_O_RDONLY);
45 NaClLog(0, "O_WRONLY = %d\n", NACL_ABI_O_WRONLY);
46 NaClLog(0, "O_RDWR = %d\n", NACL_ABI_O_RDWR);
47 #define FLOG(VAR, BIT) do {\
48 NaClLog(1, "%s: %s\n", #BIT, (VAR & BIT) ? "yes" : "no");\
50 FLOG(flags, NACL_ABI_O_CREAT);
51 FLOG(flags, NACL_ABI_O_TRUNC);
52 FLOG(flags, NACL_ABI_O_APPEND);
55 if (NaClAclBypassChecks) {
58 return -NACL_ABI_EACCES;
62 * NaClStatAclCheck: Is the NaCl app authorized to stat this pathname? The
63 * return value is syscall return convention, so 0 is success and
64 * small negative numbers are negated errno values.
66 * This is primarily for debug use. File access should be through
67 * SRPC-based file servers.
69 int32_t NaClStatAclCheck(struct NaClApp *nap,
72 "NaClStatAclCheck(0x%08"NACL_PRIxPTR", %s)\n", (uintptr_t) nap, path);
73 if (NaClAclBypassChecks) {
76 return -NACL_ABI_EACCES;
79 static uint32_t CopyPathFromUser(struct NaClApp *nap,
84 * NaClCopyInFromUserZStr may (try to) get bytes that is outside the
85 * app's address space and generate a fault.
87 if (!NaClCopyInFromUserZStr(nap, dest, num_bytes, src)) {
88 if (dest[0] == '\0') {
89 NaClLog(LOG_ERROR, "NaClSys: invalid address for pathname\n");
90 return -NACL_ABI_EFAULT;
93 NaClLog(LOG_ERROR, "NaClSys: pathname string too long\n");
94 return -NACL_ABI_ENAMETOOLONG;
100 int32_t NaClSysOpen(struct NaClAppThread *natp,
104 struct NaClApp *nap = natp->nap;
105 uint32_t retval = -NACL_ABI_EINVAL;
106 char path[NACL_CONFIG_PATH_MAX];
107 nacl_host_stat_t stbuf;
110 NaClLog(3, "NaClSysOpen(0x%08"NACL_PRIxPTR", "
111 "0x%08"NACL_PRIxPTR", 0x%x, 0x%x)\n",
112 (uintptr_t) natp, (uintptr_t) pathname, flags, mode);
114 retval = CopyPathFromUser(nap, path, sizeof path, (uintptr_t) pathname);
118 allowed_flags = (NACL_ABI_O_ACCMODE | NACL_ABI_O_CREAT
119 | NACL_ABI_O_TRUNC | NACL_ABI_O_APPEND);
120 if (0 != (flags & ~allowed_flags)) {
121 NaClLog(LOG_WARNING, "Invalid open flags 0%o, ignoring extraneous bits\n",
123 flags &= allowed_flags;
125 if (0 != (mode & ~0600)) {
126 NaClLog(1, "IGNORING Invalid access mode bits 0%o\n", mode);
130 retval = NaClOpenAclCheck(nap, path, flags, mode);
132 NaClLog(3, "Open ACL check rejected \"%s\".\n", path);
137 * Perform a stat to determine whether the file is a directory.
139 * NB: it is okay for the stat to fail, since the request may be to
142 * There is a race conditions here: between the stat and the
143 * open-as-a-file and open-as-a-dir, the type of the object that the
144 * path refers to can change.
146 retval = NaClHostDescStat(path, &stbuf);
148 /* Windows does not have S_ISDIR(m) macro */
149 if (0 == retval && S_IFDIR == (S_IFDIR & stbuf.st_mode)) {
150 struct NaClHostDir *hd;
152 hd = malloc(sizeof *hd);
154 retval = -NACL_ABI_ENOMEM;
157 retval = NaClHostDirOpen(hd, path);
158 NaClLog(1, "NaClHostDirOpen(0x%08"NACL_PRIxPTR", %s) returned %d\n",
159 (uintptr_t) hd, path, retval);
161 retval = NaClAppSetDescAvail(
162 nap, (struct NaClDesc *) NaClDescDirDescMake(hd));
163 NaClLog(1, "Entered directory into open file table at %d\n",
167 struct NaClHostDesc *hd;
169 hd = malloc(sizeof *hd);
171 retval = -NACL_ABI_ENOMEM;
174 retval = NaClHostDescOpen(hd, path, flags, mode);
176 "NaClHostDescOpen(0x%08"NACL_PRIxPTR", %s, 0%o, 0%o) returned %d\n",
177 (uintptr_t) hd, path, flags, mode, retval);
179 struct NaClDesc *desc = (struct NaClDesc *) NaClDescIoDescMake(hd);
180 if ((flags & NACL_ABI_O_ACCMODE) == NACL_ABI_O_RDONLY) {
182 * Let any read-only open be used for PROT_EXEC mmap
183 * calls. Under -a, the user informally warrants that
184 * files' code segments won't be changed after open.
186 NaClDescSetFlags(desc,
187 NaClDescGetFlags(desc) | NACL_DESC_FLAGS_MMAP_EXEC_OK);
189 retval = NaClAppSetDescAvail(nap, desc);
190 NaClLog(1, "Entered into open file table at %d\n", retval);
197 int32_t NaClSysStat(struct NaClAppThread *natp,
198 const char *pathname,
199 struct nacl_abi_stat *buf) {
200 struct NaClApp *nap = natp->nap;
201 int32_t retval = -NACL_ABI_EINVAL;
202 char path[NACL_CONFIG_PATH_MAX];
203 nacl_host_stat_t stbuf;
206 ("Entered NaClSysStat(0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxPTR","
207 " 0x%08"NACL_PRIxPTR")\n"),
208 (uintptr_t) natp, (uintptr_t) pathname, (uintptr_t) buf);
210 retval = CopyPathFromUser(nap, path, sizeof path, (uintptr_t) pathname);
214 retval = NaClStatAclCheck(nap, path);
219 * Perform a host stat.
221 retval = NaClHostDescStat(path, &stbuf);
223 struct nacl_abi_stat abi_stbuf;
225 retval = NaClAbiStatHostDescStatXlateCtor(&abi_stbuf,
227 if (!NaClCopyOutToUser(nap, (uintptr_t) buf,
228 &abi_stbuf, sizeof abi_stbuf)) {
229 retval = -NACL_ABI_EFAULT;
236 int32_t NaClSysMkdir(struct NaClAppThread *natp,
239 struct NaClApp *nap = natp->nap;
240 char path[NACL_CONFIG_PATH_MAX];
241 int32_t retval = -NACL_ABI_EINVAL;
243 if (!NaClAclBypassChecks) {
244 retval = -NACL_ABI_EACCES;
248 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
252 retval = NaClHostDescMkdir(path, mode);
257 int32_t NaClSysRmdir(struct NaClAppThread *natp,
259 struct NaClApp *nap = natp->nap;
260 char path[NACL_CONFIG_PATH_MAX];
261 int32_t retval = -NACL_ABI_EINVAL;
263 if (!NaClAclBypassChecks) {
264 retval = -NACL_ABI_EACCES;
268 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
272 retval = NaClHostDescRmdir(path);
277 int32_t NaClSysChdir(struct NaClAppThread *natp,
279 struct NaClApp *nap = natp->nap;
280 char path[NACL_CONFIG_PATH_MAX];
281 int32_t retval = -NACL_ABI_EINVAL;
283 if (!NaClAclBypassChecks) {
284 retval = -NACL_ABI_EACCES;
288 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
292 retval = NaClHostDescChdir(path);
297 int32_t NaClSysGetcwd(struct NaClAppThread *natp,
300 struct NaClApp *nap = natp->nap;
301 int32_t retval = -NACL_ABI_EINVAL;
302 char path[NACL_CONFIG_PATH_MAX];
304 if (!NaClAclBypassChecks) {
305 retval = -NACL_ABI_EACCES;
309 if (len >= NACL_CONFIG_PATH_MAX)
310 len = NACL_CONFIG_PATH_MAX - 1;
312 retval = NaClHostDescGetcwd(path, len);
316 if (!NaClCopyOutToUser(nap, buffer, &path, strlen(path) + 1))
317 retval = -NACL_ABI_EFAULT;
323 int32_t NaClSysUnlink(struct NaClAppThread *natp,
325 struct NaClApp *nap = natp->nap;
326 char path[NACL_CONFIG_PATH_MAX];
327 int32_t retval = -NACL_ABI_EINVAL;
329 if (!NaClAclBypassChecks) {
330 retval = -NACL_ABI_EACCES;
334 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
338 retval = NaClHostDescUnlink(path);