Asylo
shared_resource_manager.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 Asylo authors
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef ASYLO_PLATFORM_CORE_SHARED_RESOURCE_MANAGER_H_
20 #define ASYLO_PLATFORM_CORE_SHARED_RESOURCE_MANAGER_H_
21 
22 #include <memory>
23 
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/synchronization/mutex.h"
26 #include "asylo/platform/core/shared_name.h"
27 #include "asylo/util/status.h" // IWYU pragma: export
28 
29 namespace asylo {
30 
31 /// A manager object for shared resources.
32 ///
33 /// A manager object responsible for reference-counted untrusted resources which
34 /// are shared between trusted and untrusted code.
35 class SharedResourceManager {
36  public:
37  /// Registers a shared resource and passes ownership to the
38  /// SharedResourceManager.
39  ///
40  /// Registers a shared resource of type T by name and transfers ownership of
41  /// the object to the manager. Managed resources are objects allocated in the
42  /// untrusted partition of the application and are addressable by name from
43  /// trusted code.
44  ///
45  /// Each resource is associated with a reference count, which is initialized
46  /// to one (1) at the time the resource is registered. Resource counts are
47  /// managed explicitly by calls to AcquireResource and ReleaseResource.
48  /// Resources are automatically disposed of and removed from the resource
49  /// table when their reference count reaches zero (0).
50  ///
51  /// \param name The name to register to this resource.
52  /// \param pointer A pointer to a value that this resource owns and will
53  /// dispose of once it is no longer referenced.
54  template <typename T, typename Deleter = std::default_delete<T>>
56  absl::MutexLock lock(&mu_);
57  auto *resource = new ManagedResource<T, Deleter>(name, pointer);
58  return InstallResource(resource);
59  }
60 
61  /// Registers a shared resource owned by that remains owned by the caller.
62  ///
63  /// Has the same behavior as RegisterManagedResource, except that the
64  /// ownership of the resource remains with the caller. This means that that
65  /// the resource will not be deleted by the EnclaveManager when its reference
66  /// count reaches zero (0). This is appropriate for pointers to objects the
67  /// caller owns and would like to make available inside the enclave.
68  /// \param name The name to register to this resource.
69  /// \param pointer A pointer to a value owned by the caller.
70  template <typename T>
72  absl::MutexLock lock(&mu_);
73  auto *resource = new UnmanagedResource<T>(name, pointer);
74  return InstallResource(resource);
75  }
76 
77  /// Acquires a named resource.
78  ///
79  /// Acquires a named resource by incrementing its reference count and
80  /// returning a pointer to an object owned by the EnclaveManager. Returns
81  /// nullptr if the named resource does not exist.
82  template <typename T>
83  T *AcquireResource(const SharedName &name) {
84  absl::MutexLock lock(&mu_);
85  auto it = shared_resources_.find(name);
86  if (it == shared_resources_.end()) {
87  return nullptr;
88  }
89  it->second->reference_count++;
90  return static_cast<T *>(it->second->get());
91  }
92 
93  /// Releases a named resource.
94  ///
95  /// Releases a named resource by decrementing its reference count. Removes it
96  /// from the resource table and delegates finalization to its resource handle
97  /// when the reference count reaches zero (0). Returns false if the named
98  /// resource does not exist.
99  bool ReleaseResource(const SharedName &name);
100 
101  private:
102  // Implements a handle wrapping a pointer to a shared resource. This is
103  // provided to allow different resource types to implement their own cleanup
104  // strategy via an appropriate virtual destructor implementation.
105  struct ResourceHandle {
106  ResourceHandle(const SharedName &name)
107  : resource_name(name), reference_count(1) {}
108  virtual ~ResourceHandle() = default;
109 
110  // Fetches a raw pointer to the managed resource.
111  virtual void *get() = 0;
112 
113  // Releases the resource from the wrapper. After this call, the lifetime of
114  // the resource if no longer managed by the ResourceHandle.
115  virtual void release() = 0;
116 
117  SharedName resource_name;
118  int reference_count;
119  };
120 
121  // A resource owned by the EnclaveManager.
122  template <typename T, typename Deleter>
123  struct ManagedResource : public ResourceHandle {
124  ManagedResource(const SharedName &name, T *pointer)
125  : ResourceHandle(name), resource(pointer) {}
126  void *get() override { return static_cast<void *>(resource.get()); }
127  void release() override { resource.release(); }
128  std::unique_ptr<T, Deleter> resource;
129  };
130 
131  // A handle for a resource that is not owned by the EnclaveManager.
132  template <typename T>
133  struct UnmanagedResource : public ResourceHandle {
134  UnmanagedResource(const SharedName &name, T *pointer)
135  : ResourceHandle(name), resource(pointer) {}
136  void *get() override { return static_cast<void *>(resource); }
137  void release() override {}
138  T *resource;
139  };
140 
141  // Installs a entry into shared_resources_. Returns failure and deletes the
142  // passed resource handle if the provided name is already in use.
143  Status InstallResource(ResourceHandle *handle)
144  ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
145 
146  absl::Mutex mu_;
147  absl::flat_hash_map<SharedName, std::unique_ptr<ResourceHandle>,
148  SharedName::Hash, SharedName::Eq>
149  shared_resources_;
150 };
151 
152 } // namespace asylo
153 
154 #endif // ASYLO_PLATFORM_CORE_SHARED_RESOURCE_MANAGER_H_
T * AcquireResource(const SharedName &name)
Acquires a named resource.
Definition: shared_resource_manager.h:83
Status RegisterUnmanagedResource(const SharedName &name, T *pointer)
Registers a shared resource owned by that remains owned by the caller.
Definition: shared_resource_manager.h:71
ABSL_CONST_INIT const char kStatusMoveAssignmentMsg[]
bool ReleaseResource(const SharedName &name)
Releases a named resource.
Status RegisterManagedResource(const SharedName &name, T *pointer)
Registers a shared resource and passes ownership to the SharedResourceManager.
Definition: shared_resource_manager.h:55