| Index: src/trusted/plugin/srpc/shared_memory.cc
|
| ===================================================================
|
| --- src/trusted/plugin/srpc/shared_memory.cc (revision 2716)
|
| +++ src/trusted/plugin/srpc/shared_memory.cc (working copy)
|
| @@ -1,298 +0,0 @@
|
| -/*
|
| - * Copyright 2008 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 <signal.h>
|
| -#include <string.h>
|
| -
|
| -#include "native_client/src/include/checked_cast.h"
|
| -#include "native_client/src/include/nacl_platform.h"
|
| -
|
| -#include "native_client/src/shared/platform/nacl_host_desc.h"
|
| -#include "native_client/src/shared/imc/nacl_imc.h"
|
| -
|
| -#include "native_client/src/trusted/plugin/srpc/plugin.h"
|
| -#include "native_client/src/trusted/plugin/srpc/shared_memory.h"
|
| -#include "native_client/src/trusted/plugin/srpc/utility.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/internal_errno.h"
|
| -#include "native_client/src/trusted/service_runtime/sel_util.h"
|
| -
|
| -
|
| -namespace {
|
| -
|
| -bool RpcRead(void* obj, plugin::SrpcParams* params) {
|
| - plugin::SharedMemory* shared_memory =
|
| - reinterpret_cast<plugin::SharedMemory*>(obj);
|
| - uint32_t offset;
|
| - uint32_t len;
|
| -
|
| - // TODO(gregoryd) - the old code was able to handle both ints and doubles
|
| - // it should be handled in the marshalling code,
|
| - // otherwise the call will be rejected
|
| - if (params->ins()[0]->tag == NACL_SRPC_ARG_TYPE_DOUBLE) {
|
| - offset = static_cast<uint32_t>(params->ins()[0]->u.dval);
|
| - } else {
|
| - offset = static_cast<uint32_t>(params->ins()[0]->u.ival);
|
| - }
|
| -
|
| - if (params->ins()[1]->tag == NACL_SRPC_ARG_TYPE_DOUBLE) {
|
| - len = static_cast<uint32_t>(params->ins()[1]->u.dval);
|
| - } else {
|
| - len = static_cast<uint32_t>(params->ins()[1]->u.ival);
|
| - }
|
| -
|
| - // Ensure we will access valid addresses.
|
| - if (NULL == shared_memory->shm_addr()) {
|
| - params->set_exception_string("Shared memory not mapped");
|
| - return false;
|
| - }
|
| - if (offset + len < offset) {
|
| - params->set_exception_string("Offset + length overflows");
|
| - return false;
|
| - }
|
| - if (offset + len > shared_memory->shm_size()) {
|
| - params->set_exception_string(
|
| - "Offset + length overlaps end of shared memory");
|
| - return false;
|
| - }
|
| -
|
| - // TODO(mseaborn): Change this function to use ByteStringAsUTF8().
|
| - // UTF-8 encoding may result in a 2x size increase at the most.
|
| - // TODO(sehr): should we do a pre-scan to get the real size?
|
| - uint32_t utf8_buffer_len = 2 * len;
|
| - if ((utf8_buffer_len < len) ||
|
| - (utf8_buffer_len + 1 < utf8_buffer_len)) {
|
| - // Unsigned overflow.
|
| - params->set_exception_string("len too large to hold requested UTF8 chars");
|
| - return false;
|
| - }
|
| -
|
| - char* ret_string = reinterpret_cast<char*>(malloc(utf8_buffer_len + 1));
|
| - if (NULL == ret_string) {
|
| - params->set_exception_string("out of memory");
|
| - return false;
|
| - }
|
| -
|
| - unsigned char* shm_addr =
|
| - reinterpret_cast<unsigned char*>(shared_memory->shm_addr()) + offset;
|
| - unsigned char* out = reinterpret_cast<unsigned char*>(ret_string);
|
| - // NPAPI wants length to be the number of bytes, not UTF-8 characters.
|
| - for (unsigned int i = 0; i < len; ++i) {
|
| - unsigned char c = *shm_addr;
|
| - if (c < 128) {
|
| - // Code results in a one byte encoding
|
| - *out = c;
|
| - ++out;
|
| - } else {
|
| - // Code results in a two byte encoding
|
| - out[0] = 0xc0 | (c >> 6);
|
| - out[1] = 0x80 | (c & 0x3f);
|
| - out += 2;
|
| - }
|
| - ++shm_addr;
|
| - }
|
| - // Terminate the result string with 0.
|
| - *out = 0;
|
| -
|
| - params->outs()[0]->tag = NACL_SRPC_ARG_TYPE_STRING;
|
| - params->outs()[0]->u.sval = ret_string;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool RpcWrite(void* obj, plugin::SrpcParams* params) {
|
| - plugin::SharedMemory* shared_memory =
|
| - reinterpret_cast<plugin::SharedMemory*>(obj);
|
| - uint32_t offset;
|
| - uint32_t len;
|
| -
|
| - // TODO(gregoryd) - the old code was able to handle both ints and doubles
|
| - // it should be handled in the marshalling code,
|
| - // otherwise the call will be rejected
|
| - if (params->ins()[0]->tag == NACL_SRPC_ARG_TYPE_DOUBLE) {
|
| - offset = static_cast<uint32_t>(params->ins()[0]->u.dval);
|
| - } else {
|
| - offset = static_cast<uint32_t>(params->ins()[0]->u.ival);
|
| - }
|
| -
|
| - if (params->ins()[1]->tag == NACL_SRPC_ARG_TYPE_DOUBLE) {
|
| - len = static_cast<uint32_t>(params->ins()[1]->u.dval);
|
| - } else {
|
| - len = static_cast<uint32_t>(params->ins()[1]->u.ival);
|
| - }
|
| -
|
| - // Ensure we will access valid addresses.
|
| - if (NULL == shared_memory->shm_addr()) {
|
| - params->set_exception_string("Shared memory not mapped");
|
| - return false;
|
| - }
|
| - if (offset + len < offset) {
|
| - params->set_exception_string("Offset + length overflows");
|
| - return false;
|
| - }
|
| - if (offset + len > shared_memory->shm_size()) {
|
| - params->set_exception_string(
|
| - "Offset + length overlaps end of shared memory");
|
| - return false;
|
| - }
|
| -
|
| - // The input is a JavaScript string, which must consist of UFT-8
|
| - // characters with character codes between 0 and 255 inclusive.
|
| - NaClSrpcArg* str_param = params->ins()[2];
|
| - const unsigned char* str =
|
| - reinterpret_cast<unsigned const char*>(str_param->u.sval);
|
| - uint32_t utf_bytes = nacl::saturate_cast<uint32_t>(strlen(str_param->u.sval));
|
| - unsigned char* shm_addr =
|
| - reinterpret_cast<unsigned char*>(shared_memory->shm_addr()) + offset;
|
| -
|
| - // TODO(mseaborn): Change this function to use ByteStringFromUTF8().
|
| - for (unsigned int i = 0; i < len;) {
|
| - unsigned char c1 = str[0];
|
| - unsigned char c2 = 0;
|
| -
|
| - // Check that we are still pointing into the JavaScript string we were
|
| - // passed.
|
| - if (i >= utf_bytes) {
|
| - return false;
|
| - }
|
| - // Process the byte in the string as UTF-8 characters.
|
| - if (c1 & 0x80) {
|
| - // str[1] will not access out of bounds because sval is a NUL-terminated
|
| - // sequence of bytes. However, NUL would fail the content test just
|
| - // below, so failing here seems a good thing anyway.
|
| - if (i == len - 1) {
|
| - return false;
|
| - }
|
| - c2 = str[1];
|
| - // Assert two byte encoding.
|
| - // The first character must contain 110xxxxxb and the
|
| - // second must contain 10xxxxxxb.
|
| - if (((c1 & 0xc3) != c1) || ((c2 & 0xbf) != c2)) {
|
| - params->set_exception_string("Bad utf8 character value");
|
| - return false;
|
| - }
|
| - *shm_addr = (c1 << 6) | (c2 & 0x3f);
|
| - str += 2;
|
| - i += 2;
|
| - } else {
|
| - // One-byte encoding.
|
| - *shm_addr = c1;
|
| - ++str;
|
| - ++i;
|
| - }
|
| - ++shm_addr;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace plugin {
|
| -
|
| -void SharedMemory::LoadMethods() {
|
| - AddMethodCall(RpcRead, "read", "ii", "s");
|
| - AddMethodCall(RpcWrite, "write", "iis", "");
|
| -}
|
| -
|
| -bool SharedMemory::Init(Plugin* plugin,
|
| - nacl::DescWrapper* wrapper,
|
| - off_t length) {
|
| - bool allocated_memory = false;
|
| -
|
| - if (NULL == wrapper) {
|
| - // Creating a new object by size
|
| - size_t size = static_cast<size_t>(length);
|
| - // The Map virtual function rounds up to the nearest AllocPage.
|
| - size_t rounded_size = NaClRoundAllocPage(size);
|
| - wrapper = plugin->wrapper_factory()->MakeShm(rounded_size);
|
| - if (NULL == wrapper) {
|
| - return false;
|
| - }
|
| -
|
| - PLUGIN_PRINTF(("SharedMemory::Init(%p, 0x%08x)\n",
|
| - static_cast<void*>(plugin),
|
| - static_cast<unsigned>(length)));
|
| - // Now allocate the object through the canonical factory and return.
|
| - allocated_memory = true;
|
| - }
|
| -
|
| - if (!DescBasedHandle::Init(plugin, wrapper)) {
|
| - if (allocated_memory) {
|
| - wrapper->Delete();
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - if (0 > wrapper->Map(&addr_, &size_)) {
|
| - // BUG: we are leaking the shared memory object here.
|
| - return false;
|
| - }
|
| -
|
| - LoadMethods();
|
| - return true;
|
| -}
|
| -
|
| -SharedMemory* SharedMemory::New(Plugin* plugin, nacl::DescWrapper* wrapper) {
|
| - PLUGIN_PRINTF(("SharedMemory::New()\n"));
|
| -
|
| - SharedMemory* shared_memory = new(std::nothrow) SharedMemory();
|
| - if (shared_memory == NULL || !shared_memory->Init(plugin, wrapper, 0)) {
|
| - return NULL;
|
| - }
|
| - return shared_memory;
|
| -}
|
| -
|
| -SharedMemory* SharedMemory::New(Plugin* plugin, off_t length) {
|
| - PLUGIN_PRINTF(("SharedMemory::New()\n"));
|
| -
|
| - SharedMemory* shared_memory = new(std::nothrow) SharedMemory();
|
| - if (shared_memory == NULL || !shared_memory->Init(plugin, NULL, length)) {
|
| - return NULL;
|
| - }
|
| - return shared_memory;
|
| -}
|
| -
|
| -SharedMemory::SharedMemory() : handle_(0),
|
| - addr_(NULL),
|
| - size_(0) {
|
| - PLUGIN_PRINTF(("SharedMemory::SharedMemory(%p)\n",
|
| - static_cast<void*>(this)));
|
| -}
|
| -
|
| -SharedMemory::~SharedMemory() {
|
| - PLUGIN_PRINTF(("SharedMemory::~SharedMemory(%p)\n",
|
| - static_cast<void*>(this)));
|
| -
|
| - // Invalidates are called by Firefox in abitrary order. Hence, the plugin
|
| - // could have been freed/trashed before we get invalidated. Therefore, we
|
| - // cannot use the effp_ member of the plugin object.
|
| - // TODO(sehr): fix the resulting address space leak.
|
| - // Free the memory that was mapped to the descriptor.
|
| - // shared_memory->desc_->vtbl->Unmap(shared_memory->desc_,
|
| - // shared_memory->plugin_->effp_,
|
| - // shared_memory->addr_,
|
| - // shared_memory->size_);
|
| - // After invalidation, the browser does not respect reference counting,
|
| - // so we shut down here what we can and prevent attempts to shut down
|
| - // other linked structures in Deallocate.
|
| -
|
| - // Free the memory that was mapped to the descriptor.
|
| - // if (desc() && plugin_) {
|
| - // desc()->vtbl->Unmap(desc(),
|
| - // plugin_->effp_,
|
| - // addr_,
|
| - // size_);
|
| - // }
|
| - // TODO(sehr): is there a missing delete desc() here?
|
| - // TODO(gregoryd): in addition, should we unref the descriptor if it was
|
| - // constructed during the initialization of this object?
|
| -}
|
| -
|
| -} // namespace plugin
|
|
|