Сообщество - GNU/Linux

GNU/Linux

1 217 постов 15 636 подписчиков

Популярные теги в сообществе:

16

Аморальный патч ядра для Intel DRM

Серия Мы не пишем в техподдержку

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

А значит снова пришло время карать и патчить!

Видите эти повторяющиеся записи справа? Так будет выглядеть буфер сообщений ядра (dmesg), если вам не повезло нарваться на этот баг.

Видите эти повторяющиеся записи справа? Так будет выглядеть буфер сообщений ядра (dmesg), если вам не повезло нарваться на этот баг.

Direct Rendering Manager (DRM)

Развитие современных видеокарт пошло по весьма.. сюрреалистичному пути:

производители страстно желают, чтобы выпускаемые устройства имели максимальную совместимость с модными открытыми ОС, но одновременно были закрытыми и неповторимыми, защищенными разнообразными патентами.

То что звучит как чистая шизофрения для человека с техническим образованием, будучи спущенным сверху в виде директивы, еще и подкрепленной серьезным бюджетом, породило на свет такую «хтонь» как binary blob.

Это когда основная часть управляющей устройством логики реализуется в виде специальной прошивки с защитой и обфрускацией — того самого «блоба».

Затем вокруг создается открытая часть ПО, которая линкуется с открытым ядром и/или окружением. А все это вместе и без смущения объявляется как частично беременна открытое решение.

Еще в современном Linux есть такая штука как Direct Rendering Manager:

The Direct Rendering Manager (DRM) is a subsystem of the Linux kernel responsible for interfacing with GPUs of modern video cards

Если кратко и цензурно, то это такая специальная дыра в ядре Linux, для максимально быстрой коммуникации между видеокартой и клиентским ПО, создаваемая в первую очередь ради видеоиг.. скажем так «медийных приложений, требующих аппаратного ускорения графики».

В угаре оптимизации «ядростроители» дошли до использования 3D-ускорения (GPU) даже для отрисовки терминала текстовой консоли (тот самый KMS):

И теперь мы все имеем клевый терминал в разрешении 1920×1280 со сглаживанием шрифтов, на котором что-то разобрать возможно лишь с лупой прищурившись.

Угар портирования

Под натиском волн малолетних специалистов, желающих «гонять игоры» на серверной ОС, не выдержали даже разработчики FreeBSD:

подсистема DRM и KMS, вместе с проприетарными блобами была перенесена из Linux и теперь вовсю используется в FreeBSD.

По-умолчанию, да.

Кстати с тех лет и до сих пор разработка DRM синхронизируется с апстримом (а это внезапно отдельный проект) и ядром Linux, заезжая в сборки FreeBSD вместе со всеми свежими багами в виде срезов исходников. Основная разработка при этом едет дальше.

Нетрудно догадаться, что отправлять багрепорты в проект drm-kmod, курируемый FreeBSD или апстрим ядра Linux при таком подходе равнозначно отправке в «Спортлото».

Заодно во FreeBSD были фактически похоронены альтернативные варианты:

старый текстовый TTY и Xorg-драйвер для видеокарт Intel пока еще существуют и собираются в виде пакетов, но вот их настройку и главное — все сопутствующие сбои в клиентском ПО вы теперь вынуждены отлавливать и исправлять самостоятельно.

«Интерес сообщества» к таким технологиям оказался утрачен.

В качестве вишенки на этом интересном торте из говна, добавлю что всенародно любимый браузер Google Chrome плохо работает без модуля KMS, поэтому заводить весь этот цирк с DRM и KMS приходится даже на откровенно винтажных машинах — ради работающего браузера.

И других вариантов уже фактически нет.

Как-то так выглядит процесс попадания обновлений DRM в FreeBSD. FreeBSD — крайний справа, увы.

Как-то так выглядит процесс попадания обновлений DRM в FreeBSD. FreeBSD — крайний справа, увы.

Оборзевшая техника

Вся эта технологическая «многоножка» из разработчиков Intel с блобами, апстрима ядра Linux с любовью к тотальным переделкам на Rust, на практике приводит к тому, что в бедную FreeBSD постоянно попадают ломающие обновления, отследить и исправить которые «в моменте» не получается.

«Думали что работает» — говорят в таких случаях разработчики FreeBSD и советуют обновиться до -CURRENT версии.

Что для обычных людей и рабочего окружения на машине равносильно старому японскому ритуалу сеппуку, поскольку упадет и сломается вообще все.

В какой-то момент обновление пакета drm-kmod, содержащего тот самый порт подсистемы DRM из ядра Linux принесло мне такое:

drmn0: [drm] ERROR Fault errors on pipe A: 0x00000080

Ну принесло и принесло, ошибок много разных, исправляются далеко не все, дело это небыстрое и так далее.

Но только эта забивала собой весь буфер сообщений ядра!

Сообщений генерировалось настолько много, что dmesg — команда для отображения этого самого буфера, показывала только одну эту бесконечно повторяющуюся ошибку, как на скриншоте в шапке статьи.

При этом ошибка сама по себе довольно известная, страдают как пользователи FreeBSD:

Так и линуксоиды:

Но самое веселое, что баг оказался с рогами и копытами совсем не специфичным и само сообщение означает буквально.. ничего.

Просто «что-то сломалось», в переводе с языка Intel.

Ну что, вы все еще любите проприетарные драйвера от уважаемых производителей?

Беглый поиск в репозитории, в котором ведется разработка подсистемы DRM (напоминаю, она ведется отдельно от ядра Linux) показал, что сообщений с этой ошибкой навалом:

88 репортов, только в этом довольно новом репозитории.

88 репортов, только в этом довольно новом репозитории.

Положение дел

В итоге есть некий баг, с гнездом в районе прошивки видекарты Intel, который (судя по репортам) зверствует проявляет себя самым феерическим образом:

от спама сообщениями до мигания экрана и полного зависания системы.

Исправить своими силами этот баг нельзя, все «workaround» в сети по накалу дичи в рекомендациях напоминают известное шоу «Битва Экстрасенсов»:

нарисуйте ночью в поле пентаграмму из соли, разложите по углам загрузочные диски FreeBSD с 5й по 10ю и громко читайте Changelog задом наперед.

В качестве примера, вот так выглядит одно из решений:

Но есть и хорошие новости.

Хорошие новости

Их целых две.

Первая заключается в том, что в свежих прошивках баг вроде бы исправили на стороне Intel, но чтобы эту прошивку поставить — нужна сборка модуля DRM для FreeBSD 15, которая еще не была выпущена на момент написания статьи:

Еще стоит рассказать, что прямо сейчас идет серьезная работа по перепиливанию DRM как в его основном проекте так и на стороне команды FreeBSD (в -CURRENT), поэтому даже пытаться бекпортировать текущую версию drm-kmod в 14.х ветку не стоит.

Также (к сожалению) не стоит рассматривать переезд на 15ю версию как гарантированное решение, поскольку есть уже открытые багрепорты и оттуда:

Хотя тут явно использовалась 6.1 версия.

