LINUX.ORG.RU

Bad Epoll: в Linux и Android нашли уязвимость для получения root-доступа

 , ,

Bad Epoll: в Linux и Android нашли уязвимость для получения root-доступа

1

1

В ядре Linux раскрыта уязвимость Bad Epoll, зарегистрированная как CVE-2026-46242. Она позволяет обычному локальному пользователю без специальных прав повысить привилегии до root. По данным автора исследования Джэёна Чона, проблема затрагивает не только Linux-десктопы и серверы, но и часть Android-устройств на новых версиях ядра — это отдельно подчёркивается в описании Bad Epoll.

Ошибка находится в подсистеме epoll — стандартном механизме Linux для отслеживания множества файловых дескрипторов, сетевых соединений и событий ввода-вывода. Такие механизмы активно используют серверы, браузеры и сетевые сервисы, поэтому просто отключить epoll нельзя. В техническом разборе уязвимость описана как гонка, приводящая к use-after-free: при одновременном закрытии связанных epoll-объектов один поток освобождает внутренние структуры, а другой продолжает к ним обращаться.

Если точнее, проблема проявляется при ситуации, когда один epoll-дескриптор следит за другим, а оба дескриптора закрываются параллельно. После вызова __ep_remove() поле file->f_ep временно обнуляется, и конкурирующий __fput() может решить, что дополнительная очистка уже не нужна. В результате объект struct eventpoll или связанный с ним struct file освобождается слишком рано, но код продолжает работать с указателями на уже освобождённую память. Именно это и даёт атакующему примитив для повреждения памяти ядра.

Для атаки не нужны дополнительные capabilities и не требуются user namespaces — достаточно наличия CONFIG_EPOLL, что делает проблему особенно неприятной для обычных Linux-систем. Согласно первичному отчёту исследователя, баг был внесён в ядро коммитом 58c9b016e128 в 2023 году, а исправлен коммитом a6dc643c693.

Несмотря на очень узкое окно гонки, исследователь подготовил рабочий эксплойт для Google kernelCTF. В описании эксплуатации показано, как ошибка превращается в 8-байтную запись в освобождённую структуру, затем в утечку памяти ядра через /proc/self/fdinfo, перехват file->f_op->poll и ROP-цепочку для получения root. Для цели lts-6.12.67 заявлена надёжность около 99%, для COS — около 98%; Android-эксплойт, по словам автора, ещё находится в работе.

Под ударом находятся ядра, основанные на ветке 6.4 и новее, если в них не перенесено исправление. Старые Android-устройства на ядрах 6.1, включая Pixel 8 и похожие модели, автор считает неуязвимыми. Пользователям и администраторам остаётся единственный нормальный вариант защиты — установить обновление ядра от своего дистрибутива или вендора устройства.

>>> Подробности

★★★★★

Проверено: maxcom ()
Ответ на: комментарий от LightDiver

Ну я немного с иронией сказал не на сто процентов серьёзно, там же смайлик.

А так - можешь прочитать свое первое сообщение в этом треде: каждый раз, когда в сишном коде находят косяк, кто-нибудь из вас считает своим долгом сказать что в расте такого быть не может, потом кто-нибудь в треде показывает что может и вы говорите что вообще-то никто и не говорил что раст идеален

pihter ★★★★★
()
Ответ на: комментарий от pihter

А я там написал конкретно про этот баг. И к слову, ниже там подтвердил реалные баги, которые уже больше 11 лет живут.

Вся проблема в том, что в раст это баг языка, который надо исправлять, а в сишке - штатная работа, которую исправлять нен будут просто потому что это сишка.

С точки зрения раста - это баг раста, а с точки зрения сишки это баг программиста. А программисты не всесильны. Ты рано или поздно устанешь, забудешь, упустишь. Ты не автомат.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от LightDiver

Да я тебя слышу и тред читал, говорю же - с долей шутки

pihter ★★★★★
()
Ответ на: комментарий от firkax

«ядро Линукс майнтейнят лучшие С-шники в мире» + «косяк профнепригодных мультитред-программистов» = ну вы поняли… 😀

next_time ★★★★★
()
Ответ на: комментарий от firkax

«ядро Линукс майнтейнят лучшие С-шники в мире»

«ты сам выдумал»

Нет, ни одного опенсорсного проекта, где мантейнеры - лучше. Иначе, вы могли бы такой проект показать.

next_time ★★★★★
()
Ответ на: комментарий от dynamic_cast

Может, если там где-то file = NULL; или похожее написано, но это легко проверить прочитав код.

firkax ★★★★★
()
Ответ на: комментарий от moonmadness

Сам ты нуб. Это линуксокостыль к closefrom() который есть в нормальных системах. Но работает он корректно, тот процесс даже 100 файлов не открывает, а дескрипторы (по стандартам!) назначаются первый свободный т.е. open() не может открыть дескриптор 10000, если среди 0..9999 есть хоть один свободный.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Есть close_range, есть O_CLOEXEC.

тот процесс даже 100 файлов не открывает

А по коду - 1000, ты зачем врёшь?

Короче, на пересдачу.

moonmadness
()
Ответ на: комментарий от moonmadness

Есть close_range

Ага.

$ man close_range
Нет справочной страницы для close_range
Посмотрел на другом компе
VERSIONS
       close_range() first appeared in Linux 5.9.  Library support was added in glibc 2.34.

STANDARDS
       close_range() is a nonstandard function that is also present on FreeBSD.
Как видно, его много где нет (выше где нет мана - debian 11, ядро 5.10, glibc 2.31, в последнем этой функции ещё нет). А на момент написания того кода - не было вообще нигде в линуксах т.к. ядра были где-то на 3.х-4.х ветках.

есть O_CLOEXEC

Предлагаешь вместо close так же навешивать O_CLOEXEC в цикле? Вопрос слежения за тем, где какие файлы открыты и с какими флагами (если ты про то, что надо во всех open-ах внимательно этот CLOEXEC расставлять) - другой, и я бы не хотел, чтобы данный код от него зависел.

А по коду - 1000, ты зачем врёшь?

Зачем ты тупишь? Число 1000 там выбрано на всякий случай, вреда от этого не будет. Скорее всего же там открыто меньше 10 дескрипторов будет, или вообще только один - коннект к X-серверу (не помню точно, проверять сейчас не буду).

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

fwm = firk’s window manager, simple wm for x11 Что-то эти майнтейнеры 10 лет почти уже пишут, а «complex» не осилили, до сих пор «simple». ЧТД.

next_time ★★★★★
()

посмотрел я устройство этого epoll… ну что сказать.

вот например баг в futex, которого бы не было если бы код обработчика futex был устроен так как я написал: В Linux раскрыта уязвимость GhostLock, позволяющая получить root-доступ (комментарий)

В моей реализации ломаться нечему, если только спинлоками не пренебрегать или заряженная частица залетит на огонек. потому что сломать двусвязный список невозможно.

Так вот, блин. ну это трындец. изумительные люди.

Я так понимаю, что идея такая: epollfd на каждый файл к которому присосался создает структуру epitem которая хранит информацию о том какие события ожидаем, и т.д. ну окей, значит waiter содержит список, а epitem - поля для включения в этот список(пусть это будет epitem.waiter), поля для включения в список целевого fd(epitem.read, epitem.write, etc) и атомарную переменную lock. Списки подперты spinlockами

В lock бит 0 означает что waiter модифицирует epitem, бит 1 - epitem еще ожидает события. закрытие fd это ведь тоже событие, при котором epitem из ожидания переходит в сигнальное состояние. бит 2 - fd модифицирует item.

То есть fd должен, заблокировать свою очередь спинлоком, снять с неё epitem и увидеть там бит 0 - в этом время waiter идет ему навстречу, он поставил бит 0 через операцию CAS, и ждет спинлока на очереди fd. Fd откатывается, снимает спинлок, делаем pause (rep nop), и снова захватывает спинлок очереди. Если waiter закрывался, он уже удалил свой epitem и всё хорошо. Если waiter прошел сразу до спинлока fd, то тогда даже бодалова возле бита 0 не случится.

Если fd обогнал waiterа и поставил бит 2, то waiter на операции CAS увидит этот бит и дождется его снятия. За это время fd атомарно поставит epitem в входную очередь waiterа и пойдет обратно, при этом он еще держит свой спинлок, он снимает бит 2 и waiter проходит до спинлока fd и теперь fd снимает spinlock и засыпает и снова все успешно закрывается.

Да, много атомарных операций. Хреновенько. Но на практике под нагрузкой у вас будет обычно будиться fd, видеть что входной буфер не читан(если он по edge trigged работает), идти навстречу pollfd, и давать ему пинка. А pollfd будет трогать только spinlock своей входящей очереди.

Ну вот скажите мне, почему ведерщики не хотят делать просто и железобетонно? Почему у них всё вот так жутко переусложнено. Каждый раз глядя на офигительные решения ядерщиков мне хочется спросить - ради чего это делается? Я бы понял если бы злые злые спинлоки жрали шину как не в себя, но в линуксе qspinlocks а epitem вообще одномоментно трогают не более чем два ядра. Зачем?

ckotctvo
()
Ответ на: комментарий от ckotctvo

вот например баг в futex, которого бы не было если бы код обработчика futex был устроен так как я написал:

Ну и что же ты им не написал эту свою «умность» тогда, давным давно, когда они писали код, в котором только сейчас обнаружена уязвимость??.. ;))

Твоё «искреннее, неподдельное возмущение» напомнило известное: «Шоб ты был такой умный сейчас, как моя жена потом!..». ;P ;)))

Somebody ★★★★
()
Последнее исправление: Somebody (всего исправлений: 1)
Ответ на: комментарий от ckotctvo

раз они такие инвалиды

«Я, Джон МакМорран, искусный программист, отправил тысячи коммитов в ядро линукс, но стоило мне один раз допустить Race condition…» :)

PeleWin
()
Ответ на: комментарий от ckotctvo

а может мне за них весь линукс написать сразу? раз они такие инвалиды

Давай, написай!.. :))

А то только критиковать и мастера... Да ещё за столетней давности ошибки...

Somebody ★★★★
()

А точно не нейрослоп? Там в коде дичь есть, вроде pin_cpu(0); pin_cpu(1); И прочие интересные штуки, которые мне даже редактор кода подсвечивает. Разбираться сейчас не очень хочется, но такой код не соберётся даже. Что там в бинаре лежит я ХЗ, может майнер. Разверну виртуалку и посмотрю конечно.

peregrine ★★★★★
()
Ответ на: комментарий от ant1

В том виде в каком оно на гитхабе - не заработает. Конечно сейчас начнётся песня про это от скрипт кидди и прочее.

peregrine ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.