blob: 7d46f5df7cade37f94285e82859239462fb05c6c [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 "topaz/runtime/dart_runner/mapped_resource.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <trace/event.h>
#include <zircon/status.h>
#include "topaz/runtime/dart/utils/inlines.h"
#include "topaz/runtime/dart/utils/vmo.h"
#include "topaz/runtime/dart_runner/logging.h"
namespace dart_runner {
bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
const std::string& path,
MappedResource& resource,
bool executable) {
TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
// openat of a path with a leading '/' ignores the namespace fd.
dart_utils::Check(path[0] != '/', LOG_TAG);
fuchsia::mem::Buffer resource_vmo;
if (namespc == nullptr) {
if (!dart_utils::VmoFromFilename(path, &resource_vmo)) {
return false;
}
} else {
auto root_dir = fdio_ns_opendir(namespc);
if (root_dir < 0) {
return false;
}
if (!dart_utils::VmoFromFilenameAt(root_dir, path, &resource_vmo)) {
return false;
}
}
if (executable) {
// VmoFromFilenameAt will return VMOs without ZX_RIGHT_EXECUTE,
// so we need replace_as_executable to be able to map them as
// ZX_VM_PERM_EXECUTE.
// TODO(mdempsky): Update comment once SEC-42 is fixed.
zx_status_t status =
resource_vmo.vmo.replace_as_executable(zx::handle(), &resource_vmo.vmo);
if (status != ZX_OK) {
FX_LOGF(ERROR, LOG_TAG, "Failed to make VMO executable: %s",
zx_status_get_string(status));
return false;
}
}
return LoadFromVmo(path, std::move(resource_vmo), resource, executable);
}
bool MappedResource::LoadFromVmo(const std::string& path,
fuchsia::mem::Buffer resource_vmo,
MappedResource& resource, bool executable) {
if (resource_vmo.size == 0) {
return true;
}
uint32_t flags = ZX_VM_PERM_READ;
if (executable) {
flags |= ZX_VM_PERM_EXECUTE;
}
uintptr_t addr;
zx_status_t status = zx::vmar::root_self()->map(
0, resource_vmo.vmo, 0, resource_vmo.size, flags, &addr);
if (status != ZX_OK) {
FX_LOGF(ERROR, LOG_TAG, "Failed to map %s: %s", path.c_str(),
zx_status_get_string(status));
return false;
}
resource.address_ = reinterpret_cast<void*>(addr);
resource.size_ = resource_vmo.size;
return true;
}
MappedResource::~MappedResource() {
if (address_ != nullptr) {
zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
address_ = nullptr;
size_ = 0;
}
}
} // namespace dart_runner