В ядре Linux устранена следующая уязвимость:
io_uring: отложить сигнализацию eventfd при постановке в очередь из обработчика пробуждения
io_req_local_work_add() сигнализирует о вызове CQ Ring eventfd, когда это
один, чтобы поместить первую запись в ->work_list. Для звонков DEFER_TASKRUN это
Добавление часто выполняется из обработчика пробуждения очереди ожидания, где
удерживается произвольная блокировка очереди ожидания.
eventfd_signal_mask() отказывается повторяться только тогда, когда current->in_eventfd
установлен, но этот бит устанавливается самой функцией eventfd_signal_mask(). Если проснуться
цепочка начинается где-то еще, сигнал выходит на линию и может вернуться обратно
в эполл.
Добавьте IOU_F_TWQ_IN_WAKE, установите его на добавление Task_work, выполненное из трех
обратные вызовы очереди ожидания и использовать их для принудительного спуска io_eventfd_signal() вниз
существующая отсрочка call_rcu_hurry() вместо встроенной сигнализации.
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: io_uring: defer eventfd signaling when queued from a wakeup handler io_req_local_work_add() signals the CQ ring eventfd inline when it is the one to push the first entry onto ->work_list. For DEFER_TASKRUN rings that add is frequently done from a waitqueue wakeup handler, where an arbitrary waitqueue lock is held. eventfd_signal_mask() only refuses to recurse when current->in_eventfd is set, but that bit is set by eventfd_signal_mask() itself. If the wake chain starts somewhere else, signal goes out inline and can feed back into epoll. Add IOU_F_TWQ_IN_WAKE, set it on the task_work add done from the three waitqueue callbacks, and use it to force io_eventfd_signal() down the existing call_rcu_hurry() deferral instead of signaling inline.