kernel/thread: handle invalid user_thread pointer in user_[un]block_thread

should help with #16736

Change-Id: I103488679b8c352855fbd19405bb30c978cf4457
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3613
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Jérôme Duval
2021-01-09 18:12:18 +00:00
committed by waddlesplash
parent 62826a0665
commit d12e6085a0
+26 -18
View File
@@ -2969,10 +2969,16 @@ user_unblock_thread(thread_id threadID, status_t status)
InterruptsSpinLocker locker(thread->scheduler_lock); InterruptsSpinLocker locker(thread->scheduler_lock);
set_ac(); status_t waitStatus;
if (thread->user_thread->wait_status > 0) { if (user_memcpy(&waitStatus, &thread->user_thread->wait_status,
thread->user_thread->wait_status = status; sizeof(waitStatus)) < B_OK) {
clear_ac(); return B_BAD_ADDRESS;
}
if (waitStatus > 0) {
if (user_memcpy(&thread->user_thread->wait_status, &status,
sizeof(status)) < B_OK) {
return B_BAD_ADDRESS;
}
// Even if the user_thread->wait_status was > 0, it may be the // Even if the user_thread->wait_status was > 0, it may be the
// case that this thread is actually blocked on something else. // case that this thread is actually blocked on something else.
@@ -2980,9 +2986,7 @@ user_unblock_thread(thread_id threadID, status_t status)
&& thread->wait.type == THREAD_BLOCK_TYPE_USER) { && thread->wait.type == THREAD_BLOCK_TYPE_USER) {
thread_unblock_locked(thread, status); thread_unblock_locked(thread, status);
} }
} else }
clear_ac();
return B_OK; return B_OK;
} }
@@ -3709,13 +3713,13 @@ _user_block_thread(uint32 flags, bigtime_t timeout)
ThreadLocker threadLocker(thread); ThreadLocker threadLocker(thread);
// check, if already done // check, if already done
set_ac(); status_t waitStatus;
if (thread->user_thread->wait_status <= 0) { if (user_memcpy(&waitStatus, &thread->user_thread->wait_status,
status_t status = thread->user_thread->wait_status; sizeof(waitStatus)) < B_OK) {
clear_ac(); return B_BAD_ADDRESS;
return status;
} }
clear_ac(); if (waitStatus <= 0)
return waitStatus;
// nope, so wait // nope, so wait
thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_USER, NULL); thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_USER, NULL);
@@ -3729,13 +3733,17 @@ _user_block_thread(uint32 flags, bigtime_t timeout)
// Interruptions or timeouts can race with other threads unblocking us. // Interruptions or timeouts can race with other threads unblocking us.
// Favor a wake-up by another thread, i.e. if someone changed the wait // Favor a wake-up by another thread, i.e. if someone changed the wait
// status, use that. // status, use that.
set_ac(); status_t oldStatus;
status_t oldStatus = thread->user_thread->wait_status; if (user_memcpy(&oldStatus, &thread->user_thread->wait_status,
sizeof(oldStatus)) < B_OK) {
return B_BAD_ADDRESS;
}
if (oldStatus > 0) { if (oldStatus > 0) {
thread->user_thread->wait_status = status; if (user_memcpy(&thread->user_thread->wait_status, &status,
clear_ac(); sizeof(status)) < B_OK) {
return B_BAD_ADDRESS;
}
} else { } else {
clear_ac();
status = oldStatus; status = oldStatus;
} }