Архив за месяц: Октябрь 2015

ugidctl — модуль apache2

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

Аналогично модулю ядра, я упаковал его в rpm’ки для el6/el7

CentOS6 / RHEL6 (x86_64 only)

CentOS7 / RHEL7

Теперь можно делать в конфигурации apache вот так:

А на файловой системе вот так:

Читать далее

ugidctl – linux uid/gid control, итог

Для удобства использования модуля, я собрал его в rpm’ки для el6/el7.

CentOS6 / RHEL6 (x86_64 only)

CentOS7 / RHEL7

Читать далее

ugidctl – linux uid/gid control, часть 4

Теперь я буду собирать все элементы мозаики в кучу. Отдельного внимания разве что стоит механизм, которым я буду разрешать ядру переключать uid/gid или дополнительные группы, если мои проверки прошли успешно, но процесс непривелигерован. План такой:

  1. Даю процессу (задаче) CAP_SETUID/CAP_SETGID
  2. Вызываю sys_setuid/sys_setgid/sys_setgroups
  3. Отбираю CAP_SETUID/CAP_SETGID. Если на этой стадии что-то пошло не по плану, убиваю процесс SIGKILL‘ом — ему нельзя позволить дальше работать с повышенными привилегиями

Читать далее

ugidctl – linux uid/gid control, часть 3

Пора придумать как хранить списки uid’ов и gid’ов в ядре. Из основных особенностей этих списков должны быть следующие:

  1. Списки могут быть большими, например 1 млн. записей.
  2. Списки будут содержать только уникальные значения.
  3. По спискам нужно эффективно искать элементы.
  4. На входе списки могут содержать дублирующиеся элементы, могут быть не отсортированными. Другими словами сортировка и исключение дубликатов должны быть на стадии сохранения.

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

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

ugidctl — linux uid/gid control, часть 2

В прошлом посте я уже сделал небольшой модуль ядра, который при инициализации находит адреса обработчиков системных вызовов setuid(2), setgid(2) и setgroups(2). Пора в него добавить средства коммуникации с usersapce окружением. Выбор механизмов достаточно широк, но я решил решил остановиться на старом и добром ioctl(2). Он позволяет передавать адрес буфера с данными при вызове и возвращать статус операции в виде int’а. Назову char-device соответственно — /dev/ugidctl.

Теперь пора придумать протокол общения userspace-окружения с ядром. Разделю его на 2 части. Первые несколько вызовов будут работать когда вызывающий процесс обладает правами рута, т.е. в моем случае «взведены» CAP_SETUID и CAP_SETGID. Эти вызовы будут инициализировать список uid’ов и gid’ов, между которыми процесс сможет свободно переключаться, будучи непривилегированным. Остальная часть вызовов будет непосредственно проверять права и обращаться к sys_setuid, sys_setgid и sys_setgroups. В качестве дополнительной защиты введу случайный ключ, который процесс может получить только во время стадии инициализации ugidctl и будет обязан предоставлять в процессе переключения при каждом вызове. Также ограничу процессы, которые могут совершать переключения проверкой PID’а (идентификатора процесса), PGID’а (идентификатора группы процессов) или SID’а (идентификатора сессии), потому как открытый файловый дескриптор моего устройства процесс может намеренно или случайно передать другому.
Читать далее

ugidctl — linux uid/gid control, часть 1

Всем привет!

Буду делать механизм, позволяющий в userspace одному процессу относительно безопасно прыгать между заранее определенными uid’ами и gid’ами.

Должно выйти что-то типа такого:

К сожалению CAP_SETUID/CAP_SETGID не позволяют ограничить список пользователей, поэтому буду делать модуль ядра.
Читать далее