1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mapped_resource.h"
6
7 #include <fcntl.h>
8 #include <lib/trace/event.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <zircon/status.h>
12
13 #include "flutter/fml/logging.h"
14 #include "logging.h"
15 #include "runtime/dart/utils/inlines.h"
16 #include "runtime/dart/utils/vmo.h"
17
18 namespace dart_runner {
19
LoadFromNamespace(fdio_ns_t * namespc,const std::string & path,MappedResource & resource,bool executable)20 bool MappedResource::LoadFromNamespace(fdio_ns_t* namespc,
21 const std::string& path,
22 MappedResource& resource,
23 bool executable) {
24 TRACE_DURATION("dart", "LoadFromNamespace", "path", path);
25
26 // openat of a path with a leading '/' ignores the namespace fd.
27 dart_utils::Check(path[0] != '/', LOG_TAG);
28
29 fuchsia::mem::Buffer resource_vmo;
30 if (namespc == nullptr) {
31 if (!dart_utils::VmoFromFilename(path, &resource_vmo)) {
32 return false;
33 }
34 } else {
35 auto root_dir = fdio_ns_opendir(namespc);
36 if (root_dir < 0) {
37 FML_LOG(ERROR) << "Failed to open namespace directory";
38 return false;
39 }
40
41 bool result = dart_utils::VmoFromFilenameAt(root_dir, path, &resource_vmo);
42 close(root_dir);
43 if (!result) {
44 return result;
45 }
46 }
47
48 if (executable) {
49 // VmoFromFilenameAt will return VMOs without ZX_RIGHT_EXECUTE,
50 // so we need replace_as_executable to be able to map them as
51 // ZX_VM_PERM_EXECUTE.
52 // TODO(mdempsky): Update comment once SEC-42 is fixed.
53 zx_status_t status =
54 resource_vmo.vmo.replace_as_executable(zx::handle(), &resource_vmo.vmo);
55 if (status != ZX_OK) {
56 FML_LOG(ERROR) << "Failed to make VMO executable: "
57 << zx_status_get_string(status);
58 return false;
59 }
60 }
61
62 return LoadFromVmo(path, std::move(resource_vmo), resource, executable);
63 }
64
LoadFromVmo(const std::string & path,fuchsia::mem::Buffer resource_vmo,MappedResource & resource,bool executable)65 bool MappedResource::LoadFromVmo(const std::string& path,
66 fuchsia::mem::Buffer resource_vmo,
67 MappedResource& resource,
68 bool executable) {
69 if (resource_vmo.size == 0) {
70 return true;
71 }
72
73 uint32_t flags = ZX_VM_PERM_READ;
74 if (executable) {
75 flags |= ZX_VM_PERM_EXECUTE;
76 }
77 uintptr_t addr;
78 zx_status_t status = zx::vmar::root_self()->map(
79 0, resource_vmo.vmo, 0, resource_vmo.size, flags, &addr);
80 if (status != ZX_OK) {
81 FML_LOG(ERROR) << "Failed to map " << path << ": "
82 << zx_status_get_string(status);
83
84 return false;
85 }
86
87 resource.address_ = reinterpret_cast<void*>(addr);
88 resource.size_ = resource_vmo.size;
89 return true;
90 }
91
~MappedResource()92 MappedResource::~MappedResource() {
93 if (address_ != nullptr) {
94 zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
95 address_ = nullptr;
96 size_ = 0;
97 }
98 }
99
100 } // namespace dart_runner
101