| 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;
|
| -}
|
|
|