Остался месяц до RICON 2014, который в этом году состоится 28го и 29го октября в Лас-Вегасе, США.

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

Если соберетесь в конце октября заехать в Вегас, то не пропустите. Будет интересно!

Не прошло и пары суток, а дыру в bash начали успешно использовать.

Проблема, конечно, гораздо больше, чем некое дырявое приложение. Она обладает корнями, глубоко уходящими в недра религии юниксвэя. Мы неоднократно говорили, что склеивать бинарнички с помощью пайпов, в которых передается неструктурированная текстовая информация, это дикость из археологических глубин ранних юниксов. Мы предлагали и модернизацию pipes, и постоянно рассказываем о необходимости переводить текст-ориентированные системы на бинарные (например, раз и два), и уж разумеется наши коллеги всегда отстаивали порочность юниксвэйного запуска приложений из других приложений, и последующего анализа текстового вывода (например, довольно радикальная презентация с Linux Plumber Conference 2012 нашего коллеги Andy Grover).

Мы продолжаем отстаивать точку зрения, что весь этот цирк со злыми клоунами юниксвэй необходимо заменить на сильно связанные, но работающие независимо (компоненты systemd, приложения D-Bus) и изолированно (SELinux, cgroups и т.п.) приложения, общающиеся с помощью стандартизированных бинарных сообщений (JSON, GVariant, BSON, Bencode, XML, да что угодно) по стандартной шине данных (D-Bus / kdbus), и события которых оперативно заносятся в базу данных событий системы (Journald). Это то, что называется платформа Linux, и то, к чему мы весь мир опенсорса потихоньку ведем.

Напоследок рекомендуем прочитать своевременный пост от Dan Walsh, в котором он объясняет, почему SELinux не блокирует проблему, и как он минимизирует ущерб. Вкратце, у кого SELinux включен, у того ошибка будет изолирована, и злоумышленник не сможет похитить ваши данные, хотя и сможет использовать ваш компьютер, а вот у кого выключен (у волосатых дикарей-троглодитов), у тех злоумышленник получит полноценный доступ к вашей машинке. Такие дела.

И вновь о безопасности. Наши коллеги начали новый раунд добавления функции strlcpy, используемой в BSD, в Glibc.

Есть семейство библиотечных функций strcpy. Эти функции не глядя копируют одну строку в другую. Есть одна беда - если приемник короче источника, то будет переполнение буфера. Поэтому использовать их не рекомендуется. Вместо strcpy есть семейство strncpy, которые не копируют больше, чем можно. Но с этим семейством есть другая беда - функция будет копировать, пока есть место, и если что-то не влазит, то оно будет отброшено (включая нулевой байт в конце). В случае, когда strcpy приводит к переполнению буфера, в strncpy мы получаем байтовые массивы, что лучше, но тоже плохо.

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

Таким образом у программистов BSD есть целых три способа написать неправильный код для работы со строками, а до сих пор в Glibc было лишь два. Ulrich Drepper был предсказуемо против включения третьего неправильного варианта, т.к. какой смысл предлагать программистам писать кривой код? Но проблема была в коде, написанном программистами BSD - мы насчитали 60 программ, написанных с использованием этой функции. При ее отсутствии, программы переключаются на некий кое-как набранный самопал, оптимизированный плохо, не использующий последние разработки в GCC, что гораздо хуже.

Нашими коллегами было решено посмотреть правде в глаза. Функция strlcpy используется, и ее отсутствие в Glibc, это большая проблема, чем ее возможное наличие. Одна из недавних ошибок в SAMBA была вызвана как раз самопальной реализацией strlcpy. Принимая все это во внимание, наши коллеги начали ее включение в Glibc.

Мы, кстати, рекомендуем обратить внимание на функционал glib, и использовать его при возможности:

g_strconcat() -- concatenates a NULL-terminated list of strings g_strjoin() -- similar, but allows to add an optional separator g_strjoinv() -- concatenates an array of strings, with an optional separator g_strdupv() -- duplicate an array of strings g_strsplit() -- splits a string into an array g_strescape()/g_strcompress() -- escape/unescape a string g_strdelimit() -- change delimiter (let's say you've got a comma-delimited string and want it to be space delimited) g_strstrip() -- strip away leading + trailing whitespace g_strchomp() -- strip away leading whitespace g_strchug() -- strip away trailing whitespace g_strnfill() -- creates a string of the specified length filled with a specified character and of course my favourites: g_strdup_printf(), g_strdup_vprintf(), g_vasprintf() -- sprintf()/vsprintf() variants that allocated the necessary memory.

Независимый разработчик, Stephane Chazelas, отловил прекрасную дыру в BASH, которую подтвердили наши коллеги. Учитывая, что по религии юниксвэя, легко читаемыми баш-портянками залепляются все возможные отверстия (OpenSSH, DHCP-клиенты и т.п.), то дыра получилась массивная. По десятибалльной системе ее оценивают в 10 баллов, и для ее использования не нужно авторизации.

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

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

А вот наш коллега, Caolán McNamara, начал совсем уж необычный эксперимент. Он устанавливает в Linux-систему шрифты из Mac OS X, и пытается их использовать в LibreOffice. Сразу скажем, что мы не уверены в законности этого действия, если у вас нет легально купленной копии Mac OS X, но Caolán рискнул. В результате он получил необычный результат. Шрифты в fontconfig есть, а LibreOffice их не видит. Как обычно, для наших коллег, Caolán не побежал жаловаться в чатик или форум, а сел разбираться. Выяснилось, что в LibreOffice не поддерживалась версия "2" ttс-фонтов, нужно было добавить поддержку кодировки имени фонтов, используемую в Mac OS X, перевести Apple Language ID во внутреннее представление LibreOffice, и необходимо было внести ряд других мелких изменений.

Работа еще не закончена, но уже кое что работает. Теперь вы можете нас удивлять не только странным желанием использовать Windoz-шрифты, но и желанием использовать Mac OS X-шрифты.

Инженер Red Hat и участник Fedora и Debian David Airlie рассказал о текущем состоянии Virgil 3D (статья за paywall) на прошедшем LinuxCon North America. Мы уже вкратце упоминали про Virgil 3D, и возможно пришла пора рассказать о нем, и проблеме, которую он решает, поподробнее.

Очень хочется предоставлять виртуальным машинам возможности 3D-ускорения, имеющиеся на хостовой системе. Сейчас есть лишь проприетарные решения. Virgil 3D, это как раз открытый вариант. Сейчас он использует Mesa, но в будущем планируется добавить и DirectX и Direct3D драйверы.

Исходная задача

Airlie сказал, что решение VMware "лучший вариант из существующих" для виртуального GPU. Однако, он основан на DirectX 9, так что у него ограниченные возможности, и он проприетарный, кроме куска, который работает в гостевой системе Linux. У VirtualBox тоже есть решение, но оно основано на OpenGL, который является "худшим вариантом", т.к. его сложно сделать безопасным. У OpenGL есть слишком много точек входа, и для приложения в userspace очень легко добиться переполнения буфера или создать иные проблемы. Также есть драйвер vGallium, но это лишь исследовательский проект, до сих пор не достигший уровня пригодности для широкого использования.

Virgil 3D основан на virtio, на стандарте для виртуализированного ввода/вывода (I/O), созданном Rusty Russell. Основная идея virtio, это набор очередей для взаимодействия с драйвером, наряду с конфигурационным пространством, которое может выглядеть как PCI.

С графической части Mesa реализует OpenGL, а ее часть Gallium3D упрощает разработку 3D-драйверов. Под Mesa есть еще EGL API, который сидит между OpenGL и оборудованием. EGL был изначально спроектирован для встраиваемых устройств, но он теперь "все чаще и чаще используетсядля всего подряд", сказал David, и однажды "захватит всё". Еще одна часть мозаики, это SPICE, протокол для "удаленного десктопа" — он предоставляет удаленный доступ к аудио, видео, устройствам ввода-вывода и т.п.

На реальном графическом оборудовании обязательно есть что-то типа ring buffer, куда ядро отправляет команды. Графические драйверы из userspace создают потоки таких команд (которые манипулируют текстурами, surface, шейдерами и т.п.), чтобы передать их в ядро. Эти userspace-команды должны рассматриваться, как небезопасные. Они копируются в ядро, затем проверяются, чтобы превратить их в "безопасные" команды. А уже эти команды затем помещаются в ring buffer, за которыми располагается защитная операция (fence). Т.к. GPU асинхронное, то ядро может узнать, что набор команд был выполнен, лишь по порядковому номеру, присвоенному уже выполненной защитной операции (fence).

Поддержка 2D

Первая задача для Virgil 3D, задолго до перехода к "3D части, в которой я был заинтересован", была, это запустить базовый virtio GPU драйвер, сказал Airlie. Он поддерживал несколько мониторов, хардверные курсоры, и базовый набор 2D команд. Драйвер предоставлял memory-mapped I/O, PCI, или VGA устройства, и должен был работать на любой архитектуре, что поддерживала virtio. "Базовым компонентом был командный ring buffer", хотя оригинально было задумано два кольцевых буфера, и один для защитных операций (fence). Разработчик QEMU переписал его для использования лишь одного командного ring buffer — кольцевой буфер для защитных операций (fence) может быть добавлен попозже, если его отсутствия станет проблемой.

Базовый объект в драйвере, это ресурс, сказал Airlie, и каждый ресурс обладает уникальным идентификатором. Для 2D, каждый ресурс обладает шириной, высотой, битовой глубиной, привязанных к нему. Для 3D, есть еще "целый букет" атрибутов, и это "гораздо сложнее". Гость просто ссылается на ресурс по его идентификатору, а хост выделяет память и создает собственно ресурс. Драйвер получает страницы памяти гостевой системы, чтобы присоединить их к ресурсу.

Ресурсы отображаются в объекты OpenGL. Для 2D, драйвер просто копирует данные из гостевых страниц памяти, присоединенных к ресурсу, в объект OpenGL. Передавать данные 3D в хостовую систему гораздо сложнее, сказал Airlie. Для 2D хост просто передает данные, а для 3D можеть быть необходимость в вычитывании данных из оборудования назад, в гостевую систему.

Этот простейший драйвер предоставляет "ресурсы и способ наполнить их данными", сказал David; следующий шаг, это превратить ресурс в "передний объект", чтобы "люди могли его увидеть". Это сделано с помощью set_scanout(), что примерно тоже самое, что и выбор режима работы на обычном графическом устройстве. Также нужно вызвать flush_resource(), чтобы вызвать перерисовку OpenGL. Все это "основа простейшего GPU", большая часть которого уже включается в QEMU.

3D

Для 3D, поток небезопасных команд создается из Mesa в гостевой машине, и отправляется в драйвер с помощью команды SUBMIT_3D. Создаются 3D-контексты для каждой user-space программы из гостевой системы, и к ним присоединяются ресурсы. Это означает, что гостевая программа не обладает доступом к ресурсу, который она не создала, т.к. он просто не будет присоединен к 3D-контексту.

У потока 3D-команд есть несколько типов действий. Есть действия над состоянием объекта (создать, привязать, уничтожить), над различными типами шейдеров (включая вертексы, фрагменты и геометрию), по управлению поверхностями (surface) и текстурными объектами и т.п. Кроме того, есть также операции рендеринга, например draw, clear, и blit. Также есть набор команд, которые завершают набор 3D-команд. Всем этим нужно управлять в Virgil 3D.

Необходимо пять несвязанных компонентов, чтобы это все заработало в Linux, сказал Airlie. Два куска работают на хостовой машине: virtio GPU драйвер в QEMU и в библиотеке рендеринга. Причем, последний, это довольно большая работа. Гостевое ядро должно обладать DRM/KMS (direct rendering manager/kernel mode setting) драйвером, который поддерживает virtio GPU. В user-space ему нужен Gallium3D-драйвер для Mesa, чтобы общаться с ядром, и может понадобиться device-dependent X (DDX) драйвер для X-сервера.

Когда Airlie начал работу над проектом Virgil 3D, QEMU поддерживал лишь Simple DirectMedia Layer (SDL) 1.2 для графики, и там не было поддержки нескольких мониторов. Это значило, что QEMU нужно было портировать на SDL 2.0. Эта работа уже включена в апстрим QEMU. А код virtio GPU находится "в чьем-то дереве исходников", и пока направляется на включение в QEMU.

Библиотека для рендеринга, это то, "где вся веселуха", сказал он. Она получает поток команд, и превращает их в вызовы OpenGL API. Она также преобразовывает шейдеры в GLSL (язык для шейдеров, использующийся в OpenGL).

В рабочей конфигурации используется SPICE, чтобы общаться с виртуальной машиной QEMU, запущенной в libvirt. Это значит, что только клиент удаленного десктопа напрямую общается с графическим железом, что не то, что планировалось. Хотелось бы, чтобы QEMU тоже общался с железом.

Чтобы этого добиться, код использует dma_buf фичу ядра и передает файловые дескрипторы из QEMU в клиент удаленного десктопа и обратно. Однако SPICE использует TCP, а дескрипторы могут передаваться лишь по Unix-сокетам. Так что пока David подкрутил кое-какие права доступа у Unix-сокетов, временно назначив им права 777, чтобы хоть как то все это запустить.

Есть некоторые проблемы с OpenGL, которые надо поправить, включая то, как работать с фичами GL 3.1, которые используются редко, и которые непросто реализовать. Если на хостовой машине что-то использует GL 3.1, то Virgil 3D будет нужно как-то это обрабатывать, но GL 3.1 сейчас не реализован для Linux (и для Apple, кому интересно). Много функциональности из 3.1 может быть реализовано с помощью других фич и команд OpenGL, так что их теоретически возможно эмулировать.

TODO-лист для Virgil 3D довольно короткий, сказал Airlie, но все пункты в нем "огромны". В список входят корректная обработка возможностей OpenGL, использование текстового представления шейдеров в формате TGSI (Tungsten Graphics Shader Infrastructure) вместо бинарного, используемого сейчас (что будет "проблематично"), уже упомянутая проблема с GL 3.1, многопоточность в GL-части QEMU, и, наконец, включение всего в апстрим.

Airlie завершил свое выступление демонстрашкой 3D-игры Xonotic, запущенной в виртуалке на его ноутбуке. Получилось, как он сказал, 60 fps, "по крайней мере". Он ответил на вопросы из зада, отметив, что использование протокола удаленного доступа по сети приведет к использованию видеосжатия на хостовой машине, и передаче результатов в программу-просмотрщик, а не прямую передачу 3D-объектов и команд. Он был бы рад ошибаться в этом, но в любом случае он попробует сделать передачу 3D-объектов по сети своим следующим проектом.

[Jake Edge, автор оригинальной статьи, хотел бы поблагодарить Linux Foundation за помощь в поездке в Chicago на LinuxCon North America.]

Richard Hughes анонсировал PackageKit 1.0.0. В этом релизе отказались от плагинов - от них лишь проблемы. Вся функциональность, которая хоть кем-то затребована, была перенесена в дерево проекта. Были удалены бэкенды для conary, opkg, smart, yum - их никто не поддерживал уже очень давно. Richard недавно собрал список проблем в имеющихся бэкендах, и его услышали - бэкенды для alpm, aptcc, hif, zypp были обновлены.

Alexandre Oliva написал статью о многопоточности и потокобезопасности в Glibc.

К сожалению, Glibc не полностью соответствует стандарту POSIX в терминах потокобезопасности. И, к еще большему сожалению, проблемы есть не только в расширениях Glibc, но и в реализации POSIX-стандартных функций. В Red Hat озаботились проблемой, и с прошлого года вели аудит функций Glibc на предмет соответствия стандарту. Сейчас работа завершена, в общем никаких открытий не сделано, но удалось составить список различий между POSIX и Glibc. Дальнейшие шаги пока определяются - порой POSIX не требует потокобезопасности, а в Glibc она реализована, но порой бывает и наоборот. В последнем случае, перед исправлением надо учесть API/ABI-совместимость.

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

Внимательные пользователи Fedora 21 и RHEL 7 уже заметили появление нового типа в SELinux - unconfined_service_t. Dan Walsh решил объяснить, что это за штука такая.

Каждый, кто хоть раз использовал SELinux, знает, что домен unconfined_t, это метка процесса, который не ограничивается (unconfined) [SELinux]. Но это не единственный неограничиваемый (unconfined) домен в SELinux. На самом деле, это домен по умолчанию пользователя, который залогинился в системе. Во многих случаях, нам стоит использовать тип unconfined_user_t, а не unconfined_t.

По умолчанию, существует довольно много неограниченных (unconfined) доменов в системе с SELinux Targeted. Мы их завели, чтобы пользователи могли запускать ПО/сервисы без вмешательства SELinux, если SELinux не знает о них. Вы можете просмотреть список всех неограниченных (unconfined) доменов в вашей системе с помощью этой команды:

seinfo -aunconfined_domain_type -x


В RHEL6 и старых версиях Fedora, мы запускали сервисы с типом initrc_t по умолчанию. Ну, конечно, если кто-нибудь не написал для них специальное правило. Тип initrc_t, это по умолчанию неограниченный (unconfined) домен, пока вы не отключаете unconfined.pp модуль. Запуск неизвестных сервисов, как initrc_t, позволяет администраторам запускать приложение даже если для него не было написано правила.

В RHEL6 есть такие правила:

init_t @initrc_exec_t -> initrc_t
init_t @bin_t -> initrc_t


Если администратор добавляет исполняемый файл в /usr/sbin или /usr/bin, то init-система может запустить этот сервис с типом initrc_t.

Однако, мы обнаружили проблему.

Проблема в том, что есть слишком много правил перехода из домена initrc_t в другой домен. Например, если программа, о которой мы ничего не знаем, запущена в домене initrc_t, и она запускает, например, rsync чтобы скопировать данные между серверами, то SELinux переведет программу в домен rsync_t, и всё поломается наглухо. SELinux ошибочно посчитает, что rsync был настроен в серверном режиме, не в клиентском. Другие правила перехода также приведут к поломкам.

Мы решили, что нам нужен новый неограниченный (unconfined) домен для запуска сервисов, и в котором не будет никаких правил перехода в другие домены. Поэтому мы создали домен unconfined_service_t. Теперь у нас есть такое правило:

init_t @bin_t -> unconfined_service_t


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

Иногда приложения устанавливаются в нестандартные директории внутри /usr или /opt (или в случае Oracle даже в /u01), что заканчивается маркировкой приложения как usr_t, поэтому мы добавили следующие правила перевода из домена в домен:

# sesearch -T -s init_t  | grep unconfined_service_t
type_transition init_t bin_t : process unconfined_service_t;
type_transition init_t usr_t : process unconfined_service_t;


Вы можете их найти уже в Fedora 21.

Подводя итог

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

Примечание:
Автор благодарен Simon Sekidde и Miroslav Grepl за помощь в создании этой заметки.

Страницы