Хотя тут явно использовалась 6.1 версия.

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

compat.linuxkpi.i915_disable_power_well="0"

Так что конкретно в моем случае, проблема заключается лишь в бесконечном затирании буфера сообщений ядра этой дурацкой и бессмысленной ошибкой:

drmn0: [drm] ERROR Fault errors on pipe A: 0x00000080

Которую мы и будем сейчас цинично глушить.

Аморальный патч

Разумеется так делать нельзя:

глушить сообщения об ошибках в ваших реальных проектах не стоит.

Хотя если в вашем проекте возникает ситуация, когда сообщение об ошибке генерируется по сотне раз за секунду — ну наверное вопрос уже к вам как к разработчику, допустившему такую дичь.

К счастью FreeBSD проект не мой, прямого доступа к разработчикам нет, а сам процесс разработки подсистемы DRM сильно напоминает известный фильм «Human Centipede».

Где (а главное — зачем) искать концы в такой ситуации не очень понятно, для примера багрепорты по ошибкам DRM в трекере ядра Linux сразу просят перенаправлять в отдельный проект, не разбираясь:

Так что было решено применить военную хитрость просто заглушить сообщение об ошибке в исходниках, пересобрав DRM из портов.

Так выглядит конечный результат после патча:

Как видите буфер ядра не забит этими дурацкими сообщениями.

Как видите буфер ядра не забит этими дурацкими сообщениями.

Поскольку новая 15я по счету версия FreeBSD еще официально не вышла на момент написания статьи, я все еще использую 14.3, где максимально доступная версия DRM для этой ветки — 6.1.

Ее мы и будем жестоко патчить.

В портах она находится в этом каталоге:

/usr/ports/graphics/drm-61-kmod

Поиск в исходном коде по тексту сообщения об ошибке показал, что генерируется она всего в одном месте, в файле i915_irq.c:

drivers/gpu/drm/i915/i915_irq.c

Так выглядит место появления:

..
fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);

if (fault_errors)
drm_err(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
fault_errors);
..

Все что нужно сделать — закомментировать этот блок, начиная с условия.

И все, больше вы это проклятое сообщение не увидите, ура.

Для уменьшения работы мозгом у дорогих читателей, подготовил на этот раз готовый патч, который достаточно положить в специальный каталог и он автоматически применится при сборке drm-kmod.

Надо создать файл patch-i915_irq.c в каталоге /usr/ports/graphics/drm-61-kmod/files, затем вставить туда вот такое содержимое:

*** drivers/gpu/drm/i915/i915_irq.c.orig Tue Nov 18 17:17:39 2025
--- drivers/gpu/drm/i915/i915_irq.c Tue Nov 18 17:17:52 2025
***************
*** 2571,2585 ****

if (iir & gen8_de_pipe_underrun_mask(dev_priv))
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);

fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
! if (fault_errors)
drm_err(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
! fault_errors);
}

if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
master_ctl & GEN8_DE_PCH_IRQ) {
/*
--- 2571,2585 ----

if (iir & gen8_de_pipe_underrun_mask(dev_priv))
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);

fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
! /*if (fault_errors)
drm_err(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
! fault_errors);*/
}

