mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
LibCore: Avoid UAF on the array of wake pipes when exit()ing
If exit() is called on a thread with an EventLoop in the stack, the ThreadData storing the array of wake pipes will be destroyed first. Threads can still take a strong reference to the EventLoop after that, and will read the fds from freed memory. Instead, take a copy of the write fd, and swallow EBADF when writing to it, since that only indicates that the thread and event loop are exiting, so there's nothing to do with the wake.
This commit is contained in:
committed by
Gregory Bertilson
parent
75aac67adb
commit
04e95b7dd1
Notes:
github-actions[bot]
2026-03-02 23:09:14 +00:00
Author: https://github.com/Zaggy1024 Commit: https://github.com/LadybirdBrowser/ladybird/commit/04e95b7dd16 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8197 Reviewed-by: https://github.com/gmta ✅
@@ -263,6 +263,9 @@ struct ThreadData {
|
||||
|
||||
~ThreadData()
|
||||
{
|
||||
close(wake_pipe_fds[0]);
|
||||
close(wake_pipe_fds[1]);
|
||||
|
||||
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
|
||||
s_thread_data.remove(s_thread_id);
|
||||
}
|
||||
@@ -286,8 +289,9 @@ struct ThreadData {
|
||||
}
|
||||
|
||||
EventLoopImplementationUnix::EventLoopImplementationUnix()
|
||||
: m_wake_pipe_fds(ThreadData::the().wake_pipe_fds)
|
||||
: m_wake_pipe_write_fd(ThreadData::the().wake_pipe_fds[1])
|
||||
{
|
||||
VERIFY(m_wake_pipe_write_fd >= 0);
|
||||
}
|
||||
|
||||
EventLoopImplementationUnix::~EventLoopImplementationUnix() = default;
|
||||
@@ -317,7 +321,12 @@ void EventLoopImplementationUnix::quit(int code)
|
||||
void EventLoopImplementationUnix::wake()
|
||||
{
|
||||
int wake_event = 0;
|
||||
MUST(Core::System::write(m_wake_pipe_fds[1], { &wake_event, sizeof(wake_event) }));
|
||||
auto result = Core::System::write(m_wake_pipe_write_fd, { &wake_event, sizeof(wake_event) });
|
||||
// EBADF here just indicates that the ThreadData is destroyed, so we must be exiting the thread.
|
||||
// Ignore it.
|
||||
if (result.is_error() && result.error().code() == EBADF)
|
||||
return;
|
||||
MUST(move(result));
|
||||
}
|
||||
|
||||
void EventLoopManagerUnix::wait_for_events(EventLoopImplementation::PumpMode mode)
|
||||
|
||||
Reference in New Issue
Block a user