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 <kernel/event.h>
10 #include <kernel/thread.h>
11 #include <object/dispatcher.h>
12 #include <object/futex_context.h>
13 #include <object/handle.h>
14 #include <object/job_policy.h>
15 #include <object/thread_dispatcher.h>
16 #include <vm/vm_aspace.h>
17 
18 #include <zircon/syscalls/object.h>
19 #include <zircon/types.h>
20 #include <fbl/array.h>
21 #include <fbl/canary.h>
22 #include <fbl/intrusive_double_list.h>
23 #include <fbl/mutex.h>
24 #include <fbl/name.h>
25 #include <fbl/ref_counted.h>
26 #include <fbl/ref_ptr.h>
27 #include <fbl/string_piece.h>
28 
29 class JobDispatcher;
30 
31 class ProcessDispatcher final
32     : public SoloDispatcher<ProcessDispatcher, ZX_DEFAULT_PROCESS_RIGHTS> {
33 public:
34     static zx_status_t Create(
35         fbl::RefPtr<JobDispatcher> job, fbl::StringPiece name, uint32_t flags,
36         fbl::RefPtr<Dispatcher>* dispatcher, zx_rights_t* rights,
37         fbl::RefPtr<VmAddressRegionDispatcher>* root_vmar_disp,
38         zx_rights_t* root_vmar_rights);
39 
40     // Traits to belong in the parent job's raw list.
41     struct JobListTraitsRaw {
node_stateJobListTraitsRaw42         static fbl::DoublyLinkedListNodeState<ProcessDispatcher*>& node_state(
43             ProcessDispatcher& obj) {
44             return obj.dll_job_raw_;
45         }
46     };
47 
48     // Traits to belong in the parent job's list.
49     struct JobListTraits {
node_stateJobListTraits50         static fbl::SinglyLinkedListNodeState<fbl::RefPtr<ProcessDispatcher>>& node_state(
51             ProcessDispatcher& obj) {
52             return obj.dll_job_;
53         }
54     };
55 
GetCurrent()56     static ProcessDispatcher* GetCurrent() {
57         ThreadDispatcher* current = ThreadDispatcher::GetCurrent();
58         DEBUG_ASSERT(current);
59         return current->process();
60     }
61 
62     // Dispatcher implementation
get_type()63     zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_PROCESS; }
64     void on_zero_handles() final;
65     zx_koid_t get_related_koid() const final;
66 
67     ~ProcessDispatcher() final;
68 
69     // state of the process
70     enum class State {
71         INITIAL, // initial state, no thread present in process
72         RUNNING, // first thread has started and is running
73         DYING,   // process has delivered kill signal to all threads
74         DEAD,    // all threads have entered DEAD state and potentially dropped refs on process
75     };
76 
77     // Performs initialization on a newly constructed ProcessDispatcher
78     // If this fails, then the object is invalid and should be deleted
79     zx_status_t Initialize();
80 
81     // Maps a |handle| to an integer which can be given to usermode as a
82     // handle value. Uses Handle->base_value() plus additional mixing.
83     zx_handle_t MapHandleToValue(const Handle* handle) const;
84     zx_handle_t MapHandleToValue(const HandleOwner& handle) const;
85 
86     // Maps a handle value into a Handle as long we can verify that
87     // it belongs to this process. Use |skip_policy = true| for testing that
88     // a handle is valid without potentially triggering a job policy exception.
89     Handle* GetHandleLocked(
90         zx_handle_t handle_value, bool skip_policy = false) TA_REQ(handle_table_lock_);
91 
92     // Adds |handle| to this process handle list. The handle->process_id() is
93     // set to this process id().
94     void AddHandle(HandleOwner handle);
95     void AddHandleLocked(HandleOwner handle) TA_REQ(handle_table_lock_);
96 
97     // Removes the Handle corresponding to |handle_value| from this process
98     // handle list.
99     HandleOwner RemoveHandle(zx_handle_t handle_value);
100     HandleOwner RemoveHandleLocked(zx_handle_t handle_value) TA_REQ(handle_table_lock_);
101 
102     // Remove all of an array of |user_handles| from the
103     // process. Returns ZX_OK if all of the handles were removed, and
104     // returns ZX_ERR_BAD_HANDLE if any were not.
105     zx_status_t RemoveHandles(user_in_ptr<const zx_handle_t> user_handles,
106                               size_t num_handles);
107 
108     // Get the dispatcher corresponding to this handle value.
109     template <typename T>
GetDispatcher(zx_handle_t handle_value,fbl::RefPtr<T> * dispatcher)110     zx_status_t GetDispatcher(zx_handle_t handle_value,
111                               fbl::RefPtr<T>* dispatcher) {
112         return GetDispatcherAndRights(handle_value, dispatcher, nullptr);
113     }
114 
115     // Get the dispatcher and the rights corresponding to this handle value.
116     template <typename T>
GetDispatcherAndRights(zx_handle_t handle_value,fbl::RefPtr<T> * dispatcher,zx_rights_t * out_rights)117     zx_status_t GetDispatcherAndRights(zx_handle_t handle_value,
118                                        fbl::RefPtr<T>* dispatcher,
119                                        zx_rights_t* out_rights) {
120         fbl::RefPtr<Dispatcher> generic_dispatcher;
121         auto status = GetDispatcherInternal(handle_value, &generic_dispatcher, out_rights);
122         if (status != ZX_OK)
123             return status;
124         *dispatcher = DownCastDispatcher<T>(&generic_dispatcher);
125         if (!*dispatcher)
126             return ZX_ERR_WRONG_TYPE;
127         return ZX_OK;
128     }
129 
130     // Get the dispatcher corresponding to this handle value, after
131     // checking that this handle has the desired rights.
132     // Returns the rights the handle currently has.
133     template <typename T>
GetDispatcherWithRights(zx_handle_t handle_value,zx_rights_t desired_rights,fbl::RefPtr<T> * dispatcher,zx_rights_t * out_rights)134     zx_status_t GetDispatcherWithRights(zx_handle_t handle_value,
135                                         zx_rights_t desired_rights,
136                                         fbl::RefPtr<T>* dispatcher,
137                                         zx_rights_t* out_rights) {
138         fbl::RefPtr<Dispatcher> generic_dispatcher;
139         auto status = GetDispatcherWithRightsInternal(handle_value,
140                                                       desired_rights,
141                                                       &generic_dispatcher,
142                                                       out_rights);
143         if (status != ZX_OK)
144             return status;
145         *dispatcher = DownCastDispatcher<T>(&generic_dispatcher);
146         if (!*dispatcher)
147             return ZX_ERR_WRONG_TYPE;
148         return ZX_OK;
149     }
150 
151     // Get the dispatcher corresponding to this handle value, after
152     // checking that this handle has the desired rights.
153     template <typename T>
GetDispatcherWithRights(zx_handle_t handle_value,zx_rights_t desired_rights,fbl::RefPtr<T> * dispatcher)154     zx_status_t GetDispatcherWithRights(zx_handle_t handle_value,
155                                         zx_rights_t desired_rights,
156                                         fbl::RefPtr<T>* dispatcher) {
157         return GetDispatcherWithRights(handle_value, desired_rights, dispatcher, nullptr);
158     }
159 
160     zx_koid_t GetKoidForHandle(zx_handle_t handle_value);
161 
162     bool IsHandleValid(zx_handle_t handle_value);
163     bool IsHandleValidNoPolicyCheck(zx_handle_t handle_value);
164 
165     // Calls the provided
166     // |zx_status_t func(zx_handle_t, zx_rights_t, fbl::RefPtr<Dispatcher>)|
167     // on every handle owned by the process. Stops if |func| returns an error,
168     // returning the error value.
169     template <typename T>
ForEachHandle(T func)170     zx_status_t ForEachHandle(T func) const {
171         Guard<fbl::Mutex> guard{&handle_table_lock_};
172         for (const auto& handle : handles_) {
173             const Dispatcher* dispatcher = handle.dispatcher().get();
174             zx_status_t s = func(MapHandleToValue(&handle), handle.rights(),
175                                  dispatcher);
176             if (s != ZX_OK) {
177                 return s;
178             }
179         }
180         return ZX_OK;
181     }
182 
183     // accessors
handle_table_lock()184     Lock<fbl::Mutex>* handle_table_lock() TA_RET_CAP(handle_table_lock_) {
185         return &handle_table_lock_;
186     }
futex_context()187     FutexContext* futex_context() { return &futex_context_; }
188     State state() const;
aspace()189     fbl::RefPtr<VmAspace> aspace() { return aspace_; }
190     fbl::RefPtr<JobDispatcher> job();
191 
192     void get_name(char out_name[ZX_MAX_NAME_LEN]) const final;
193     zx_status_t set_name(const char* name, size_t len) final;
194 
195     void Exit(int64_t retcode) __NO_RETURN;
196     void Kill();
197 
198     // Suspends the process.
199     //
200     // Suspending a process causes all child threads to suspend as well as any new children
201     // that are added until the process is resumed. Suspend() is cumulative, so the process
202     // will only resume once Resume() has been called an equal number of times.
203     //
204     // Returns ZX_OK on success, or ZX_ERR_BAD_STATE iff the process is dying or dead.
205     zx_status_t Suspend();
206     void Resume();
207 
208     // Syscall helpers
209     zx_status_t GetInfo(zx_info_process_t* info);
210     zx_status_t GetStats(zx_info_task_stats_t* stats);
211     // NOTE: Code outside of the syscall layer should not typically know about
212     // user_ptrs; do not use this pattern as an example.
213     zx_status_t GetAspaceMaps(user_out_ptr<zx_info_maps_t> maps, size_t max,
214                               size_t* actual, size_t* available);
215     zx_status_t GetVmos(user_out_ptr<zx_info_vmo_t> vmos, size_t max,
216                         size_t* actual, size_t* available);
217 
218     zx_status_t GetThreads(fbl::Array<zx_koid_t>* threads);
219 
220     // exception handling support
221     zx_status_t SetExceptionPort(fbl::RefPtr<ExceptionPort> eport);
222     // Returns true if a port had been set.
223     bool ResetExceptionPort(bool debugger);
224     fbl::RefPtr<ExceptionPort> exception_port();
225     fbl::RefPtr<ExceptionPort> debugger_exception_port();
226     // |eport| can either be the process's eport or that of any parent job.
227     void OnExceptionPortRemoval(const fbl::RefPtr<ExceptionPort>& eport);
228 
229     // The following two methods can be slow and inaccurate and should only be
230     // called from diagnostics code.
231     uint32_t ThreadCount() const;
232     size_t PageCount() const;
233 
234     // Look up a process given its koid.
235     // Returns nullptr if not found.
236     static fbl::RefPtr<ProcessDispatcher> LookupProcessById(zx_koid_t koid);
237 
238     // Look up a thread in this process given its koid.
239     // Returns nullptr if not found.
240     fbl::RefPtr<ThreadDispatcher> LookupThreadById(zx_koid_t koid);
241 
242     uintptr_t get_debug_addr() const;
243     zx_status_t set_debug_addr(uintptr_t addr);
244 
245     // Checks the |condition| against the parent job's policy.
246     //
247     // Must be called by syscalls before performing an action represented by an
248     // ZX_POL_xxxxx condition. If the return value is ZX_OK the action can
249     // proceed; otherwise, the process is not allowed to perform the action,
250     // and the status value should be returned to the usermode caller.
251     //
252     // E.g., in sys_channel_create:
253     //
254     //     auto up = ProcessDispatcher::GetCurrent();
255     //     zx_status_t res = up->QueryBasicPolicy(ZX_POL_NEW_CHANNEL);
256     //     if (res != ZX_OK) {
257     //         // Channel creation denied by the calling process's
258     //         // parent job's policy.
259     //         return res;
260     //     }
261     //     // Ok to create a channel.
262     zx_status_t QueryBasicPolicy(uint32_t condition) const;
263 
264     // Returns this job's timer slack policy.
265     TimerSlack GetTimerSlackPolicy() const;
266 
267     // return a cached copy of the vdso code address or compute a new one
vdso_code_address()268     uintptr_t vdso_code_address() {
269         if (unlikely(vdso_code_address_ == 0)) {
270             return cache_vdso_code_address();
271         }
272         return vdso_code_address_;
273     }
274 
275 private:
276     // compute the vdso code address and store in vdso_code_address_
277     uintptr_t cache_vdso_code_address();
278 
279     // The diagnostic code is allow to know about the internals of this code.
280     friend void DumpProcessList();
281     friend void KillProcess(zx_koid_t id);
282     friend void DumpProcessMemoryUsage(const char* prefix, size_t min_pages);
283 
284     ProcessDispatcher(fbl::RefPtr<JobDispatcher> job, fbl::StringPiece name, uint32_t flags);
285 
286     ProcessDispatcher(const ProcessDispatcher&) = delete;
287     ProcessDispatcher& operator=(const ProcessDispatcher&) = delete;
288 
289 
290     zx_status_t GetDispatcherInternal(zx_handle_t handle_value, fbl::RefPtr<Dispatcher>* dispatcher,
291                                       zx_rights_t* rights);
292 
293     zx_status_t GetDispatcherWithRightsInternal(zx_handle_t handle_value, zx_rights_t desired_rights,
294                                                 fbl::RefPtr<Dispatcher>* dispatcher_out,
295                                                 zx_rights_t* out_rights);
296 
297     void OnProcessStartForJobDebugger(ThreadDispatcher *t);
298 
299     // Thread lifecycle support.
300     //
301     // |suspended| indicates whether the parent process is currently suspended or not. If true,
302     // the child thread must increment its own suspend count by one and transition to suspend.
303     friend class ThreadDispatcher;
304     zx_status_t AddThread(ThreadDispatcher* t, bool initial_thread, bool* suspended);
305     void RemoveThread(ThreadDispatcher* t);
306 
307     void SetStateLocked(State) TA_REQ(get_lock());
308     void FinishDeadTransition();
309 
310     // Kill all threads
311     void KillAllThreadsLocked() TA_REQ(get_lock());
312 
313     // TODO(dbort): Add "canary_.Assert()" calls to methods.
314     fbl::Canary<fbl::magic("PROC")> canary_;
315 
316     // the enclosing job
317     const fbl::RefPtr<JobDispatcher> job_;
318 
319     // Policy set by the Job during Create().
320     //
321     // It is critical that this field is immutable as it will be accessed without synchronization.
322     const JobPolicy policy_;
323 
324     // The process can belong to either of these lists independently.
325     fbl::DoublyLinkedListNodeState<ProcessDispatcher*> dll_job_raw_;
326     fbl::SinglyLinkedListNodeState<fbl::RefPtr<ProcessDispatcher>> dll_job_;
327 
328     uint32_t handle_rand_ = 0;
329 
330     // list of threads in this process
331     using ThreadList = fbl::DoublyLinkedList<ThreadDispatcher*, ThreadDispatcher::ThreadListTraits>;
332     ThreadList thread_list_ TA_GUARDED(get_lock());
333 
334     // our address space
335     fbl::RefPtr<VmAspace> aspace_;
336 
337     // our list of handles
338     mutable DECLARE_MUTEX(ProcessDispatcher) handle_table_lock_; // protects |handles_|.
339     fbl::DoublyLinkedList<Handle*> handles_ TA_GUARDED(handle_table_lock_);
340 
341     FutexContext futex_context_;
342 
343     // our state
344     State state_ TA_GUARDED(get_lock()) = State::INITIAL;
345 
346     // Suspend count; incremented on Suspend(), decremented on Resume().
347     int suspend_count_ TA_GUARDED(get_lock()) = 0;
348 
349     // True if FinishDeadTransition has been called.
350     // This is used as a sanity check only.
351     bool completely_dead_ = false;
352 
353     // process return code
354     int64_t retcode_ = 0;
355 
356     // Exception ports bound to the process.
357     fbl::RefPtr<ExceptionPort> exception_port_ TA_GUARDED(get_lock());
358     fbl::RefPtr<ExceptionPort> debugger_exception_port_ TA_GUARDED(get_lock());
359 
360     // This is the value of _dl_debug_addr from ld.so.
361     // See third_party/ulib/musl/ldso/dynlink.c.
362     uintptr_t debug_addr_ TA_GUARDED(get_lock()) = 0;
363 
364     // This is a cache of aspace()->vdso_code_address().
365     uintptr_t vdso_code_address_ = 0;
366 
367     // The user-friendly process name. For debug purposes only. That
368     // is, there is no mechanism to mint a handle to a process via this name.
369     fbl::Name<ZX_MAX_NAME_LEN> name_;
370 };
371 
372 const char* StateToString(ProcessDispatcher::State state);
373