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

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

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

История[править | править код]

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

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

Появление каждого пространства имён
Пространство имён Версия ядра Год
Файловая система (Mount) 2.4.19 2002
UTS 2.6.19 2006
ID процессов (PID) 2.6.24 2008
Сети (Network) 2.6.29 2009
Межпроцессное взаимодействие (IPC) 2.6.30 2009
Пользовательские ID (User) 3.8 2013

Виды пространства имён[править | править код]

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

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

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

Файловая система (Mount)[править | править код]

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

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

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

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

UTS[править | править код]

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

Система характеризуется системным вызовом 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[1].

ID процессов (PID)[править | править код]

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

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

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

Сети (Network)[править | править код]

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

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

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

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

Межпроцессное взаимодействие (IPC)[править | править код]

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

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

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

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

Пользовательские ID (User)[править | править код]

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

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

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

Применение в контейнерах[править | править код]

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

Изоляция процессов[править | править код]

Технология контейнеризации обеспечивает изоляцию процессов путем переноса процессов, запущенных в контейнере, в собственное пространство имен и ограничения прав и видимости процессов, запущенных в других контейнерах и на самой хостовой машине.  Этот механизм работает при поддержке пространства имён 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[17] – это сетевой протокол, созданный для взаимодействия приложений в кластерных системах. Использования такого метода взаимодействия нарушает изоляцию IPC между контейнерами.

Список известных уязивомстей, связанных с пространствами имён:

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

Примечания[править | править код]

  1. 1 2 3 4 5 6 7 8 Namespaces in operation, part 1: namespaces overview [LWN.net]. lwn.net. Проверено 8 декабря 2017.
  2. jail, section 9.. docs.freebsd.org. Проверено 11 декабря 2017.
  3. 1 2 User namespaces progress [LWN.net]. lwn.net. Проверено 11 декабря 2017.
  4. 1 2 Advanced Topics - Linux Kernel Networking: Implementation and Theory (2014) (EN-US). apprize.info. Проверено 11 декабря 2017.
  5. Separation Anxiety: A Tutorial for Isolating Your System with Linux Namespaces. Toptal Engineering Blog. Проверено 11 декабря 2017.
  6. uname(2) - Linux manual page. man7.org. Проверено 8 декабря 2017.
  7. pid_namespaces(7) - Linux manual page. man7.org. Проверено 5 декабря 2017.
  8. PID namespaces in the 2.6.24 kernel [LWN.net]. lwn.net. Проверено 8 декабря 2017.
  9. 1 2 3 4 namespaces(7) - Linux manual page. man7.org. Проверено 8 декабря 2017.
  10. Network namespaces [LWN.net]. lwn.net. Проверено 8 декабря 2017.
  11. svipc(7) - Linux manual page. man7.org. Проверено 17 декабря 2017.
  12. Alexey V. Pautov. Энциклопедия программиста Linux. 6 Межпроцессовые коммуникации LINUX (рус.). rus-linux.net. Проверено 17 декабря 2017.
  13. user_namespaces(7) - Linux manual page. man7.org. Проверено 11 декабря 2017.
  14. Linux Containers - LXC - Introduction (англ.). linuxcontainers.org. Проверено 8 декабря 2017.
  15. Docker security (англ.). Docker Documentation. Проверено 8 декабря 2017.
  16. Elena Reshetova, Janne Karhunen, Thomas Nyman, N. Asokan. Security of OS-level virtualization technologies: Technical report // arXiv:1407.4245 [cs]. — 2014-07-16.
  17. TIPC Home Page. tipc.sourceforge.net. Проверено 11 декабря 2017.
  18. NVD - CVE-2013-1956. nvd.nist.gov. Проверено 11 декабря 2017.
  19. CVE-2013-1957 : The clone_mnt function in fs/namespace.c in the Linux kernel before 3.8.6 does not properly restrict changes to the MNT_. www.cvedetails.com. Проверено 11 декабря 2017.
  20. [https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-1959 CVE - CVE-2013-1959] (англ.). cve.mitre.org. Проверено 11 декабря 2017.
  21. NVD - CVE-2013-1858. nvd.nist.gov. Проверено 11 декабря 2017.
  22. CVE-2014-5206 : The do_remount function in fs/namespace.c in the Linux kernel through 3.16.1 does not maintain the MNT_LOCK_READONLY bit. www.cvedetails.com. Проверено 11 декабря 2017.

Ссылки[править | править код]