Пространство имён (Linux)

Пространство имён (от ) — это функция ядра Linux, позволяющая изолировать и виртуализировать глобальные системные ресурсы множества процессов. Примеры ресурсов, которые можно виртуализировать: ID процессов, имена хостов, ID пользователей, доступ к сетям, межпроцессное взаимодействие и файловые системы. Одной из общих целей пространств имён является поддержка реализации контейнеров — инструмента для виртуализации на уровне операционной системы (а также других целей), обеспечивающего группу процессов иллюзией того, что они являются единственными процессами в системе. Поэтому одной из главных целей пространства имён является поддержка контейнеризации в Linux.

История 
Идеи, лежащие в основе механизма пространств имён исходят из ранних операционных систем. В Unix в 1979 году был добавлен системный вызов chroot() — как раз с целью обеспечить изоляцию и предоставить разработчикам отдельную от основной системы площадку для тестирования. В ядре Linux изоляция процессов была усовершенствована благодаря добавлению новых подсистем и новых системных вызовов.

Пространства имён Linux возникли в 2002 году в версии ядра 2.4.19. Дополнительные пространства имён были добавлены в 2006 году и продолжали добавляться в будущем. Достаточная функциональность для полной изоляции и безопасной работы контейнеров была завершена в ядре версии 3.8 с введением пространств имён пользователей.

Виды пространства имён 
Linux-система при старте инициализирует один экземпляр каждого типа пространства имён, кроме пространства имён файловой системы. После инициализации можно создать или объединить дополнительные пространства имён.

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

Функциональные возможности пространства имён одинаковы для всех типов: каждый процесс связан с пространством имён и может видеть или использовать только ресурсы, связанные с этим пространством имён, и, где это применимо, — с его потомками. Таким образом, каждый процесс (или его группа) может иметь уникальное представление о ресурсе. Изолированный ресурс зависит от типа пространства имён, созданного для данной группы процессов.

Файловая система (Mount) 
Пространство имён файловой системы — это независимое дерево файловой системы, ассоциированное с определённой группой процессов.

Каждое пространство имён предоставляет уникальный вид файловой системы для всех процессов, принадлежащим этому пространству.

При создании новых пространств, можно установить флаг для копирования списка точек монтирования из родительского пространства. Однако последующие операции по монтированию и демонтированию в одном пространстве никак не сказываются на других пространствах (в том числе — и на родительском, и на потомке). Но между пространствами можно установить связь «ведущий — ведомый», и тогда все действия, связанные с монтированием, в пространстве ведущего распространяются и на пространства, помеченные как ведомые. Обратные операции, то есть операции в пространстве ведомого, никак не влияют на пространство ведущего. Такая возможность позволяет сразу монтировать новое устройство в несколько пространств имён файловой системы, вместо монтирования в каждом отдельном пространстве.

Пространство имён файловой системы было первым типом пространств имён выполненных в версии Linux 2.4.19 в 2002 году.

UTS 
Пространство имён UTS (Unix Time Sharing) используется для изоляции двух конкретных элементов системы, относящихся к системному вызову uname().

Система характеризуется системным вызовом uname(). uname() возвращает структуру utsname, состоящую из 6 строк, описывающих текущую систему: sysname[], nodename[], release[], version[], machine[], domainname[]. При этом из них только два элемента изменяются во время выполнения, nodename[] и domainname[]. nodename[] это имя хоста системы, а domainname[] это доменное имя NIS. Пространство имен UTS изолирует эти два системных идентификатора nodename[] и domainname[]. В контейнеризации функция пространства имен UTS позволяет каждому контейнеру иметь свое имя хоста и имя домена.

Для существования нескольких экземпляров пространств имён UTS происходит выделение новых экземпляров структуры utsname в ядре для каждого экземпляра такого пространства и изменение системных вызовов, которые изменяют значения пространства, для поиска подходящего экземпляра структуры utsname в качестве текущего.

Пространство имён UTS впервые появилось сборке ядра Linux 2.6.19.

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

В новом пространстве имён первый процесс является инициализирующим или init-процессом для этого пространства и имеет PID 1. При завершении init-процесса ядро завершает все процессы, принадлежащие одному пространству через сигнал SIGKILL.

Пространство имён ID процессов впервые появилось в версии ядра 2.6.24. Однако оно было отмечено как «экспериментальное», с тем чтобы предотвратить его широкое развертывание дистрибьюторами, в то время как некоторые остающиеся вопросы решаются.

Сети (Network) 
Пространство имён для сетей предоставляет изоляцию систем ресурсов, связанных с сетями: сетевое оборудование, стеки протоколов IPv4 и IPv6, таблицы IP-маршрутизации, файрволы, номера портов (сокеты) и другие.

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

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

Впервые появилось в версии ядра 2.6.24. Однако было полностью закончено только в версии 2.6.29.

Межпроцессное взаимодействие (IPC) 
System V IPC включает в себя семафоры, разделяемую память и очереди сообщений. Каждый ресурс межпроцессного взаимодействия должен иметь свой уникальный идентификатор (ID). Это позволяет процессам, взаимодействующим между собой, обращаться к общему ресурсу. И для изоляции таких ресурсов было создано пространство имён IPC.

