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_check.h"
12 #include "native_client/src/shared/platform/nacl_host_desc.h"
13 #include "native_client/src/shared/platform/nacl_host_dir.h"
14 #include "native_client/src/trusted/desc/nacl_desc_dir.h"
15 #include "native_client/src/trusted/desc/nacl_desc_io.h"
16 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
17 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
18 #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
19 #include "native_client/src/trusted/service_runtime/include/sys/unistd.h"
20 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
21 #include "native_client/src/trusted/service_runtime/nacl_copy.h"
22 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
23 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
26 static uint32_t CopyPathFromUser(struct NaClApp *nap,
31 * NaClCopyInFromUserZStr may (try to) get bytes that is outside the
32 * app's address space and generate a fault.
34 if (!NaClCopyInFromUserZStr(nap, dest, num_bytes, src)) {
35 if (dest[0] == '\0') {
36 NaClLog(LOG_ERROR, "NaClSys: invalid address for pathname\n");
37 return -NACL_ABI_EFAULT;
40 NaClLog(LOG_ERROR, "NaClSys: pathname string too long\n");
41 return -NACL_ABI_ENAMETOOLONG;
47 int32_t NaClSysOpen(struct NaClAppThread *natp,
51 struct NaClApp *nap = natp->nap;
52 uint32_t retval = -NACL_ABI_EINVAL;
53 char path[NACL_CONFIG_PATH_MAX];
54 nacl_host_stat_t stbuf;
57 NaClLog(3, "NaClSysOpen(0x%08"NACL_PRIxPTR", "
58 "0x%08"NACL_PRIx32", 0x%x, 0x%x)\n",
59 (uintptr_t) natp, pathname, flags, mode);
61 if (!NaClAclBypassChecks) {
62 return -NACL_ABI_EACCES;
65 retval = CopyPathFromUser(nap, path, sizeof path, (uintptr_t) pathname);
69 allowed_flags = (NACL_ABI_O_ACCMODE | NACL_ABI_O_CREAT
70 | NACL_ABI_O_TRUNC | NACL_ABI_O_APPEND);
71 if (0 != (flags & ~allowed_flags)) {
72 NaClLog(LOG_WARNING, "Invalid open flags 0%o, ignoring extraneous bits\n",
74 flags &= allowed_flags;
76 if (0 != (mode & ~0600)) {
77 NaClLog(1, "IGNORING Invalid access mode bits 0%o\n", mode);
82 * Perform a stat to determine whether the file is a directory.
84 * NB: it is okay for the stat to fail, since the request may be to
87 * There is a race conditions here: between the stat and the
88 * open-as-a-file and open-as-a-dir, the type of the object that the
89 * path refers to can change.
91 retval = NaClHostDescStat(path, &stbuf);
93 /* Windows does not have S_ISDIR(m) macro */
94 if (0 == retval && S_IFDIR == (S_IFDIR & stbuf.st_mode)) {
95 struct NaClHostDir *hd;
97 hd = malloc(sizeof *hd);
99 retval = -NACL_ABI_ENOMEM;
102 retval = NaClHostDirOpen(hd, path);
103 NaClLog(1, "NaClHostDirOpen(0x%08"NACL_PRIxPTR", %s) returned %d\n",
104 (uintptr_t) hd, path, retval);
106 retval = NaClAppSetDescAvail(
107 nap, (struct NaClDesc *) NaClDescDirDescMake(hd));
108 NaClLog(1, "Entered directory into open file table at %d\n",
112 struct NaClHostDesc *hd;
114 hd = malloc(sizeof *hd);
116 retval = -NACL_ABI_ENOMEM;
119 retval = NaClHostDescOpen(hd, path, flags, mode);
121 "NaClHostDescOpen(0x%08"NACL_PRIxPTR", %s, 0%o, 0%o) returned %d\n",
122 (uintptr_t) hd, path, flags, mode, retval);
124 struct NaClDesc *desc = (struct NaClDesc *) NaClDescIoDescMake(hd);
125 if ((flags & NACL_ABI_O_ACCMODE) == NACL_ABI_O_RDONLY) {
127 * Let any read-only open be used for PROT_EXEC mmap
128 * calls. Under -a, the user informally warrants that
129 * files' code segments won't be changed after open.
131 NaClDescSetFlags(desc,
132 NaClDescGetFlags(desc) | NACL_DESC_FLAGS_MMAP_EXEC_OK);
134 retval = NaClAppSetDescAvail(nap, desc);
135 NaClLog(1, "Entered into open file table at %d\n", retval);
142 int32_t NaClSysStat(struct NaClAppThread *natp,
145 struct NaClApp *nap = natp->nap;
146 int32_t retval = -NACL_ABI_EINVAL;
147 char path[NACL_CONFIG_PATH_MAX];
148 nacl_host_stat_t stbuf;
151 ("Entered NaClSysStat(0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIx32","
152 " 0x%08"NACL_PRIx32")\n"), (uintptr_t) natp, pathname, nasp);
154 if (!NaClAclBypassChecks) {
155 return -NACL_ABI_EACCES;
158 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
163 * Perform a host stat.
165 retval = NaClHostDescStat(path, &stbuf);
167 struct nacl_abi_stat abi_stbuf;
169 retval = NaClAbiStatHostDescStatXlateCtor(&abi_stbuf, &stbuf);
170 if (!NaClCopyOutToUser(nap, nasp, &abi_stbuf, sizeof abi_stbuf)) {
171 retval = -NACL_ABI_EFAULT;
178 int32_t NaClSysMkdir(struct NaClAppThread *natp,
181 struct NaClApp *nap = natp->nap;
182 char path[NACL_CONFIG_PATH_MAX];
183 int32_t retval = -NACL_ABI_EINVAL;
185 if (!NaClAclBypassChecks) {
186 retval = -NACL_ABI_EACCES;
190 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
194 retval = NaClHostDescMkdir(path, mode);
199 int32_t NaClSysRmdir(struct NaClAppThread *natp,
201 struct NaClApp *nap = natp->nap;
202 char path[NACL_CONFIG_PATH_MAX];
203 int32_t retval = -NACL_ABI_EINVAL;
205 if (!NaClAclBypassChecks) {
206 retval = -NACL_ABI_EACCES;
210 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
214 retval = NaClHostDescRmdir(path);
219 int32_t NaClSysChdir(struct NaClAppThread *natp,
221 struct NaClApp *nap = natp->nap;
222 char path[NACL_CONFIG_PATH_MAX];
223 int32_t retval = -NACL_ABI_EINVAL;
225 if (!NaClAclBypassChecks) {
226 retval = -NACL_ABI_EACCES;
230 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
234 retval = NaClHostDescChdir(path);
239 int32_t NaClSysGetcwd(struct NaClAppThread *natp,
242 struct NaClApp *nap = natp->nap;
243 int32_t retval = -NACL_ABI_EINVAL;
244 char path[NACL_CONFIG_PATH_MAX];
246 if (!NaClAclBypassChecks) {
247 retval = -NACL_ABI_EACCES;
251 if (len >= NACL_CONFIG_PATH_MAX)
252 len = NACL_CONFIG_PATH_MAX - 1;
254 retval = NaClHostDescGetcwd(path, len);
258 if (!NaClCopyOutToUser(nap, buffer, &path, strlen(path) + 1))
259 retval = -NACL_ABI_EFAULT;
265 int32_t NaClSysUnlink(struct NaClAppThread *natp,
267 struct NaClApp *nap = natp->nap;
268 char path[NACL_CONFIG_PATH_MAX];
269 int32_t retval = -NACL_ABI_EINVAL;
271 if (!NaClAclBypassChecks) {
272 retval = -NACL_ABI_EACCES;
276 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
280 retval = NaClHostDescUnlink(path);
281 NaClLog(3, "NaClHostDescUnlink '%s' -> %d\n", path, retval);
286 int32_t NaClSysTruncate(struct NaClAppThread *natp,
288 uint32_t length_addr) {
289 struct NaClApp *nap = natp->nap;
290 char path[NACL_CONFIG_PATH_MAX];
291 int32_t retval = -NACL_ABI_EINVAL;
292 nacl_abi_off_t length;
294 if (!NaClAclBypassChecks)
295 return -NACL_ABI_EACCES;
297 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
301 if (!NaClCopyInFromUser(nap, &length, length_addr, sizeof length))
302 return -NACL_ABI_EFAULT;
304 retval = NaClHostDescTruncate(path, length);
305 NaClLog(3, "NaClHostDescTruncate '%s' %"NACL_PRId64" -> %d\n",
306 path, length, retval);
310 int32_t NaClSysLstat(struct NaClAppThread *natp,
313 struct NaClApp *nap = natp->nap;
314 int32_t retval = -NACL_ABI_EINVAL;
315 char path[NACL_CONFIG_PATH_MAX];
316 nacl_host_stat_t stbuf;
319 ("Entered NaClSysLstat(0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIx32","
320 " 0x%08"NACL_PRIx32")\n"), (uintptr_t) natp, pathname, nasp);
322 if (!NaClAclBypassChecks) {
323 return -NACL_ABI_EACCES;
326 retval = CopyPathFromUser(nap, path, sizeof path, pathname);
331 * Perform a host stat.
333 retval = NaClHostDescLstat(path, &stbuf);
335 struct nacl_abi_stat abi_stbuf;
337 retval = NaClAbiStatHostDescStatXlateCtor(&abi_stbuf, &stbuf);
338 if (!NaClCopyOutToUser(nap, nasp, &abi_stbuf, sizeof abi_stbuf)) {
339 return -NACL_ABI_EFAULT;
345 int32_t NaClSysLink(struct NaClAppThread *natp,
348 struct NaClApp *nap = natp->nap;
349 char oldpath[NACL_CONFIG_PATH_MAX];
350 char newpath[NACL_CONFIG_PATH_MAX];
351 int32_t retval = -NACL_ABI_EINVAL;
353 if (!NaClAclBypassChecks)
354 return -NACL_ABI_EACCES;
356 retval = CopyPathFromUser(nap, oldpath, sizeof oldpath, oldname);
360 retval = CopyPathFromUser(nap, newpath, sizeof newpath, newname);
364 return NaClHostDescLink(oldpath, newpath);
367 int32_t NaClSysRename(struct NaClAppThread *natp,
370 struct NaClApp *nap = natp->nap;
371 char oldpath[NACL_CONFIG_PATH_MAX];
372 char newpath[NACL_CONFIG_PATH_MAX];
373 int32_t retval = -NACL_ABI_EINVAL;
375 if (!NaClAclBypassChecks)
376 return -NACL_ABI_EACCES;
378 retval = CopyPathFromUser(nap, oldpath, sizeof oldpath, oldname);
382 retval = CopyPathFromUser(nap, newpath, sizeof newpath, newname);
386 return NaClHostDescRename(oldpath, newpath);
389 int32_t NaClSysSymlink(struct NaClAppThread *natp,
392 struct NaClApp *nap = natp->nap;
393 char oldpath[NACL_CONFIG_PATH_MAX];
394 char newpath[NACL_CONFIG_PATH_MAX];
395 int32_t retval = -NACL_ABI_EINVAL;
397 if (!NaClAclBypassChecks)
398 return -NACL_ABI_EACCES;
400 retval = CopyPathFromUser(nap, oldpath, sizeof oldpath, oldname);
404 retval = CopyPathFromUser(nap, newpath, sizeof newpath, newname);
408 return NaClHostDescSymlink(oldpath, newpath);
411 int32_t NaClSysChmod(struct NaClAppThread *natp,
413 nacl_abi_mode_t mode) {
414 struct NaClApp *nap = natp->nap;
415 char pathname[NACL_CONFIG_PATH_MAX];
416 int32_t retval = -NACL_ABI_EINVAL;
418 if (!NaClAclBypassChecks)
419 return -NACL_ABI_EACCES;
421 retval = CopyPathFromUser(nap, pathname, sizeof pathname, path);
425 return NaClHostDescChmod(pathname, mode);
428 int32_t NaClSysAccess(struct NaClAppThread *natp,
431 struct NaClApp *nap = natp->nap;
432 char pathname[NACL_CONFIG_PATH_MAX];
433 int32_t retval = -NACL_ABI_EINVAL;
435 if (!NaClAclBypassChecks)
436 return -NACL_ABI_EACCES;
439 * amode must either be F_OK or some combination of the three permission bits.
441 if (amode != NACL_ABI_F_OK
442 && (amode & ~(NACL_ABI_R_OK | NACL_ABI_W_OK | NACL_ABI_X_OK)) != 0)
443 return -NACL_ABI_EINVAL;
445 retval = CopyPathFromUser(nap, pathname, sizeof pathname, path);
449 retval = NaClHostDescAccess(pathname, amode);
450 NaClLog(3, "NaClHostDescAccess '%s' %d -> %d\n", pathname, amode, retval);
454 int32_t NaClSysReadlink(struct NaClAppThread *natp,
458 struct NaClApp *nap = natp->nap;
459 char pathname[NACL_CONFIG_PATH_MAX];
460 char realpath[NACL_CONFIG_PATH_MAX];
461 int32_t retval = -NACL_ABI_EINVAL;
463 if (!NaClAclBypassChecks)
464 return -NACL_ABI_EACCES;
466 if (count >= NACL_CONFIG_PATH_MAX)
467 return -NACL_ABI_EINVAL;
469 retval = CopyPathFromUser(nap, pathname, sizeof pathname, path);
473 retval = NaClHostDescReadlink(pathname, realpath, count);
477 CHECK(retval <= (int32_t)count);
478 if (!NaClCopyOutToUser(nap, buffer, realpath, retval))
479 return -NACL_ABI_EFAULT;
484 int32_t NaClSysUtimes(struct NaClAppThread *natp,
487 struct NaClApp *nap = natp->nap;
488 char pathname[NACL_CONFIG_PATH_MAX];
489 int32_t retval = -NACL_ABI_EINVAL;
491 if (!NaClAclBypassChecks)
492 return -NACL_ABI_EACCES;
494 retval = CopyPathFromUser(nap, pathname, sizeof pathname, path);
499 return -NACL_ABI_EACCES;
501 /* TODO(sbc): implement in terms of NaClHost function. */
502 return -NACL_ABI_ENOSYS;