1 // Copyright 2016 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #pragma once
8 
9 #include <fbl/arena.h>
10 #include <fbl/atomic.h>
11 #include <fbl/intrusive_double_list.h>
12 #include <fbl/macros.h>
13 #include <fbl/mutex.h>
14 #include <fbl/ref_ptr.h>
15 #include <kernel/lockdep.h>
16 #include <stdint.h>
17 #include <zircon/types.h>
18 
19 class Dispatcher;
20 class Handle;
21 
22 // HandleOwner wraps a Handle in a unique_ptr-like object that has single
23 // ownership of the Handle and deletes it whenever it falls out of scope.
24 class HandleOwner {
25 public:
26     HandleOwner() = default;
HandleOwner(decltype (nullptr))27     HandleOwner(decltype(nullptr)) : h_(nullptr) {}
28 
HandleOwner(Handle * h)29     explicit HandleOwner(Handle* h) : h_(h) {}
30 
31     HandleOwner(const HandleOwner&) = delete;
32     HandleOwner& operator=(const HandleOwner&) = delete;
33 
HandleOwner(HandleOwner && other)34     HandleOwner(HandleOwner&& other) : h_(other.release()) {}
35 
36     HandleOwner& operator=(HandleOwner&& other) {
37         reset(other.release());
38         return *this;
39     }
40 
~HandleOwner()41     ~HandleOwner() {
42         Destroy();
43     }
44 
45     Handle* operator->() const {
46         return h_;
47     }
48 
get()49     Handle* get() const {
50         return h_;
51     }
52 
release()53     Handle* release() {
54         Handle* h = h_;
55         h_ = nullptr;
56         return h;
57     }
58 
reset(Handle * h)59     void reset(Handle* h) {
60         Destroy();
61         h_ = h;
62     }
63 
swap(HandleOwner & other)64     void swap(HandleOwner& other) {
65         Handle* h = h_;
66         h_ = other.h_;
67         other.h_ = h;
68     }
69 
70     explicit operator bool() const { return h_ != nullptr; }
71 
72 private:
73     // Defined inline below.
74     inline void Destroy();
75 
76     Handle* h_ = nullptr;
77 };
78 
79 // A Handle is how a specific process refers to a specific Dispatcher.
80 class Handle final : public fbl::DoublyLinkedListable<Handle*> {
81 public:
82     // The handle arena's mutex. This is public since it protects
83     // other things like |Dispatcher::handle_count_|.
84     DECLARE_SINGLETON_MUTEX(ArenaLock);
85 
86     // Returns the Dispatcher to which this instance points.
dispatcher()87     const fbl::RefPtr<Dispatcher>& dispatcher() const { return dispatcher_; }
88 
89     // Returns the process that owns this instance. Used to guarantee
90     // that one process may not access a handle owned by a different process.
process_id()91     zx_koid_t process_id() const {
92         return process_id_.load(fbl::memory_order_relaxed);
93     }
94 
95     // Sets the value returned by process_id().
96     void set_process_id(zx_koid_t pid);
97 
98     // Returns the |rights| parameter that was provided when this instance
99     // was created.
rights()100     uint32_t rights() const {
101         return rights_;
102     }
103 
104     // Returns true if this handle has all of the desired rights bits set.
HasRights(zx_rights_t desired)105     bool HasRights(zx_rights_t desired) const {
106         return (rights_ & desired) == desired;
107     }
108 
109     // Returns a value that can be decoded by Handle::FromU32() to derive a
110     // pointer to this instance.  ProcessDispatcher will XOR this with its
111     // |handle_rand_| to create the zx_handle_t value that user space sees.
base_value()112     uint32_t base_value() const {
113         return base_value_;
114     }
115 
116     // To be called once during bring up.
117     static void Init();
118 
119     // Maps an integer obtained by Handle::base_value() back to a Handle.
120     static Handle* FromU32(uint32_t value);
121 
122     // Get the number of outstanding handles for a given dispatcher.
123     static uint32_t Count(const fbl::RefPtr<const Dispatcher>&);
124 
125     // Should only be called by diagnostics.cpp.
126     struct diagnostics {
127         // Dumps internal details of the handle table using printf().
128         static void DumpTableInfo();
129 
130         // Returns the number of outstanding handles.
131         static size_t OutstandingHandles();
132     };
133 
134     // Handle should never be created by anything other than Make or Dup.
135     static HandleOwner Make(
136         fbl::RefPtr<Dispatcher> dispatcher, zx_rights_t rights);
137     static HandleOwner Dup(Handle* source, zx_rights_t rights);
138 
139 private:
140     DISALLOW_COPY_ASSIGN_AND_MOVE(Handle);
141 
142     // Called only by Make.
143     Handle(fbl::RefPtr<Dispatcher> dispatcher,
144            zx_rights_t rights, uint32_t base_value);
145     // Called only by Dup.
146     Handle(Handle* rhs, zx_rights_t rights, uint32_t base_value);
147 
148     // Private subroutines of Make and Dup.
149     static void* Alloc(const fbl::RefPtr<Dispatcher>&, const char* what,
150                        uint32_t* base_value);
151     static uint32_t GetNewBaseValue(void* addr);
152 
153     // Handle should never be destroyed by anything other than Delete,
154     // which uses TearDown to do the actual destruction.
155     ~Handle() = default;
156     void TearDown() TA_EXCL(ArenaLock::Get());
157     void Delete();
158 
159     // Only HandleOwner is allowed to call Delete.
160     friend class HandleOwner;
161 
162     // process_id_ is atomic because threads from different processes can
163     // access it concurrently, while holding different instances of
164     // handle_table_lock_.
165     fbl::atomic<zx_koid_t> process_id_;
166     fbl::RefPtr<Dispatcher> dispatcher_;
167     const zx_rights_t rights_;
168     const uint32_t base_value_;
169 
170     // The handle arena.
171     static fbl::Arena TA_GUARDED(ArenaLock::Get()) arena_;
172 
173     // NOTE! This can return an invalid address.  It must be checked
174     // against the arena bounds before being cast to a Handle*.
IndexToHandle(uint32_t index)175     static uintptr_t IndexToHandle(uint32_t index) TA_NO_THREAD_SAFETY_ANALYSIS {
176         return reinterpret_cast<uintptr_t>(arena_.start()) + index * sizeof(Handle);
177     }
178 
HandleToIndex(Handle * handle)179     static uint32_t HandleToIndex(Handle* handle) TA_NO_THREAD_SAFETY_ANALYSIS {
180         return static_cast<uint32_t>(
181             handle - reinterpret_cast<Handle*>(arena_.start()));
182     }
183 };
184 
185 // This can't be defined directly in the HandleOwner class definition
186 // because Handle is an incomplete type at that point.
Destroy()187 inline void HandleOwner::Destroy() {
188     if (h_)
189         h_->Delete();
190 }
191