Каждое пространство имён IPC имеет свой собственный набор идентификаторов System V IPC и свою собственную систему очередей сообщений POSIX. Объекты, созданные в этом пространстве имён, видны всем процессам, состоящим в этом пространстве, и не видны всем остальным процессам в других пространствах имён.

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

Пространство имён IPC впервые было представлено в версии ядра 2.6.19 для семафоров и разделяемой памяти. В версии 2.6.30 также были добавлены очереди сообщений POSIX.

Пользовательские ID (User) 
Пространства имён пользователей изолируют ID пользователей и групп, корневой каталог, ключи и capabilities. Идентификаторы пользователя и группы процесса могут отличаться внутри и вне пространства имён пользователей. В частности, процесс может иметь непривилегированное ID пользователя вне пространства имён пользователей, пока в то же время иметь ID root внутри пространства, то есть процесс имеет полные привилегии для операций внутри пространства имён.

Пространства имён могу быть вложенными, это означает, что каждое пространство имён пользователя (за исключением инициализирующего пространства) имеет родительское пространство и может иметь ноль или несколько дочерних пространств. Ядро накладывает лимит в 32 вложенных уровня пространств имён пользователей начиная с версии 3.11.

Пространство имён пользователей впервые было представлено в версии ядра 3.8.

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

Изоляция процессов 
Технология контейнеризации обеспечивает изоляцию процессов путем переноса процессов, запущенных в контейнере, в собственное пространство имен и ограничения прав и видимости процессов, запущенных в других контейнерах и на самой хостовой машине. Этот механизм работает при поддержке пространства имён PID , которое изолирует пространство идентификаторов процесса контейнера от пространства хоста. Поскольку пространство имён PID иерархичное, то процесс может видеть только процессы в своем собственном пространстве имен, либо в его «дочернем» пространстве имен. Вследствие этого, после создания и присвоения пространства имен контейнеру, хостовая машина может видеть и взаимодействовать с пространством идентификаторов процесса контейнера, но процесс внутри контейнера не может видеть и что-либо делать с пространством хоста или другого контейнера.

Изоляция файловой системы 
Для достижения защищенности контейнеров и хостовой машины от нелегитимных процессов и модификаций с файловой системой необходима изоляция файловых систем.

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

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

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

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

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

Изоляция пользователей 
Только с появлением пространства имён пользователей стала возможна полная изоляция контейнеров от хостовой машины. Поскольку до появления этого пространства, пользователь имел ID 0 в контейнере, то есть был пользователем root в этом контейнере, и при этом же имел такой же ID внутри хостовой машины, что создавал большую угрозу для всей системы. И только благодаря пространству имён пользователей удалось разделить эти ID, то есть пользователь остается привилегированным внутри контейнера и при этом непривилегированным внутри хостовой машины.

Изоляция UTS 
Благодаря пространству имён UTS каждый контейнер может иметь свое собственное доменное имя NIS domainname[] и имя контейнера nodename[] . Это является важным фактором для многих приложений, веб-сервисов, логирования и других возможностей.

Безопасность 
Хотя пространство имён IPC покрывает большинство методов межпроцессных взаимодействий, существуют исключения. Таким исключением является Transparent Inter-Process Communication — это сетевой протокол, созданный для взаимодействия приложений в кластерных системах. Использование такого метода взаимодействия нарушает изоляцию IPC между контейнерами.

Список известных уязивомстей, связанных с пространствами имён:
 CVE-2013-1956: ядро Linux не проверяет наличие каталога chroot, отличающегося от корневого каталога пространства имен. Это уязвимость позволяет локальным пользователям обходить предполагаемые ограничения файловой системы с помощью сконструированного системного вызова.
 CVE-2013-1957: уязвимость позволяет локальным пользователям обходить предназначенное только для чтения свойство файловой системы, используя отдельное пространство имен файловой системы.
 CVE-2013-1959: уязвимость позволяет локальным пользователям получать права, открывая файл в рамках непривилегированного процесса, а затем изменяя файл в рамках привилегированного процесса. Известный экспойт.
 CVE-2013-1858: уязвимость позволяет локальным пользователям получать права путем вызова chroot и использования совместного доступа к каталогу / между родительским процессом и процессом-потомком.
 CVE-2014-5206: уязвимость позволяет локальным пользователям обойти ограничение «только для чтения», и обойти механизмы защиты «песочницы» с помощью команды mount -o remount в пространстве имен пользователя.

Примечания

Ссылки 
 Namespaces in operation, part 1: namespaces overview
 Network namespaces
 Multiple Instances of the Global Linux Namespaces
 NAMESPACES(7)
 MOUNT_NAMESPACES(7)
 PID_NAMESPACES(7)
 USER_NAMESPACES(7)
 Использование пространств имен команды mount
 Virtual Servers and Checkpoint/Restart in Mainstream Linux
 Understanding and Hardening Linux Containers
 Security of OS-level virtualization technologies

Ядро Linux