diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 1cbf9162e8a..0151de28476 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -179,10 +179,14 @@ bool Thread::SelectBlocker::should_unblock(Thread& thread, time_t now_sec, long auto& process = thread.process(); for (int fd : m_select_read_fds) { + if (!process.m_fds[fd]) + continue; if (process.m_fds[fd].description->can_read()) return true; } for (int fd : m_select_write_fds) { + if (!process.m_fds[fd]) + continue; if (process.m_fds[fd].description->can_write()) return true; } diff --git a/Tests/Kernel/null-deref-close-during-select.cpp b/Tests/Kernel/null-deref-close-during-select.cpp new file mode 100644 index 00000000000..907c6506161 --- /dev/null +++ b/Tests/Kernel/null-deref-close-during-select.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +int pipefds[2]; + +int main(int, char**) +{ + pipe(pipefds); + + pthread_t tid; + pthread_create( + &tid, nullptr, [](void*) -> void* { + sleep(1); + printf("ST: close()\n"); + close(pipefds[1]); + pthread_exit(nullptr); + return nullptr; + }, + nullptr); + + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(pipefds[1], &rfds); + + printf("MT: select()\n"); + int rc = select(pipefds[1] + 1, &rfds, nullptr, nullptr, nullptr); + if (rc < 0) { + perror("select"); + return 1; + } + + printf("ok\n"); + return 0; +}