if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&
master_ctl & GEN8_DE_PCH_IRQ) {
/*

Дальше просто перезапускаем сборку:

make clean
make

Проверяем что изменения в файле i915_irq.cприменились и запускаем установку собранного пакета:

make reinstall

После чего перезагружаем систему.

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

Но главное это разумеется хорошее настроение и поставленная на место машина, вернувшаяся к своей основной задаче служить людям.

P.S.

Ошибка действительно дурацкая, еще и наведенная — если дойдет до серьезных сбоев вроде мигания экрана (screen flickering), вы увидите дополнительные сообщения в логах, по которым можно продолжать искать реальную проблему.

Так что вопрос удаления этого сообщения чисто косметический и частично — лишней нагрузки, поскольку генерация сотен таких сообщений в секунду разумеется нагружала систему.

Статья была опубликована на Хабре, оригинал как обычно в нашем блоге.

Показать полностью 10
48

Xfce и «автоматический» диалог

Серия Мы не пишем в техподдержку

Сейчас будет еще одна «трешевая» история из мира открытого ПО, из тех что не рассказывают детям, дамам и сотрудникам ППС.

С добрым утром!

С добрым утром!

XFCE

Xfce это такое очень популярное рабочее окружение (Desktop Environment), яркий представитель опенсорса, который вы неоднократно могли видеть в моих статьях и скриншотах.

Одно время им пользовался даже сам Линус Торвальдс, мотивировав переезд чрезмерным ожирением KDE и уходом в лунатизм разработчиков Gnome.

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

БАГ

Разумеется в Xfce есть баги и недоработки, не такие феерические как например в KDE («Плазма не падает» ага), но тоже временами доставляющие и долгоживущие. Как раз об одном таком «долгожителе» и пойдет наш сегодняшний рассказ.

Как это выглядит в действии:

ноутбук засыпает, ноутбук просыпается и на экране внезапно появляется.. диалог «Display Settings».

Казалось бы мелочь, ну появляется и появляется (причем не на всех ОС и ноутбуках), б‑г с ним и без того проблем навалом.

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

Так что я полез за боевым топором компилятором.

Ресерч

Первый же беглый поиск дал понять, что это не осеннее обострение проблема есть далеко не только у меня, вот например сообщение с официального форума Xfce от 2021 года:

А вот об этой проблеме пишут на форуме Linux Mint:

<a href="https://d.pikabu.ru/story/xfce_i_avtomaticheskiy_dialog_14153311?u=https%3A%2F%2Fforums.linuxmint.com%2Fviewtopic.php%3Ft%3D413429&t=%D0%A0%D0%B5%D0%BF%D0%BE%D1%80%D1%82&h=48d1b6934569fb2232a3ea9ffc1d2f0220e60378" title="https://forums.linuxmint.com/viewtopic.php?t=413429" target="_blank" rel="nofollow noopener">Репорт</a> бага из Linux Mint

Репорт бага из Linux Mint

И на форуме Manjaro Linux:

И даже на форуме FreeBSD:

Так что проблема действительно есть, причем именно в Xfce а не в конкретной ОС, дистрибутиве или настройках окружения.

Дальнейшие изыскания привели в багтрекер Xfce, к этому багу из 2013 (!) года:

Я насчитал двадцать (20) дублей, закрытых за все время жизни этого тикета, но поскольку с 2013го года сам трекер успел переехать с BugZilla на Gitlab (оригинальный тикет находится тут) — гарантированно что-то успело потеряться.

Несмотря на сильно отличающееся описание, если посмотреть переписку под тикетом — можно увидеть знакомые рога и копыта очертания бага с открытием диалога:

А вот это сообщение в обсуждении навело на возможное место в исходном коде, ответственное за проблему:

Разумеется с 2021го года логика в исходниках успела измениться до неузнаваемости и в актуальной на момент написания статьи версии 4.20 это место выглядит иначе:

Суть происходящего

При восстановлении из сна, происходит повторное включение монитора (какой сюрприз), которое вызывает отработку логики, отвечающей за поиск новых устройств вывода:

Из-за данной логики и происходит отображение диалога «Display Settings», по замыслу авторов — как приглашение к настройке нового устройства, когда например подключается второй монитор или проектор.

"Благими намерениями", вы правильно поняли.

Обратите внимание на вот такую проверку:

/* Start the display dialog according to the user preferences */
if (action == ACTION_ON_NEW_OUTPUT_SHOW_DIALOG)
{
..

Чуть выше по коду в этом же файле displays-x11.c происходит чтение из настроек:

gint action = xfconf_channel_get_int (channel, NOTIFY_PROP, ACTION_ON_NEW_OUTPUT_DEFAULT);
if (action != ACTION_ON_NEW_OUTPUT_DO_NOTHING || old_outputs->len == 0)
{
..

Таким образом по идее создателей, если в этом диалоге в поле «When display is connected» выставлено значение «Do nothing»:

Тогда никакого диалога при просыпании ноутбука появляться не будет.

Но есть нюанс.

Нюанс

У Xfce традиционно не очень хорошо с настройками — она их регулярно теряет и сбрасывает при обновлениях, перезаписывает новыми опциями и вообще всячески ломает.

Из‑за чего диалог «Display Settings» появляется снова и снова.

Я решил что хватит это терпеть видеть сей проклятый диалог при просыпании ноутбука более не желаю, поэтому применил спецсредства.

Решение

Думаю нетрудно догадаться, что окончательное решение диалогового вопроса оказалось очень простым:

/* Start the display dialog according to the user preferences */
if (action == ACTION_ON_NEW_OUTPUT_SHOW_DIALOG)
{
// const gchar *cmd = helper->outputs->len <= 2 ? "xfce4-display-settings -m" : "xfce4-display-settings";
// xfce_spawn_command_line (NULL, cmd, FALSE, FALSE, TRUE, NULL);
g_print("Ignored 'Display Settings' dialog \n");
}

Да, весь блок (он такой один), отвечающий за запуск диалога «Display Settings» был самым банальным образом закомментирован в файле displays-x11.c. И нет, мне не стыдно.

Wayland

Несмотря на то что автор не пользуется Wayland, Xfce его поддерживает и в файле displays-wayland.c есть полностью аналогичное место, где также зашит вызов диалога «Display Settings».

Так что если вы используете Wayland и столкнулись с описываемой проблемой — теперь знаете где именно искать и что делать.

Однако поправить код в таком проекте это лишь начало, ключевая проблема — как это потом собрать и запустить.

Сборка

На самом деле мне сильно повезло, что исправление выше находится в небольшом и автономном консольном приложении xfsettingsd, исходники которого в свою очередь находятся в отдельном репозитории xfce4-settings.

Так что экстремальных приключений в виде сборки всего Xfce из исходников с последующей установкой удастся избежать.

Забираем исходники xfce4-settings:

git clone https://gitlab.xfce.org/xfce/xfce4-settings.git

Переключаемся на релизную ветку той версии Xfce, которая у вас уже установлена — не забываем, что мы правим лишь один небольшой сервис, а все остальное остается из пакетной версии:

git checkout origin/xfce-4.20 -b xfce-4.20

Вытаскиваем зависимые репозитории:

git submodule update --init --recursive

Запускаем сборку:

./autogen
./configure
gmake

В каталоге xfsettingsd появится одноименный бинарник с измененной логикой.

Я не стал заморачиваться с отдельным каталогом в PATH и изучать доступные в Xfce механизмы переопределения путей, вместо этого просто подменив бинарник:

cp ./xfsettingsd/xfsettingsd /usr/local/bin/

И все, больше никаких надоедливых диалогов.

Так выглядит проверочное сообщение, добавленное вместо закомментированных вызовов:

Эпилог

Разумеется такое исправление никогда не примут в апстрим Xfce (занятый переездом на meson) и без навыков программирования вы обречены на вечные муки и страдания наблюдать этот диалог до скончания времен — пока при очередном обновлении не слетит конфигурация.

Добавлю, что сам этот функционал принудительного открытия диалога настроек при изменении оборудования — откровенно дурацкий, из серии «хотели как лучше» и точно нуждается в пересмотре.

Но повлиять «с моей галерки» на авторов Xfce разумеется никакой возможности нет.

P.S.

Статья была опубликована на Хабре, более вольный оригинал в нашем блоге.

Показать полностью 11
62

Chrome, Xfce и очень страшное кино

Серия Мы не пишем в техподдержку

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

Картина "Хром шатает батарею цифрового Ильича".

Картина "Хром шатает батарею цифрового Ильича".

Отдыхаем хорошо

Как и все нормальные люди, я смотрю фильмы, сериалы и длинные видео на ноутбуке и чтобы тот случайно не ушел в сон во время просмотра — включаю на нем «режим презентации».

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

Однако после одного из обновлений, стал замечать, что браузер-то оборзел научился самостоятельно перехватывать засыпание ноутбука, блокировку экрана и запуск скринсейвера во время просмотра видео, без всяких «режимов презентации».

Затем такое поведение появилось и на обычных сайтах — без видимого видео или аудио-контента.

Без каких-либо сообщений, запросов и подтверждений на подобные действия. Затем ноутбук впервые разрядился в ноль, будучи оставленным с открытой страницей какого-то левого сайта, таймеры для suspend и hibernate внезапно не сработали.

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

Изучение проблемы

Первым делом я полез в поисковик, убедиться что проблема — не результат осеннего обострения или моего специфического окружения, в котором половина системы это разнообразные компиляторы и средства разработки, а другая — горы исходного кода.

Оказалось что сия дичь действительно массовая и хорошо известная:

Разумеется тут не про порно, человек просто собирал ядро из исходников. "Sensitive situation".

Разумеется тут не про порно, человек просто собирал ядро из исходников. "Sensitive situation".

Хотя в статье речь пойдет о Xfce, аналогичным обазом ведут себя все «большие» окружения — KDE, Gnome, Cinnamon и так далее:

Отдельная «шутка юмора» — попытка втащить поддержку такого поведения в.. Sway:

Monitor dbus and inhibit swayidle when Firefox or Chromium request it

Хотя любители тайловых менеджеров — особая раса сверхлюдей, понять мотивы которых обывателю не дано, так что не буду даже пытаться.

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

Как видите тут стоит низкий приоритет и не назначен ответственный, ниже станет понятно почему.

Как видите тут стоит низкий приоритет и не назначен ответственный, ниже станет понятно почему.

Помимо означенного тикета в трекере Ubuntu, где тусуются в основном простые пользователи, нашелся еще один эпичный тикет в трекере уже самого Chromium, где обитают в основном разработчики, висящий аж с 2013 года:

Если прокрутить в самый низ страницы, можно заметить статус «Fixed» и битую ссылку на коммит (поскольку трекер переехал), суть которого — легализация специального API для управления блокировкой экрана и засыпанием.. прямо из кода на странице!

Примерно такого:

// The wake lock sentinel.
let wakeLock = null;

// Function that attempts to request a screen wake lock.
const requestWakeLock = async () => {
try {
wakeLock = await navigator.wakeLock.request();
wakeLock.addEventListener('release', () => {
console.log('Screen Wake Lock released:', wakeLock.released);
});
console.log('Screen Wake Lock released:', wakeLock.released);
} catch (err) {
console.error(`${err.name}, ${err.message}`);
}
};

// Request a screen wake lock…
await requestWakeLock();
// …and release it again after 5s.
window.setTimeout(() => {
wakeLock.release();
wakeLock = null;
}, 5000);

Как тебе такое, Илон Маск?

Повторяю для тех, кто еще не понял и не осознал:

любая веб-макака, верстающая на полставки порносайты, ныне может с помощью специального кода на странице заставить браузер Chrome заблокировать засыпание вашего ноутбука.

И защитить от такого может лишь знание языка С и эта замечательная статья.

Механизм работы

Прежде чем «карать и патчить» очередную оборзевшую программу, стоит рассказать широкой аудитории как вся эта кухня вообще работает, хотя‑бы для осознания печальных реалий.

Есть одна неведомая штука в Linux-системах, под названием systemd:

systemd is a suite of basic building blocks for a Linux system. It provides a system and service manager that runs as PID 1 and starts the rest of the system.

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

Так вот, у этого замечательного systemd с недавних пор появился «сказочный» функционал, созданный для перехвата управления процессами засыпания и выключения системы:

systemd 183 and newer include a logic to inhibit system shutdowns and sleep states. This is implemented as part of systemd-logind.daemon(8)

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

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

Можете конечно попробовать заблокировать механизм inhibit в systemd, но все последствия — на вас и вашей совести.

Мы же пойдем немного другим, менее радикальным путем.

Менеджер управления питанием Xfce

Этой командой можно посмотреть список запущенных перехватчиков:

systemd-inhibit --list

В моей системе (Linux Manjaro) вывод выглядит следующим образом:

Обратите внимание, что самого браузера Chrome в списке нет, зато есть xfce4-power-manager — менеджер управления питанием из Xfce, который принимает входящие запросы на перехват и решает что делать дальше.

Остальные сервисы обрабатывают только события засыпания (sleep).

Так что наша цель это xfce4-power-manager , именно туда мы сейчас и залезем, для нанесения правок.

xfce4-power-manager — по большей части фоновое приложение, автоматически запускаемое при старте среды Xfce. Но в отличие от прошлого поциента, тут есть некоторый интерфейс и взаимодействие с пользователем, которое происходит с помощью иконки в трее:

По нажатию правой кнопки мыши, появится меню со списком дерзких приложений, которые в данный момент перехватывают управление питанием:

Так что ответственный за весь этот электронный беспредел был наконец четко определен.

Кровавый патчинг

Исходный код менеджера управления питанием находится в основном репозитории Xfce, исправляемая версия должна совпадать с установленной локально, чтобы не словить феерические проблемы совместимости.

Автор использовал версию 4.20, установленную на момент написания статьи.

Место предстоящей правки — файл xfpm-inhibit.c, в который вынесена вся логика по обработке перехватов (inhibit).

Нас интересует метод xfpm_inhibit_inhibit,строка 370, где начинается обработка входящего запроса на перехват управления.

Код метода небольшой, поэтому привожу его целиком:

static gboolean
xfpm_inhibit_inhibit (XfpmInhibit *inhibit,
GDBusMethodInvocation *invocation,
const gchar *IN_appname,
const gchar *IN_reason,
gpointer user_data)
{
const gchar *sender;
guint cookie;

if (IN_appname == NULL || IN_reason == NULL)
{
g_dbus_method_invocation_return_error (invocation,
XFPM_ERROR,
XFPM_ERROR_INVALID_ARGUMENTS,
_("Invalid arguments"));
return TRUE;
}

sender = g_dbus_method_invocation_get_sender (invocation);
cookie = xfpm_inhibit_add_application (inhibit, IN_appname, sender);

XFPM_DEBUG ("Inhibit send application name=%s reason=%s sender=%s",
IN_appname, IN_reason, sender);

xfpm_inhibit_has_inhibit_changed (inhibit);
xfpm_dbus_monitor_add_unique_name (inhibit->priv->monitor,
G_BUS_TYPE_SESSION, sender);
xfpm_power_management_inhibit_complete_inhibit (user_data,
invocation, cookie);
return TRUE;
}

Обратите внимание на вызов метода XFPM_DEBUG, содержащего текст отладочного сообщения. Все подобные сообщения становятся видны только если запустить xfce4-power-manager с ключом --debug.

Именно так и было найдено место будущей правки, после сообщения в консоли:

xfpm_inhibit_inhibit(): Inhibit send application name=/usr/lib/chromium/chromium reason=Video Wake Lock sender=:1.459

Что мы имеем в итоге:

  • есть единственная точка входа (метод) в менеджере управления питанием, с которой начинается регистрация перехватчика управления;

  • метод принимает на вход название приложения (полный путь), посягнувшего на такой перехват.

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

if (strstr(IN_appname,"chrom") != NULL ) {
XFPM_DEBUG ("Chrome уходи!");
return TRUE;
}

Для не знающих и не владеющих:

метод strstr проверяет на входжение слова «chrom» в названии дерзкого приложения, которое отправило запрос на перехват управления питанием, если оно там есть — происходит немедленный выход из этого метода, а запрос игнорируется.

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

Так это выглядит в действии после наложения моего «кровавого» патча:

В этот знаменательный день браузер Chrome.. пошел лесом.

Сборка

Теперь поговорим о печальном — о сборке всего этого цирка с конями.

Проект xfce4-power-manager это уже существенная часть Xfce, чтобы собрать его из исходников и заставить работать — придется постараться.

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

Куда проще скачать готовый архив со специально подготовленными исходниками релизной версии.

Напоминаю что мы патчим версию 4.20.

Во-вторых, придется установить в систему довольно много библиотек и утилит для разработки:

  • A working GNU toolchain

  • Gtk+ and Glib headers, in some distributions called the -devel packages

    • Xfce 4.20 requires Gtk+ 3.24 and Glib-2.0 >= 2.72 (See also: 4.20 dependencies)

      • Same version for gmodule-2.0, gobject-2.0, gthread-2.0, gio-2.0 and gdbus

    • gdk-pixbuf-2.0 >= 2.42.8

    • gobject-introspection >= 1.72

    • gtk-layer-shell 0.7.0

    • pkgconfig

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

Таков путь.

Распаковываем скачанный архив с исходниками и запускаем скрипт configure:

tar xvjf ~/Downloads/xfce4-power-manager-4.20.0.tar.bz2
cd fce4-power-manager-4.20.0
./configure --disable-wayland

Поскольку сам автор не использует Wayland — тут отключена зависимость от него при сборке, но если вам оно актуально, придется установить дополнительные библиотеки:

  • wayland 1.20

  • wayland-protocols 1.25

Добавляем описанный выше блок в файл src/xfpm-inhibit.c и наконец запускаем сборку:

make

Если сборка завершится успешно, в каталоге src будет готовый бинарник с патчем, проверить который можно так:

pkill -f xfce4-power-manager
./src/xfce4-power-manager --debug

Дальше открываем в Chrome любую страницу с видео и смотрим выдаваемые сообщения:

Победа.

Победа.

Разумеется, после такого патча вам придется вручную включать и отключать режим презентации (Presentation mode) при просмотре длинных роликов в браузере, зато процесс будет полностью контролируемым.

Также подобным образом можно «обламывать рога» и другим интересным приложениям, дерзнувшим покуситься на управление питанием, например с недавних пор за подобным неблаговидным делом был замечен Firefox.

Эпилог

Грустно наблюдать (в который уж раз), как некогда хороший софт, по мере роста популярности скатывается в полное УГ отрицание пользовательского опыта и начинает считать своих пользователей полными идиотами:

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

И лишь владение языком С и навыки системного программирования все еще позволяют ставить на место оборзевшие программы — изучайте же инженерное дело настоящим образом!

Статья была опубликована на Хабре, оригинал статьи как обычно в нашем блоге.

Показать полностью 9
14

WiFi, который не ловил

Серия Мы не пишем в техподдержку

Рассказываю про еще одну коварную подлость, встроенную в современные технологии беспроводной связи — WiFi. Про это знают все приличные сетевые инженеры, но почему-то не рассказывают простым пользователям.

Проблема

Временами во время разъездов, когда нахожусь в дороге, включаю мобильную точку WiFi на своем телефоне — чтобы подключиться к ней с ноутбука и попасть в интернет.

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

Однако после одного из недавних обновлений, WiFi-точка на телефоне стала работать нестабильно и подключиться получалось не с первой попытки.

Временами мобильная точка пропадала из выдачи — ее не было видно в списке доступных сетей, даже когда телефон лежал рядом. Причем проблемы с подключением были далеко не со всем клиентским оборудованием и не со всеми ОС, так что дело было явно не в ней самой.

Я довольно долго не мог понять в чем дело и забивал на исправление, пока однажды это не стало проблемой:

в нужный момент не смог подключиться и отправить важное письмо.

Тут стоит указать, что хотя все действия происходили на FreeBSD, сама проблема актуальна для любых ОС, включая внезапно встроенные.

Были скопированы настройки сети с «соседнего устройства», где все работало, после чего попытался подключиться полностью вручную — указав название точки, пароль, SSID и номер канала.

Мобильная точка выбирает номер канала случайным образом при каждом включении и на момент отладки выпал номер 13.

Внезапно, при попытке указать канал с этим «чертовым» номером появилась ошибка:

unknown/undefined channel number 13 flags 0x0

Которая немедленно была забита в поисковик и выдала кучу сообщений с похожими проблемами:

Как в FreeBSD-системах:

Так и в Linux:

И даже в прошивках роутеров:

Если думали, что проблеме подвержены только открытые ОС и любимая Windows или MacOS от такого не страдают — у меня для вас плохие новости: раз, два.

Проклятие тринадцатого канала

Посмотрев на номер уже было подумать, что все это происки «темных сил», шатающих WiFi автора темными ночами.

Но ведь FreeBSD это система с красным чертом на логотипе, по идее 13й канал должен быть наоборот самым стабильным и работать безупречно.

Как же так?

Все дело оказалось в.. так называемом Regulatory Domain:

FreeBSD's net80211 stack has basic regulatory domain support, enforcing restrictions on frequency, operating modes, transmission power and general behavior.

Та самая сказочная хтонь, про которую вы точно слышали, если имеете отношение к беспроводным сетям и админству, но слабо представляли как оно может влиять на просторах нашей необъятной.

А теперь читаем:

While the USA restricts 2.4 GHz Wi-Fi to eleven channels, channels 12 through 14 are available elsewhere in the world. You might even be able to activate them by changing your router settings, although you should not do so. Channel 14 is the most tempting to people, as it would have even less interference---but it's illegal to operate your router on this channel in the USA.

Круто?

Как думаете, что произойдет если при установке системы (любой) будет выбрана страна по-умолчанию — США?

Помимо очевидной английской локали, форматов дат и времени, будет применен еще и этот самый «regulatory domain» для Wifi — для США.

И вы получите описанную проблему с подключением и каналами. Ну разве 21 век это не чудо?

Решение

Как уже писал в самом начале, про сам «regulatory domain» знает любой более-менее опытный сисадмин, но вот как его неправильный выбор влияет на работу WiFi-карты — не знает почему-то никто (проверено).

Поэтому вполне допускаю, что описанное окажется сюрпризом и для вас.

К счастью для исправления ситуации, на этот раз не надо патчить драйвера или пересобирать ядро, достаточно указать в /etc/rc.conf правильный regulatory domain:

create_args_wlan0="country RU"

Затем перезагрузить всю систему, либо поддержку сети:

/etc/rc.d/netif restart

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

ifconfig wlan0 list regdomain

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

Еще один удивительный момент:

ни одна нейросеть не смогла найти связь между проблемами с подключением к WiFi и выбором regulatory domain, ни для одной ОС.

Хотя по идее это старая и широко известная история.

P.S.

Статья была опубликована на Хабре, оригинал как обычно в нашем блоге, копия на Яндекс Дзене.

Стоит еще добавить, что на самом деле проблема касается двух каналов: 12 и 13. А еще есть 14, использование которого разрешено только в Японии, поэтому для его использования придется переключиться на их regulatory domain.

Показать полностью 5
0

Посоветуйте рабочий аналог Lightroom в Linux

А есть кто-нибудь, кто занимается фотографией в Linux?

Я долгое время работал с фотками в Lighroom и был от него в восторге. В восторге был до тех пор пока не познакомился с Capute One - афигеный инструмент и шикарная работа с цветом! Порой в нем чудо получается с помощью нескольких движений в отличии от целой работы в Ligtroom, но... захотелось попробовать найти что-то подобное в Linux и пока только наткнулся на darktable и RawTherapee, хочется и каталог и обработку на уровне, и чтобы пресеты были ибо не делать же одно и тоже каждый раз вручную.

darktable и RawTherapee..... после LR и C1 складывается ощущение будто ты пересел с какой-нибудь комфортной и проходимой Audi A4 Quattro в какую-то низко посаженную Приору с пневмоподвеской, все как надо - тонировка в круг, ревущая на весь квартал перделка в глушаке, куча неона внутри, бортовой компьютер, куча кнопочек, мультимедиа с андроид, GPS, Starlink, 50 колонок, кожаный салон, пуск двигателя с кнопки. Короче вроде куча всего есть, только нахуя если в итоге все равно это говно? ) В общем не нашел я эти инструменты удобными, результат какой-то получить можно, но там где есть автоматика - она говно, где нет автоматики руками получается раз в 30 дольше чем в нормальных редакторах..

Может я плохо искал и есть реально удобные и эффективные инструменты для работы с большим каталогом и редактором?

45

История еще одного патча: зависшая батарея

Серия Мы не пишем в техподдержку

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

Патч ядра Linux и три года изысканий, рассказываю как это было.

Божественные Вайнона Райдер и Натали Портман, работы нейросети. Ну и пропатченное ядро.

Божественные Вайнона Райдер и Натали Портман, работы нейросети. Ну и пропатченное ядро.

Вводная

Автор очень давно использует самые разнообразные версии и вариации Linux и UNIX‑систем для работы и диких развлечений, в том числе на ноутбуках, поэтому старается решать все найденные проблемы, по мере сил.

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

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

Описываемая история — как раз из последних.

Проблема

Вкратце проблема заключалась в абзаце, вынесенном в заголовок:

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

Естественно в Windows все работало правильно и стабильно, в любых режимах засыпания.

Ноутбук редкий, ноутбук старый, от вендора, который в гробу видал никогда не любил альтернативные ОС и тем более в страшном сне не мог представить, что одна из его топовых моделей (на свое время) вместо подсчета прибылей успешному бизнесмену, стала бы использоваться для компиляции ядра из исходников и прочих гиковских непотребств.

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

Работа с ACPI — традиционно самая замороченная область ядра Linux, а процессы засыпания и возвращения к работе — сложны и нестабильны по своей сути.

Так что оно глючило, глючит и будет глючить, в любой ОС и на любом оборудовании при любой погоде.

Процесс отлова ошибок связанных с ACPI усложнен тем, что такие ошибки чаще всего «плавающие» — могут появиться не через один цикл «засыпания‑пробуждения» а например через десять, т. е. вам надо десять раз подряд погрузить ноутбук в сон и затем пробудить чтобы отловить ошибку.

Правда ведь отладка это весело?

Решение

Далеко не сразу (ушло примерно три года), путем хитрых запросов к поисковикам и изучения исходников ядра, автор все же смог отыскать концы этой проблемы.

И помог в этом случайный комментарий неизвестного китайского разработчика:

I have few reputation so I can't tell others about solution in their questions, so I will post it here.

Solution : build kernel with this PATCH

Description : I tracked the issue ,I discovered that all was working good until the 4.19.86 kernel.

So I checked DIFF and After many tries maybe 50 or more.

I found the cause : It was (if statement was added in 4.19.86 COMMIT) ,particularly checking if spaceid == 0 [ACPI_ADR_SPACE_SYSTEM_MEMORY]. Commit Link

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

Еще речь шла про совсем уж древнюю версию ядра (4.19, релиз в 2018м году) а само сообщение датировалось 2022 годом.

Но вы ведь и не думали, что все будет настолько просто, верно?

Решение

Посмотрим на код «виновника торжества», файл drivers/acpi/acpica/evregion.c, метод acpi_ev_execute_reg_methods, а еще точнее — вот этот замечательный комментарий:

/*
* These address spaces do not need a call to _REG, since the ACPI
* specification defines them as: "must always be accessible". Since
* they never change state (never become unavailable), no need to ever
* call _REG on them. Also, a data_table is not a "real" address space,
* so do not call _REG. September 2018.
*/

Обратите внимание на дату — 2018й год, год выпуска версии ядра 4.19, в которой и проявилась данная проблема.

По сути самого комментария и исходя из логики, один из коммитеров ядра Linux в далеком 2018 году хотел «сделать как лучше»:

if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
(space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
(space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
return_VOID;
}

Полагая что строгое соотвествие спецификации ACPI в данном случае бывает всегда — коммитер вставил заглушку, убирающую вызов _REG метода для вроде как системных частей ACPI‑прошивки.

Чем и поломал восстановление статуса батареи при пробуждении ноутбука.

Благими намерениями выстелена дорога в Ад. (ц)

Исправление

Все что нужно сделать для исправления ситуации, это убрать из условия проверки константу ACPI_ADR_SPACE_SYSTEM_MEMORY:

if (
// (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
(space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
(space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
return_VOID;
}

Ну и опционально добавить отладку, чтобы убедиться в правильности работы:

if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
printk(KERN_DEBUG "PRO HEHE : Bypassing for battery is done");
}

Отладка была включена в текущем ядре, само сообщение можно наблюдать на стартовой картинке к статье.

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

Эпилог

Такой патч никогда не примут в аппстрим ядра, потому что он неправилен с точки зрения спецификации ACPI.

Собственно сама проблема с зависшей батареей появилась из-за того что некоторые вендоры класть хотели на стандарты и спецификации.

К сожалению такого рода проблемы в новых версиях ядра Linux появляются все чаще, поэтому и ситуация и ее решение — уже можно сказать типовые и подобным образом решаются ныне и многие другие проблемы с оборудованием.

Так что если на вашем ноутбуке также проявляется описанная проблема с «зависанием» батареи — теперь будете знать в какую сторону копать.

P.S.

Если вы внимательно смотрели на заглавную картинку к статье, могли заметить что автор использовал нестандартное ядро:

XanMod is a general-purpose Linux kernel distribution with custom settings and new features. Built to provide a stable, smooth and solid system experience.

The real-time version is recommended for critical runtime applications such as Linux gaming server / client for eSports, streaming, live productions and
ultra-low latency enthusiasts.

Этот набор патчей ядра Linux действительно сильно ускоряет работу, что особенно заметно на некрожелезе времен молодости Брежнева, которое автор регулярно использует для укрепления стойкости духа.

P.P.S.

На данный момент проблема все также актуальна и вряд ли будет решена в апстриме ядра в обозримом будущем. Поэтому автор продолжает накладывать описанный патч (и еще несколько) при каждой пересборке ядра.

Статья была опубликована на Хабре, оригинал которой находится в нашем блоге.

Показать полностью 3
40

WCC: Гримуар компьютерного колдуна

Серия Жестокие эксперименты

Рассказываю об одном весьма необычном инструменте, способном удивить даже очень изысканную публику. Поскольку с его помощью можно быстро и безболезненно.. сменить пол любимой программе для Linux. Добро пожаловать, снова.

Вдумчивое чтение содержимого этих терминалов может привести в дурку, я предупредил.

Вдумчивое чтение содержимого этих терминалов может привести в дурку, я предупредил.

The Witchcraft Compiler Collection

Сей замечательный проект — отличное доказательство существования черной магии и колдовства тому, как мало на самом деле мы знаем об устройстве собственных программ.

По крайней мере лично автор весьма смутно представляет, как эта адская штука вообще работает, несмотря на весь свой опыт и многолетнюю практику:

WCC is a collection of compilation tools to perform binary black magic on the GNU/Linux and other POSIX platforms.

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

Если вкратце, WCC это такой набор очень специфичных утилит для препари.. исследования чужих программ.

Информации об этой штуке в сети крайне мало, фактически помимо проекта на Github, существует лишь одна интересная презентация, показанная на конференции Defcon, слайды из которой также использовались в статье.

Так что материал получился весьма редким.

Сборка и инвольтация эгрегора

К сожалению проект успел немного устареть, хотя и присутствует в виде готовых пакетов во многих дистрибутивах Linux. Однако в Mageia, которую автор использовал ради колдовской ступы на логотипе в качестве тестовой среды, WCC почему-то не оказалось, так что пришлось собирать руками.

Согласно описанию, необходимо установить следующие пакеты:

capstone, glibc, libbfd, libdl, zlib, libelf, libreadline, libgsl, make

Однако libbfd ныне стал частью пакета binutils и отдельно более не поставляется, а binutils скорее всего уже установлен по-умолчанию.

Забираем исходники и запускаем сборку:

git clone https://github.com/endrazine/wcc.git
git submodule init && git submodule update && make

Конечно же попытка собрать себе "гримуар электронного колдуна" из исходников закончится закономерным провалом:

Вы же не думали, что будет легко?

Вы же не думали, что будет легко?

Взывание к темным богам и поиск проблемы, взятой из трассировки выше в разных поисковиках:

undefined reference to `sframe_encoder_write'

привел наконец к вот такому багрепорту из трекера Debian. Там же был обнаружен и этот адский патч для WCC:

diff -Nru wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch
--- wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch 2020-03-21 19:02:12.000000000 +0200
+++ wcc-0.0.2+dfsg/debian/patches/binutils_shared.patch 2023-01-18 16:09:29.000000000 +0200
@@ -12,7 +12,7 @@
-all::
- $(CC) $(CFLAGS) wcc.c -o wcc -lbfd -lelf -lcapstone
+all:
-+ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -lz -ldl -liberty -lelf -lcapstone
++ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -l:libsframe.a -lz -ldl -liberty -lzstd -lelf -lcapstone
# $(CC) $(CFLAGS) -m32 -Wl,-rpath /home/jonathan/solution-exp/unlinking/awareness/self/wcc/src/wcc/lib32/ wcc.c -o wcc32 -lelf ./lib32/libbfd-2.24-system.so ./lib32/libcapstone.so.3

cp wcc ../../bin/

Как можно догадаться из этих двух строчек (если вы приличный маг):

-+ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -lz -ldl -liberty -lelf -lcapstone
++ $(CC) $(CFLAGS) wcc.c -o wcc -l:libbfd.a -l:libsframe.a -lz -ldl -liberty -lzstd -lelf -lcapstone

для завершения сборки необходимо изменить паметры, передаваемые линковщику.

Что я и проделал в файле src/wcc/Makefile:

После исправления, сборка заканчивается успешно и в каталоге bin появляются готовые к использованию "колдунские" приложения:

Колдовской набор.

Колдовской набор.

Теперь можно начинать плести заклинания.

Колдунство первое: превращаем приложение в библиотеку

Нет это не шутка и не прикол, это та самая "черная магия" от системной разработки, которой не научат на курсах по вайбкодингу.

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

Transforming an ELF executable binary into an ELF shared library.

Последовательность заклинаний шагов выглядит так:

Превращение утилиты cat в разделяемую библиотеку.

Превращение утилиты cat в разделяемую библиотеку.

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

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

Из презентации WCC для Defcon.

Из презентации WCC для Defcon.

На скриншоте выше видно, что по факту в файле изменился лишь один байт, точнее поле заголовка ELF64:

Из заголовочных файлов формата ELF.

Из заголовочных файлов формата ELF.

Хотя назначение этого поля не является секретом и присутствует даже в Википедии, помимо официального руководства, до столь затейливого его применения никто на моей памяти не доходил. Кроме авторов WCC.

При вызове, первым шагом происходит откат работы линковщика:

The primary use of wcc is to "unlink" (undo the work of a linker) ELF binaries, either executables or shared libraries, back into relocatable shared objects. The following command line attempts to unlink the binary /bin/ls (from GNU binutils) into a relocatable file named /tmp/ls.o

Пример вызова:

wcc -c /bin/ls -o /tmp/ls.o

По идее уже на этой стадии должен быть получен «relocable file», с которым может работать обычный gcc. Например должна отрабатывать команда:

gcc /tmp/ls.o -o /tmp/ls.so -shared

К сожалению в моей Mageia это не сработало, поэтому был использован альтернативный вариант "очищения":

cp /bin/ls /tmp/ls.o
wld --libify /tmp/ls.o

Результат выполнения команды wld теперь спокойно распознается обычным компилятором gcc:

gcc /tmp/ls.o -o /tmp/ls.so -shared

И в результате действительно получается разделяемая библиотека, которую можно спокойно линковать с вашим приложением:

file /tmp/ls.so
/tmp/ls.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=68d93a1d888eb560b8842
55a59c37cd6be0adddd, not stripped

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

Вставляет покруче Некрономикона.

Вставляет покруче Некрономикона.

Но едем дальше.

Получение имени пользователя радикальным способом - через рефлексию в плеере VLC (!)

Получение имени пользователя радикальным способом - через рефлексию в плеере VLC (!)

Колдунство второе: рефлексия для.. чистого С

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

The witchcraft shell accepts ELF shared libraries, ELF ET_DYN executables and Witchcraft Shell Scripts written in Punk-C as an input. It loads all the executables in its own address space and makes their API available for programming in its embedded interpreter.

Вообще этот абзац - один сплошной "майндфак" для всех, кто хоть немного знаком с языком С, в лучших традициях Лавкрафта погружающий разум несчастных быдлокодеров во мрак ультрахардкора.

Хотя авторы WCC на голубом глазу заявляют:

This provides for binaries functionalities similar to those provided via reflection on languages like Java.

до рефлексии уровня Java/.NET тут все же очень далеко и вызывать столь интересным образом методы в чужих библиотеках получается далеко не всегда.

Теперь рассказываю, как можно попробовать сие темное колдунство в действии. Интерпретатору wsh из состава WCC скармливается разделяемая библиотека или ELF-приложение:

wsh /usr/sbin/apache2

К сожалению стабильность работы вызывает вопросы, поэтому тут 50/50 — колдунство может сработать, а может выпасть segmentation fault. Если был передан бинарник — автоматически произойдет его «библификация», описанная выше.

Если сработало, появится сообщение зелеными буквами на черном фоне:

loading of libified binary succeeded

И можно будет пытаться вызывать:

a = ap_get_server_banner()
print(a)

Код выше — отдельный язык, такая своеобразная помесь С и Lua, с весьма поэтическим названием:

The resulting API, a powerful combination of lua and C API is called Punk-C

Авторы решили не заморачиваться с типами данных, поэтому и родилась на свет эта дикая помесь ужа с ежом С и Lua.

Так выглядит более сложный пример использования:

#!/usr/bin/wsh

-- Computing a MD5 sum using cryptographic functions from foreign binaries
-- (eg: sshd/OpenSSL)

function str2md5(input)

out = calloc(33, 1)
ctx = calloc(1024, 1)

MD5_Init(ctx)
MD5_Update(ctx, input, strlen(input))
MD5_Final(out, ctx)

free(ctx)
return out
end

input = "Message needing hashing\n"
hash = str2md5(input)
hexdump(hash,16)

exit(0)

Для демонстрации работы необходимо вначале загрузить одну из библиотек, реализующих функции MD5-хеширования, что и было немедленно проделано:

Считаем MD5-хеш с помощью метода, вызванного через рефлексию из бинарника sshd.

Считаем MD5-хеш с помощью метода, вызванного через рефлексию из бинарника sshd.

Как видите все работает и действительно отображается MD5-хеш для введенной строки, вычисленный с помощью вызова функции из бинарника sshd.

Без исходников и без линковки.

Но это далеко не все колдовские приколы, которые позволяет творить WCC.

Колдунство третье: восстановление флагов сборки

Хотя авторы WCC опять несколько преувеличивают, рассказывая про возможность восстановления абсолютно всех флагов сборки:

When compiling C code, it is often required to pass extra arguments to the compiler to signify which shared libraries should be explicitly linked against the compile code. Figuring out those compilation parameters can be cumbersome. The wldd commands displays the shared libraries compilation flags given at compile time for any given ELF binary.

На практике же речь идет только о библиотеках:

Ключи сборки mplayer.

Ключи сборки mplayer.

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

Колдунство четвертое: генератор заголовков

Последнее в этой статье, но далеко не последнее по важности и применимости:

The wcch command takes an ELF binary path as a command line, and outputs a minimal C header file declaring all the exported global variables and functions from the input binary. This automates prototypes declaration when writing C code and linking with a binary for which C header files are not available.

Вот тут действительно респект и жертвоприношение уважение, поскольку столь мощное колдунство может сильно помочь в разработке:

Генерация заголовочного .h файла из бинарника sshd. Без исходного кода.

Генерация заголовочного .h файла из бинарника sshd. Без исходного кода.

Но все же стоит помнить про ограничения технологии и не ждать 100% корректности получаемых заголовков.

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

cat /tmp/sshd.h |head -c 500


/**
* Automatically generated by the Witchcraft Compiler Collection 0.0.9
**/
extern void *optind;
extern void *obstack_alloc_failed_handler;
extern void *error_message_count;
extern void *argp_err_exit_status;
extern void *_IO_2_1_stderr_;
extern void *stdin;
extern void *program_invocation_short_name;
[alex@illuminati wcc]$

Думаю очевидно, что артефакты вроде:

extern void *_IO_2_1_stderr_;
extern void *stdin;

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

Резюмируя

WCC это по истине необычный и редкий проект, к сожалению (или к счастью) неизвестный широкой программерской публике.

Хотя его использование требует серьезной подготовки и определенных навыков, а работа утилит часто нестабильна - эффект в виде зарева полыхающих пердаков быдлокодеров простых разработчиков выходит эпический.

Если вы занимаетесь серьезной разработкой на C/C++ под Linux и ненавидите человескую расу, думаю стоит ознакомиться с этой штукой поближе, чтобы включить WCC в свои темные планы и нечестивые эксперименты.

P.S.

Оригинал статьи в нашем блоге, статья была опубликована на Хабре.

Показать полностью 11
12

Бэкап Шрёдингера

Бэкап Шрёдингера

Бэкапы есть? А если найду?

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

Формально бэкапы существовали. За них отвечала команда администрирования виртуальной инфраструктуры. Доступа к гипервизорам, их настройкам и самим резервным копиям у меня не было. Проверить консистентность я не мог, сколько займёт восстановление — не знал, и вообще не был уверен, что в случае аварии сервер реально поднимется. Поэтому для себя вывел простое правило: пока не проверил восстановление — бэкапа не существует.

Первый эксперимент

Из локальных средств резервного копирования нашлась интересная практика: раз в неделю снималась SquashFS-копия файловой системы и складывалась на NAS. С неё и начал.

После нескольких итераций получилось поднять сервер вручную: загрузка с Live-CD, разворачивание файловой системы, переустановка GRUB — и система стартовала уже с восстановленного диска.

Даже если такой способ когда-нибудь не позволит восстановить сервер целиком, остаются конфиги, сертификаты, служебные данные — то, что обычно в самый неподходящий момент приходится собирать заново. Уже одно это делает такой бэкап полезным.

Чёрный ящик

Схема бэкапа была простой: Puppet раскладывал скрипт резервного копирования на сервер, cron запускал его по расписанию. На этом контроль заканчивался. Есть ли свежий бэкап? Не пустой ли он? Можно ли на него рассчитывать? Ответа на эти вопросы не было.

Написал небольшую утилиту проверки. Она подключается к хранилищу, ищёт резервные копии каждого сервера и прогоняет простые проверки:

  • существует ли текущий бэкап;

  • существует ли предыдущий;

  • не слишком ли маленький получившийся архив;

  • не отличается ли его размер от предыдущего больше допустимого порога.

Это не гарантирует целостность данных, но ловит большинство типичных ошибок. А они нашлись! На удивление, полностью исправных серверов оказалось меньше, чем ожидалось. Где-то cron запускал скрипт с неправильным окружением. Где-то не хватало прав доступа. На части серверов отсутствовали нужные пакеты. Встречались и банальные ошибки в настройках. После исправления резервное копирование стало заметно стабильнее.

Новая проблема

Исправив одну проблему, бонусом получил следующую. Все серверы запускали бэкап в одно и то же время. Десятки машин одновременно начинали сжимать данные и лить их на сетевое хранилище. Канал забивался, скорость падала, часть копий завершалась с ошибками.

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

Оркестратор

Появился отдельный сервер-оркестратор. На каждом клиентском сервере создаётся специальный пользователь, которому разрешено выполнять ровно один заранее определённый скрипт резервного копирования с повышенными привилегиями — и ничего больше. Оркестратор хранит список серверов, последовательно подключается к каждому по SSH и запускает бэкап. Пока один сервер не закончит, следующий не стартует.

Привязки к конкретным машинам нет. Через Puppet любому серверу можно назначить роль клиента резервного копирования, роль оркестратора или обе сразу. Пользователи, права, ключи, скрипты, расписание — всё поднимается автоматически. Благодаря этому оркестратор можно перенести на другую машину без ручной перенастройки инфраструктуры.

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

Скрипт бэкапа

Заодно доработал сам скрипт резервного копирования. Теперь он:

  • автоматически удаляет собственные копии старше четырёх недель, не трогая данные других серверов;

  • проверяет размер созданного архива и сравнивает его с предыдущим;

  • кроме самого архива рядом сохраняется информация, необходимая для восстановления сервера;

  • по завершении пишет небольшой файл состояния — дата выполнения, размер копии, итоговый статус, диагностическое сообщение.

Zabbix просто читает из файла состояние последнего бэкапа и сигнализирует, если копия давно не обновлялась, завершилась с ошибкой или подозрительно похудела.

Итог

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

Теперь легко отследить, в каком состоянии находится резервное копирование. Существующий процесс стал более управляемым, а уровень тревожности стал ниже.

Если считаете что я изобрёл велосипед, или есть советы как сделать бэкапирование более качественным, то пишите в комментариях, с удовольствием почерпну для себя ценную информацию!

Показать полностью
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества