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:
committed by
waddlesplash
parent
62826a0665
commit
d12e6085a0
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user