From 97f7f7bad59cdd42bf5f504089e5cecd441da3ce Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 23 Feb 2023 20:32:03 -0500 Subject: kernel: be more careful about kernel address keys --- src/core/hle/kernel/k_condition_variable.cpp | 4 ++-- src/core/hle/kernel/k_light_lock.cpp | 2 +- src/core/hle/kernel/k_process.cpp | 2 +- src/core/hle/kernel/k_thread.cpp | 12 +++++++----- src/core/hle/kernel/k_thread.h | 14 ++++++++++++-- 5 files changed, 23 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 8dae78397..f40cf92b1 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -113,7 +113,7 @@ Result KConditionVariable::SignalToAddress(VAddr addr) { // Remove waiter thread. bool has_waiters{}; KThread* const next_owner_thread = - owner_thread->RemoveWaiterByKey(std::addressof(has_waiters), addr); + owner_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); // Determine the next tag. u32 next_value{}; @@ -283,7 +283,7 @@ Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { // Remove waiter thread. bool has_waiters{}; KThread* next_owner_thread = - cur_thread->RemoveWaiterByKey(std::addressof(has_waiters), addr); + cur_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); // Update for the next owner thread. u32 next_value{}; diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index b922a67a5..14cb615da 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -91,7 +91,7 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { // Get the next owner. bool has_waiters; - KThread* next_owner = owner_thread->RemoveWaiterByKey( + KThread* next_owner = owner_thread->RemoveKernelWaiterByKey( std::addressof(has_waiters), reinterpret_cast(std::addressof(tag))); // Pass the lock to the next owner. diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 514f20ef4..d44f6e921 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -157,7 +157,7 @@ bool KProcess::ReleaseUserException(KThread* thread) { // Remove waiter thread. bool has_waiters{}; - if (KThread* next = thread->RemoveWaiterByKey( + if (KThread* next = thread->RemoveKernelWaiterByKey( std::addressof(has_waiters), reinterpret_cast(std::addressof(exception_thread))); next != nullptr) { diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 2831df733..8c403f5fd 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -933,12 +933,14 @@ void KThread::AddHeldLock(LockWithPriorityInheritanceInfo* lock_info) { held_lock_info_list.push_front(*lock_info); } -KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(VAddr address_key_) { +KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(VAddr address_key_, + bool is_kernel_address_key_) { ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Try to find an existing held lock. for (auto& held_lock : held_lock_info_list) { - if (held_lock.GetAddressKey() == address_key_) { + if (held_lock.GetAddressKey() == address_key_ && + held_lock.GetIsKernelAddressKey() == is_kernel_address_key_) { return std::addressof(held_lock); } } @@ -961,7 +963,7 @@ void KThread::AddWaiterImpl(KThread* thread) { } // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(address_key_); + auto* lock_info = this->FindHeldLock(address_key_, is_kernel_address_key_); if (lock_info == nullptr) { // Create a new lock for the address key. lock_info = @@ -1067,11 +1069,11 @@ void KThread::RemoveWaiter(KThread* thread) { } } -KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, VAddr key) { +KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, VAddr key, bool is_kernel_address_key_) { ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(key); + auto* lock_info = this->FindHeldLock(key, is_kernel_address_key_); if (lock_info == nullptr) { *out_has_waiters = false; return nullptr; diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e09dcbea0..bd125f5f1 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -595,7 +595,13 @@ public: [[nodiscard]] Result GetThreadContext3(std::vector& out); - [[nodiscard]] KThread* RemoveWaiterByKey(bool* out_has_waiters, VAddr key); + [[nodiscard]] KThread* RemoveUserWaiterByKey(bool* out_has_waiters, VAddr key) { + return this->RemoveWaiterByKey(out_has_waiters, key, false); + } + + [[nodiscard]] KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, VAddr key) { + return this->RemoveWaiterByKey(out_has_waiters, key, true); + } [[nodiscard]] VAddr GetAddressKey() const { return address_key; @@ -666,6 +672,9 @@ public: } private: + [[nodiscard]] KThread* RemoveWaiterByKey(bool* out_has_waiters, VAddr key, + bool is_kernel_address_key); + static constexpr size_t PriorityInheritanceCountMax = 10; union SyncObjectBuffer { std::array sync_objects{}; @@ -850,7 +859,7 @@ public: } void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info); - LockWithPriorityInheritanceInfo* FindHeldLock(VAddr address_key); + LockWithPriorityInheritanceInfo* FindHeldLock(VAddr address_key, bool is_kernel_address_key); private: using LockWithPriorityInheritanceInfoList = @@ -926,6 +935,7 @@ public: condvar_key = cv_key; address_key = address; address_key_value = value; + is_kernel_address_key = false; } void ClearConditionVariable() { -- cgit v1.2.3