Текущее состояние kdbus

На прошедшем Blackhat нашли возможность получать информацию из Android-приложений, нелегально подсоединившись к Binder (23-страничная статья доступна онлайн). На первый взгляд, это какая-то сомнительная возможность, ведь присоединиться к системной шине, да еще и под произвольным именем, это само по себе непросто - "съесть-то он съест, да кто ж ему даст?". Но есть нюанс! Оказалось (увы, но внутренности Android задокументированы не очень хорошо), что даже внутри приложения Android коммуникации между различными составными частями программы происходят по шине. Поэтому добившись такого подключения, можно заглядывать внутрь приложения, вытаскивая данные. которые само приложение наружу отправлять не будет, обходя таким образом систему безопасности.

Если кто забыл, то Binder, это аналог D-Bus от Google, который уже работает в ядре. Прямо сейчас между Binder и D-Bus / kdbus есть серьезные архитектурные различия, обуславливаемые разными целями обоих решений, о которых с т.з. разработчика вы уже могли слышать. С точки зрения пользователя, существенное различие между двумя системами, это паттерны использования - в Linux обращения к шине D-Bus нечасты (можно подсоединиться утилитой dbus-monitor и оценить порядок величины), а вот Android, как показали исследователи, основывается на message passing, активно используя обмен сообщениями по шине даже внутри приложений (см. выше). Поэтому тема производительности D-Bus до недавних пор была малоинтересной разработчикам (не было особого спроса), а вот производительность в Binder была главной целью, и ради нее был принесен в жертву кое-какой функционал. Сейчас ситуация меняется. Активное использование message passing против традиционной архитектуры (shared libs + приложения, сующие друг другу разное в пайпы и сокеты), это то светлое будущее, к которому мы ведем Linux, невзирая на очаги бессмысленного сопротивления любителей заняться в одиночку юниксвэем. Именно поэтому уже началась работа по осовремениванию D-Bus, и разработчики уже добились успехов. И теперь, несмотря на более современную архитектуру Android по сравнению с "обычным" линуксом, в целом различия между ними уже не выглядят неустранимыми, и работа по реализации Binder поверх kdbus тоже идет.

Но каково текущее положение с kdbus? Наш коллега, известный борец с Linux-сепаратистами, Jon Masters, в своей заметке о ядре 3.17 и текущей разработке, посвятил несколько абзацев и состоянию kdbus:

...
Готовимся к kdbus

Результаты подготовительной работы в рамках реализации kdbus, ядерной реализации D-Bus, уже включены в версию 3.17. D-Bus, это система IPC (Inter-Process Communicaton), изначально разработанная в коммьюнити FreeDesktop и GNOME (сейчас также используется в KDE и Qt4). D-Bus позволяет системным сервисам регистрироваться в некоем глобальном пространстве имен, и затем отправлять и получать сообщения. Сервисы могут быть запущены в ответ на поступающие в их адрес сообщения, как уже работают многие десктопные службы современного Linux. В обычной конфигурации D-Bus запускается, чтобы предоставлять системную шину, по которой общаются системные сервисы, и по шине на каждый пользовательский логин для пользователей. Обычно D-Bus предоставляется демоном dbus-daemon, но ведется работа по переносу части его функций в пожирающий весь системный функционал systemd. И как часть проекта по переносу, идет работа по улучшению его производительность используя ядерный механизм.

Модуль ядра, kdbus, предназначен для уменьшения количества взаимодействий, необходимых для того, чтобы один сервис послал сообщение другому, используя механизм D-Bus. Будучи полностью userspace-решением, от существующих сервисов требуется системный вызов для посылки сообщения, который потом будет обработан (легковесным, но тем не менее) демоном dbus-daemon, и наконец получен требуемым адресатом сообщения после еще нескольких пересылов внутри и наружу ядра. Чтобы не требовать большого числа переключений контекстов между процессами (известных, как "задачи" внутри ядра, kdbus устраняет необходимость в специализированном демоне во многих случаях. Вместо этого сообщения могут быть напрямую посланы и получены по кратчайшему маршруту. В некоторых случаях, однако, может понадобиться более серьезная обработка, так что системный сервис останется, особенно для legacy-приложений.

Для того, чтобы kdbus функционировал, в ядро нужно добавить некоторые изменения (кроме того, что туда надо включить сам kdbus. Эти изменения включают memfd (не так давно добавленный), механизм, которые предоставляет zero-copy разделяемую память между процессами с использованием файловых дескрипторов, как используются традиционные файлы. Рука об руку с этим механизмом идет система file sealing ("запечатывание регионов памяти" для предотвращения их изменений), т.к. необходимо добиться того, чтобы посланное см помощью memfd сообщение можно было разобрать в принимающем процессе без риска того, что посылающий процесс модифицирует сообщение после посылки, прямо в доступной ему области памяти. Как только memfd "запечатан", содержимое не может быть изменено посылающим процессом. Типичная схема посылки сообщения с помощью kdbus происходит следующим образом - отправитель выделяет память получая ее memfd, создает в этой памяти сообщение, запечатывает memfd и отсылает его в kdbus. Т.к. kdbus, это ядерный механизм, то передача будет производиться легко, "zero-copy". Ядро будет использовать несколько классических трюков управления памятью, чтобы напрямую передать массив данных по memfd.
...


Ну это вкратце, как kdbus устроен. Но без потребителей, это будет лишь сложная и забавная погремушка. Первым потребителем kdbus видимо станет systemd, а затем на него может перейти Android. Но уже сейчас у GNOME появились планы по использованию kdbus. Конечно, переход GNOME на kdbus вызовет дополнительные проблемы у устаревших операционок, которые уже еле-еле справляются (несовместимые между собой форки BSD, непопулярные дистрибутивы, неперешедшие до сих пор на systemd). Действительно, некоторые наши коллеги сначала обещали, что GNOME будет поддерживать совместимость с устаревшими системами, без systemd, но сейчас это становится все сложнее и сложнее, и через несколько релизов мы перестанем ее поддерживать.