Index: src/trusted/gio/gio_shm.c |
diff --git a/src/trusted/gio/gio_shm.c b/src/trusted/gio/gio_shm.c |
deleted file mode 100644 |
index 73941c88f3227ae8aedcf5fb62b7fc3c43529c99..0000000000000000000000000000000000000000 |
--- a/src/trusted/gio/gio_shm.c |
+++ /dev/null |
@@ -1,448 +0,0 @@ |
-/* |
- * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
- * Use of this source code is governed by a BSD-style license that can be |
- * found in the LICENSE file. |
- */ |
- |
-#include <errno.h> |
-#include <string.h> |
- |
-#include "native_client/src/include/portability.h" |
- |
-#include "native_client/src/shared/platform/nacl_check.h" |
-#include "native_client/src/shared/platform/nacl_host_desc.h" |
-#include "native_client/src/shared/platform/nacl_log.h" |
- |
-#include "native_client/src/trusted/gio/gio_shm.h" |
-#include "native_client/src/trusted/service_runtime/include/bits/mman.h" |
-#include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
-#include "native_client/src/trusted/service_runtime/nacl_config.h" |
-#include "native_client/src/trusted/service_runtime/sel_util.h" |
- |
-#include "native_client/src/trusted/desc/nacl_desc_base.h" |
-#include "native_client/src/trusted/desc/nacl_desc_effector_trusted_mem.h" |
-#include "native_client/src/trusted/desc/nacl_desc_imc_shm.h" |
- |
-/* |
- * This code maps in GIO_SHM_WINDOWSIZE bytes at a time for doing |
- * "I/O" from/to the shared memory object. This value must be an |
- * integer multiple of NACL_MAP_PAGESIZE. |
- */ |
-#define GIO_SHM_WINDOWSIZE (16 * NACL_MAP_PAGESIZE) |
- |
-/* |
- * Release current window if it exists, then map in window at the |
- * provided new_window_offset. This is akin to filbuf. |
- * |
- * Preconditions: 0 == (new_win_offset & (NACL_MAP_PAGESIZE - 1)) |
- * new_win_offset < self->shm_sz |
- */ |
-static int NaClGioShmSetWindow(struct NaClGioShm *self, |
- size_t new_win_offset) { |
- uintptr_t map_result; |
- size_t actual_len; |
- |
- NaClLog(4, |
- "NaClGioShmSetWindow: new_win_offset 0x%"NACL_PRIxS"\n", |
- new_win_offset); |
- if (0 != (new_win_offset & (NACL_MAP_PAGESIZE - 1))) { |
- NaClLog(LOG_FATAL, |
- ("NaClGioShmSetWindow: internal error, requested" |
- " new window offset 0x%"NACL_PRIxS" is not aligned.\n"), |
- new_win_offset); |
- } |
- |
- if (new_win_offset >= self->shm_sz) { |
- NaClLog(LOG_FATAL, |
- ("NaClGioShmSetWindow: setting window beyond end of shm object" |
- " offset 0x%"NACL_PRIxS", size 0x%"NACL_PRIxS"\n"), |
- new_win_offset, self->shm_sz); |
- } |
- |
- if (NULL != self->cur_window) { |
- NaClDescUnmapUnsafe(self->shmp, (void *) self->cur_window, |
- self->window_size); |
- } |
- self->cur_window = NULL; |
- self->window_size = 0; |
- |
- /* |
- * The Map virtual function will NOT pad space beyond the end of the |
- * memory mapping object with zero-filled pages. This is done for |
- * user code in nacl_syscall_common.c (NaClSysMmap), and the Map |
- * virtual function exposes the behavioral inconsistencies wrt |
- * allowing but ignoring mapping an offset beyond the end of file |
- * (linux) versus disallowing the mapping (MapViewOfFileEx). |
- * |
- * Here, we know the actual size of the shm object, and can deal |
- * with it. |
- */ |
- actual_len = GIO_SHM_WINDOWSIZE; |
- if (actual_len > self->shm_sz - new_win_offset) { |
- actual_len = self->shm_sz - new_win_offset; |
- } |
- map_result = |
- (*((struct NaClDescVtbl const *) self->shmp->base.vtbl)-> |
- Map)(self->shmp, |
- NaClDescEffectorTrustedMem(), |
- (void *) NULL, |
- actual_len, |
- NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, |
- NACL_ABI_MAP_SHARED, |
- (nacl_off64_t) new_win_offset); |
- NaClLog(4, |
- "NaClGioShmSetWindow: Map returned 0x%"NACL_PRIxPTR"\n", |
- map_result); |
- if (NaClPtrIsNegErrno(&map_result)) { |
- return 0; |
- } |
- |
- self->cur_window = (char *) map_result; |
- self->window_size = actual_len; |
- self->window_offset = new_win_offset; |
- |
- return 1; |
-} |
- |
-static ssize_t NaClGioShmReadOrWrite(struct Gio *vself, |
- void *buf, |
- size_t count, |
- int is_write) { |
- struct NaClGioShm *self = (struct NaClGioShm *) vself; |
- size_t new_window_offset; |
- size_t transfer; |
- size_t window_end; |
- size_t window_remain; |
- size_t sofar; |
- |
- NaClLog(4, |
- ("NaClGioShmReadOrWrite: 0x%"NACL_PRIxPTR"," |
- " 0x%"NACL_PRIxPTR", 0x%"NACL_PRIxS", %d\n"), |
- (uintptr_t) vself, |
- (uintptr_t) buf, |
- count, |
- is_write); |
- sofar = 0; |
- while (count > 0) { |
- NaClLog(4, "NaClGioShmReadOrWrite: count 0x%"NACL_PRIxS"\n", count); |
- if (self->io_offset >= self->shm_sz) { |
- break; |
- } |
- NaClLog(4, " cur_window 0x%"NACL_PRIxPTR"\n", |
- (uintptr_t) self->cur_window); |
- NaClLog(4, " io_offset 0x%"NACL_PRIxS"\n", self->io_offset); |
- NaClLog(4, "window_offset 0x%"NACL_PRIxS"\n", self->window_offset); |
- if (NULL == self->cur_window |
- || self->io_offset < self->window_offset |
- || self->window_offset + self->window_size <= self->io_offset) { |
- /* |
- * io_offset is outside the window. move the window so that |
- * it's within. |
- */ |
- NaClLog(4, "Seek required\n"); |
- |
- new_window_offset = (self->io_offset |
- & (~(((size_t) NACL_MAP_PAGESIZE) - 1))); |
- NaClLog(4, "new_window_offset 0x%"NACL_PRIxS"\n", new_window_offset); |
- CHECK(0 == (new_window_offset & |
- (((size_t) NACL_MAP_PAGESIZE)-1))); |
- if (!NaClGioShmSetWindow(self, new_window_offset)) { |
- if (0 == sofar) { |
- errno = EIO; |
- sofar = -1; |
- } |
- return sofar; |
- } |
- } else { |
- NaClLog(4, "no seek required\n"); |
- } |
- NaClLog(4, " cur_window 0x%"NACL_PRIxPTR"\n", |
- (uintptr_t) self->cur_window); |
- NaClLog(4, " io_offset 0x%"NACL_PRIxS"\n", self->io_offset); |
- NaClLog(4, "window_offset 0x%"NACL_PRIxS"\n", self->window_offset); |
- |
- CHECK(self->window_offset <= self->io_offset); |
- CHECK(self->io_offset < self->window_offset + self->window_size); |
- |
- transfer = count; |
- window_end = self->window_offset + self->window_size; |
- if (window_end > self->shm_sz) { |
- window_end = self->shm_sz; |
- } |
- window_remain = window_end - self->io_offset; |
- |
- NaClLog(4, "remaining in window 0x%"NACL_PRIxS"\n", window_remain); |
- |
- CHECK(window_remain <= GIO_SHM_WINDOWSIZE); |
- |
- if (transfer > window_remain) { |
- transfer = window_remain; |
- } |
- |
- NaClLog(4, "transfer 0x%"NACL_PRIxS"\n", transfer); |
- |
- if (is_write) { |
- NaClLog(4, |
- ("about to \"write\" memcpy(0x%"NACL_PRIxPTR", " |
- " 0x%"NACL_PRIxPTR", 0x%"NACL_PRIxS" bytes)\n"), |
- (uintptr_t) (self->cur_window |
- + (self->io_offset - self->window_offset)), |
- (uintptr_t) buf, |
- transfer); |
- |
- memcpy(self->cur_window + (self->io_offset - self->window_offset), |
- buf, |
- transfer); |
- } else { |
- NaClLog(4, |
- ("about to \"read\" memcpy(0x%"NACL_PRIxPTR", " |
- " 0x%"NACL_PRIxPTR", 0x%"NACL_PRIxS" bytes)\n"), |
- (uintptr_t) buf, |
- (uintptr_t) (self->cur_window |
- + (self->io_offset - self->window_offset)), |
- transfer); |
- |
- memcpy(buf, |
- self->cur_window + (self->io_offset - self->window_offset), |
- transfer); |
- } |
- self->io_offset += transfer; |
- sofar += transfer; |
- |
- buf = (void *)((uintptr_t) buf + transfer); |
- count -= transfer; |
- } |
- |
- return sofar; |
-} |
- |
-static ssize_t NaClGioShmRead(struct Gio *vself, |
- void *buf, |
- size_t count) { |
- return NaClGioShmReadOrWrite(vself, buf, count, 0); |
-} |
- |
-static ssize_t NaClGioShmWrite(struct Gio *vself, |
- const void *buf, |
- size_t count) { |
- return NaClGioShmReadOrWrite(vself, (void *) buf, count, 1); |
-} |
- |
-static off_t NaClGioShmSeek(struct Gio *vself, |
- off_t offset, |
- int whence) { |
- struct NaClGioShm *self = (struct NaClGioShm *) vself; |
- size_t new_pos = (size_t) -1; |
- |
- NaClLog(4, "NaClGioShmSeek(0x%"NACL_PRIxPTR", %ld (0x%lx), %d)\n", |
- (uintptr_t) vself, (long) offset, (long) offset, whence); |
- /* |
- * Note that if sizeof(new_pos) < sizeof(offset), we are dropping |
- * high-order bits and we do not detect this. However, the check |
- * after the switch keeps the values somewhat sane: we will never |
- * set the I/O offset to be outside the range [0, self->shm_sz]. |
- */ |
- switch (whence) { |
- case SEEK_SET: |
- new_pos = (size_t) offset; |
- break; |
- case SEEK_CUR: |
- new_pos = self->io_offset + offset; |
- break; |
- case SEEK_END: |
- new_pos = self->shm_sz + offset; |
- break; |
- } |
- /* allow equality, so setting to the end of file is okay */ |
- if (self->shm_sz < new_pos) { |
- NaClLog(4, " invalid offset\n"); |
- errno = EINVAL; |
- return -1; |
- } |
- NaClLog(4, " setting to %ld (0x%lx)\n", (long) new_pos, (long) new_pos); |
- /* sizeof(off_t) >= sizeof(size_t) */ |
- self->io_offset = new_pos; |
- return (off_t) self->io_offset; |
-} |
- |
-static int NaClGioShmFlush(struct Gio *vself) { |
- UNREFERENCED_PARAMETER(vself); |
- return 0; |
-} |
- |
-static int NaClGioShmClose(struct Gio *vself) { |
- struct NaClGioShm *self = (struct NaClGioShm *) vself; |
- |
- if (NULL != self->cur_window) { |
- NaClDescUnmapUnsafe(self->shmp, (void *) self->cur_window, |
- NACL_MAP_PAGESIZE); |
- } |
- self->cur_window = NULL; |
- |
- if (NULL == self->shmp) { |
- NaClLog(LOG_ERROR, "NaClGioShmClose: double close detected\n"); |
- errno = EIO; |
- return -1; |
- } |
- |
- NaClDescUnref(self->shmp); |
- self->shmp = NULL; /* double close will fault */ |
- return 0; |
-} |
- |
-static void NaClGioShmDtor(struct Gio *vself) { |
- struct NaClGioShm *self = (struct NaClGioShm *) vself; |
- |
- /* |
- * Users of Gio objects are expected to Close then Dtor, but Dtor |
- * should cleanup regardless. |
- */ |
- if (NULL != self->shmp) { |
- if (-1 == (*vself->vtbl->Close)(vself)) { |
- NaClLog(LOG_ERROR, "NaClGioShmDtor: auto Close failed!\n"); |
- } |
- } |
- |
- self->shmp = NULL; |
- self->base.vtbl = NULL; |
-} |
- |
-const struct GioVtbl kNaClGioShmVtbl = { |
- NaClGioShmDtor, |
- NaClGioShmRead, |
- NaClGioShmWrite, |
- NaClGioShmSeek, |
- NaClGioShmFlush, |
- NaClGioShmClose, |
-}; |
- |
- |
-static int NaClGioShmCtorIntern(struct NaClGioShm *self, |
- struct NaClDesc *shmp, |
- size_t shm_size) { |
- struct nacl_abi_stat stbuf; |
- int vfret; |
- int rval = 0; |
- |
- self->base.vtbl = NULL; |
- |
- self->shmp = NULL; |
- self->cur_window = NULL; |
- |
- if (0 != (vfret = (*((struct NaClDescVtbl const *) shmp->base.vtbl)-> |
- Fstat)(shmp, &stbuf))) { |
- NaClLog(1, "NaClGioShmCtorIntern: Fstat virtual function returned %d\n", |
- vfret); |
- goto cleanup; |
- } |
- /* |
- * nacl_abi_off_t is signed 32-bit quantity, but we don't want to |
- * hardwire in that knowledge here. |
- * |
- * size_t is unsigned, and may be 32-bits or 64-bits, depending on |
- * the underlying host OS. |
- * |
- * we want to ensure that the shm's size, as reported by the desc |
- * abstraction and thus is in nacl_abi_off_t, is at least that |
- * claimed by the ctor argument. so, if (as Integers) |
- * |
- * stbuf.nacl_abi_st_size < shm_size |
- * |
- * holds, this is an error. however, the value-preserving cast rule |
- * makes this harder. |
- * |
- * Note that for signed sizes (ssize_t), the kernel ABI generally |
- * only reserve -1 for error, and asking for an I/O operation via a |
- * size_t that would succeed but yield a ssize_t return value that |
- * is negative is okay, since -1 is never valid as an I/O size on a |
- * von Neuman machine (except for a writev where the iov entries |
- * overlap): there just isn't that much data to read/write, when the |
- * instructions also take up space in the process address space. |
- * Whether requiring the programmer to detect this corner case is |
- * advisable is a different argument -- similar to negative ssize_t |
- * sizes, the syscall can just succeed with a partial transfer to |
- * avoid returning -1 on a success, just as we could avoid returning |
- * negative values; in practice, we do the latter, since we often |
- * see code written that tests for syscall error by comparing the |
- * return value to see if it is less than zero, rather than if it is |
- * equal to -1. |
- */ |
- if (stbuf.nacl_abi_st_size < 0) { |
- NaClLog(LOG_ERROR, "NaClGioShmCtorIntern: actual shm size negative\n"); |
- goto cleanup; |
- } |
- if (stbuf.nacl_abi_st_size <= (nacl_abi_off_t) SIZE_T_MAX |
- && (size_t) stbuf.nacl_abi_st_size < shm_size) { |
- NaClLog(LOG_ERROR, |
- "NaClGioShmCtorIntern: claimed shm file size greater than" |
- " actual shm segment size\n"); |
- goto cleanup; |
- } |
- if (OFF_T_MAX < SIZE_T_MAX && (size_t) OFF_T_MAX < shm_size) { |
- NaClLog(LOG_ERROR, |
- ("NaClGioShmCtorIntern: claimed shm file size greater than" |
- " off_t max value, %"NACL_PRId64"\n"), |
- (int64_t) OFF_T_MAX); |
- goto cleanup; |
- } |
- |
- self->shmp = NaClDescRef(shmp); |
- |
- self->io_offset = 0; |
- self->shm_sz = shm_size; |
- self->window_offset = 0; |
- |
- self->base.vtbl = &kNaClGioShmVtbl; |
- |
- if (!NaClGioShmSetWindow(self, 0)) { |
- NaClLog(LOG_ERROR, |
- ("NaClGioShmCtorIntern: initial seek to beginning failed\n")); |
- NaClDescUnref(self->shmp); |
- self->shmp = NULL; |
- self->shm_sz = 0; |
- self->base.vtbl = NULL; |
- goto cleanup; |
- } |
- |
- rval = 1; |
- cleanup: |
- return rval; |
-} |
- |
-int NaClGioShmCtor(struct NaClGioShm *self, |
- struct NaClDesc *shmp, |
- size_t shm_size) { |
- |
- int rv; |
- |
- CHECK(shm_size == NaClRoundAllocPage(shm_size)); |
- |
- rv = NaClGioShmCtorIntern(self, shmp, shm_size); |
- |
- return rv; |
-} |
- |
-int NaClGioShmAllocCtor(struct NaClGioShm *self, |
- size_t shm_size) { |
- struct NaClDescImcShm *shmp; |
- int rv; |
- |
- CHECK(shm_size == NaClRoundAllocPage(shm_size)); |
- |
- shmp = malloc(sizeof *shmp); |
- if (NULL == shmp) { |
- return 0; |
- } |
- if (!NaClDescImcShmAllocCtor(shmp, shm_size, /* executable= */ 0)) { |
- free(shmp); |
- return 0; |
- } |
- |
- rv = NaClGioShmCtorIntern(self, (struct NaClDesc *) shmp, shm_size); |
- NaClDescUnref((struct NaClDesc *) shmp); |
- |
- if (!rv) { |
- free(shmp); |
- } |
- return rv; |
-} |