1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef BERBERIS_GUEST_OS_PRIMITIVES_GUEST_THREAD_H_ 18 #define BERBERIS_GUEST_OS_PRIMITIVES_GUEST_THREAD_H_ 19 20 #include <csetjmp> // jmp_buf 21 #include <csignal> // stack_t 22 #include <memory> 23 24 #include "berberis/guest_state/guest_addr.h" 25 #include "berberis/guest_state/guest_state_opaque.h" 26 #include "berberis/runtime_primitives/signal_queue.h" 27 28 struct NativeBridgeStaticTlsConfig; 29 30 namespace berberis { 31 32 class GuestSignalActionsTable; 33 34 int CreateNewGuestThread(pthread_t* thread_id, 35 const pthread_attr_t* attr, 36 void* guest_stack, 37 size_t guest_stack_size, 38 size_t guest_guard_size, 39 GuestAddr func, 40 GuestAddr arg); 41 42 pid_t CloneGuestThread(GuestThread* thread, 43 int flags, 44 GuestAddr guest_stack_top, 45 GuestAddr parent_tid, 46 GuestAddr new_tls, 47 GuestAddr child_tid); 48 49 struct GuestArgumentBuffer; 50 void RunGuestPthreadKeyDtor(GuestAddr pc, GuestArgumentBuffer* buf); 51 52 struct GuestCallExecution { 53 GuestCallExecution* parent = nullptr; 54 GuestAddr sp = {}; 55 jmp_buf buf; 56 }; 57 58 // ATTENTION: GuestThread object can only be used by the current thread! 59 class GuestThread { 60 public: 61 static GuestThread* CreatePthread(void* stack, size_t stack_size, size_t guard_size); 62 static GuestThread* CreateClone(const GuestThread* parent, bool share_signal_actions); 63 static GuestThread* CreateForTest(ThreadState* state); 64 static void Destroy(GuestThread* thread); 65 static void Exit(GuestThread* thread, int status); 66 67 // Initialize *current* guest thread. 68 void InitStaticTls(); 69 70 // Configure static tls for *current* *main* guest thread. 71 void ConfigStaticTls(const NativeBridgeStaticTlsConfig* config); 72 73 void ProcessPendingSignals(); 74 75 // Both return *previous* pending signals status (false: disabled, true: enabled). 76 bool ProcessAndDisablePendingSignals(); 77 bool TestAndEnablePendingSignals(); 78 79 void SetSignalFromHost(const siginfo_t& info); 80 GetAttr(GuestAddr * stack_base,size_t * stack_size,size_t * guard_size)81 void GetAttr(GuestAddr* stack_base, size_t* stack_size, size_t* guard_size) const { 82 *stack_base = ToGuestAddr(stack_); 83 *stack_size = stack_size_; 84 *guard_size = guard_size_; 85 } 86 state()87 const ThreadState* state() const { return state_; } state()88 ThreadState* state() { return state_; } 89 guest_call_execution()90 GuestCallExecution* guest_call_execution() const { return guest_call_execution_; } set_guest_call_execution(GuestCallExecution * guest_call_execution)91 void set_guest_call_execution(GuestCallExecution* guest_call_execution) { 92 guest_call_execution_ = guest_call_execution; 93 } 94 95 bool SigAltStack(const stack_t* ss, stack_t* old_ss, int* error); 96 void SwitchToSigAltStack(); 97 bool IsOnSigAltStack() const; 98 DisallowStackUnmap()99 void DisallowStackUnmap() { mmap_size_ = 0; } GetStackTop()100 [[nodiscard]] GuestAddr GetStackTop() const { return stack_top_; } 101 102 // TODO(b/156271630): Refactor to make this private. 103 void* GetHostStackTop() const; 104 GetSignalActionsTable()105 [[nodiscard]] GuestSignalActionsTable* GetSignalActionsTable() { return signal_actions_.get(); } 106 // Use to unshare signal handlers for CLONE_VM without CLONE_SIGHAND. 107 void CloneSignalActionsTableFrom(GuestSignalActionsTable* from_table); 108 109 private: 110 GuestThread() = default; 111 static GuestThread* Create(); 112 113 bool AllocStack(void* stack, size_t stack_size, size_t guard_size); 114 bool AllocShadowCallStack(); 115 bool AllocStaticTls(); 116 117 void ProcessPendingSignalsImpl(); 118 119 // Set the default table for the main process. 120 void SetDefaultSignalActionsTable(); 121 122 // Host stack. Valid for cloned threads only. 123 void* host_stack_ = nullptr; 124 125 // Stack. 126 void* stack_ = nullptr; 127 size_t stack_size_ = 0; 128 size_t guard_size_ = 0; 129 size_t mmap_size_ = 0; 130 GuestAddr stack_top_ = {}; 131 132 void* static_tls_ = nullptr; 133 134 // Shadow call stack. 135 void* scs_region_ = nullptr; 136 GuestAddr scs_base_ = {}; 137 138 ThreadState* state_ = nullptr; 139 140 SignalQueue pending_signals_; 141 // When created with CreateClone guest threads either share or fork signal handlers 142 // from the parent. We implement this using shared_ptr semantics. 143 // When created with CreatePthread guest threads use the default global handlers, 144 // which we should never delete. So we create shared_ptr with void deleter in this case. 145 std::shared_ptr<GuestSignalActionsTable> signal_actions_; 146 147 GuestCallExecution* guest_call_execution_ = nullptr; 148 149 void* sig_alt_stack_ = nullptr; 150 size_t sig_alt_stack_size_ = 0; 151 }; 152 153 } // namespace berberis 154 155 #endif // BERBERIS_GUEST_OS_PRIMITIVES_GUEST_THREAD_H_ 156