Как процесс может определить, что он находится в дочернем пространстве имен?

Вы должны вернуть manjaro systemd жесткий диск с домашним разделом. Вероятно, UUID находится в /etc/fstab, и этот раздел сейчас отключен.

Это большое и маленькое дело одновременно. Есть ли у вас причина для установки /homeснаружи? В противном случае вполне стандартно держать дома на «корне». Не /root, а /.

Неудача драматична, но потому, что «дом» отсутствует, это неудивительно.

5
09.04.2021, 12:39
1 ответ

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

Техническое описание

Примечание об ограничении ответственности

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


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

Пространства имен «Boot»

Начиная с ядра версии 3.8 до текущей последней стабильной версии версии 5.11(и текущей версии версии 5.12 -rc ), исходный ] Пространства имен IPC, UTS, user, PID, cgroup и time всегда имеют определенный жестко закодированный идентификатор, как указано ниже. Следовательно, мы можем с уверенностью предположить, что для этих типов пространств имен любой идентификатор пространства имен, превышающий фиксированный, может считаться дочерним пространством имен:

IPC    = 0xEFFFFFFF
UTS    = 0xEFFFFFFE
USER   = 0xEFFFFFFD
PID    = 0xEFFFFFFC
CGROUP = 0xEFFFFFFB
TIME   = 0xEFFFFFFA

Приведенный выше список взят из исходников версии 5.12 -rc6, но эти значения всегда были одинаковыми, начиная с версии 3.8, за исключением, конечно, пространств имен, которых вообще не существовало в версии 3.8 («cgroup» была добавлена ​​в версии 4.6, а «время» — в версии 5.6 ).

Обратите внимание, как эти исходные пространства имен были добавлены (за годы )со значениями, "растущими" вниз. И наоборот, все дочерние пространства имен принимают последовательные значения (по -требованию ), растущие вверх от0xF0000000.

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

Однако,позвольте мне повторить, что эти значения вообще не являются частью какого-либо официального API, доступного для пользовательского пространства(даже для ядра -пространства AFAICT ), поэтому они могут быть изменены в будущем .

Разработчики ядра могут даже сделать их динамическими или даже случайными. На самом деле, вы можете заметить, что пространства имен монтирования и сети отсутствуют в этом списке, потому что все пространства имен сети и монтирования, включая начальные, уже полностью динамические, и всегда принимать идентификаторы, начинающиеся с 0xF0000000, как и любое дочернее пространство имен. В результате, для начальных пространств имен mount и network все равно приходится выполнять некоторые эвристики даже в самых благоприятных условиях.

Пространство имен монтирования

По своему опыту я заметил, что идентификатор пространства имен начального монтирования всегда получает первое динамическое значение(0xF0000000). Предположительно, это связано с тем, что начальное пространство имен PID создает экземпляр общей файловой системы proc, таким образом извлекая -из первого пространства имен монтирования. В любом случае, идентификатор исходного пространства имен монтирования кажется легко предсказуемым, практически фиксированным, даже если он находится в динамическом диапазоне.

Сетевое пространство имен

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

Первое сетевое пространство имен создается как следствие любого процесса (, обычно PID 1 ), запрашивающего первую сетевую операцию с момента загрузки системы.Следовательно, каталог /proc/net/становится доступным, и в нем создаются файлы/каталоги, каждый со своим собственным номером инода, выделенным из одних и тех же (динамических )значений, используемых для идентификаторов пространства имен. Так получилось (по моему опыту на момент написания этой статьи ), что первое имя, созданное в ней, — это каталог stat. Следовательно, этот каталог принимает последний номер инода, сгенерированный непосредственно перед созданием экземпляра сетевого пространства имен. Таким образом, собственный идентификатор сетевого пространства имен равен /proc/net/statномеру инода + 1.

Естественно, что каталог /proc/net/stat, будучи на самом деле именем "пространства имен", как его видит произвольный процесс, не обязательно может относиться к исходному сетевому пространству имен . Это относится к начальному сетевому пространству имен, когда процесс, обращающийся к этому каталогу , живет в начальных пространствах имен (, т. е. это не -контейнеризованный процесс ), но в контейнеризованной среде, которая более вероятно, относятся к выделенному сетевому пространству имен, к которому принадлежит процесс, а не к исходному сетевому пространству имен.

Q:Итак, как процесс может попытаться угадать в общем, является ли его сетевое пространство имен фактически исходным?

A:Перечисляя рекурсивно все видимые не -pid файлы/каталоги в каталоге /procдля поиска номеров инодов, начиная с 0xF0000001до встречает первую дыру как минимум 2отсутствующих номеров инодов.

Многие не -файлы/каталоги pid в /procявляются (на сегодняшний день )общими для всех пространств имен PID, поскольку они связаны с основными функциями ядра (, например. статистика irq и т.д. ).Отверстие в их номерах инодов должно быть не менее 2 смежных номеров , потому что одно предназначено для каталога /proc/net/stat, созданного для исходного сетевого пространства имен, а другое — для самого исходного сетевого пространства имен. (также предполагается атомарное распределение между двумя ). В такой первой дыре будет лежать начальный идентификатор сетевого пространства имен. Сравните эту (дыру из )идентификаторов с собственным (или другим произвольным )идентификатором сетевого пространства имен, и (в наиболее распространенных случаях )вы наконец-то все установили.

Однако, даже для общих случаев, очевидно, что мы полагаемся на те не -имена pid, которые всегда видны для всех пространств имен PID и . ] имеют ту же нумерацию, что и идентификаторы пространств имен и , находящиеся в (почти )идеальной последовательности и , причем номера инодов /proc/net/*распределяются атомарно вместе с собственным идентификатором пространства имен. Все эти предположения могут оставаться верными сейчас, но вполне могут перестать быть верными в будущем просто потому, что такое поведение вовсе не является официальным API.

Кроме того, просто для того, чтобы еще больше указать на сложность этого вопроса, обратите внимание, что в /procпросматривается всегда пространство имен PID процесса, который смонтировал , который определенный каталог /proc, следовательно, не обязательно пространство имен PID процесса , читающего этот каталог /proc. Несоответствие между «установщиком» /procи «читателем» /procмаловероятно в здравой практике, но все же вполне возможно и легко приводит к непоследовательному анализу.


Некоторые самоуверенные соображения

За исключением начального пользовательского пространства имен, обнаружение которого очень просто 1 и также является частью официального API, обнаружение пространств имен представляет собой проблему, для решения которой требуется много усилий,если это вообще возможно, потому что не существует реального и всеобъемлющего API, поддерживающего его (, что предположительно сделано намеренно ради более полной изоляции ). Несколько лет назад в список пространств имён была добавлена ​​параioctl(2)операций, но они всё ещё достаточно ограничены, и я никак не мог понять (даже безумных )способов их использования для окончательного обнаружения.

На самом деле существует еще несколько простых приемов для определения пространств имен PID, но они также не являются официальным API. Посмотрите, например, что systemdлюди обсуждали также недавно по поводу своих инструментов. По-видимому, они тоже исследовали вопрос о том, что procномер устройства должен быть «3 или 4», но отказались от этой идеи, потому что заметили, что он не держит так много (и, возможно, когда-либо держался только в «солнечном свете». дневные» условия, какими бы обычными они ни были ). Они также исследовали, что PID 2 всегда является [kthreadd]и/или общее присутствие потоков ядра, что было бы неоспоримым признаком исходного пространства имен PID, но они также отказались от этой идеи, потому что монтирование procс hidepid=[12]игнорирует эту проверку. полностью.

Я бы сказал, что фундаментальная проблема с обнаружением пространств имен заключается в том, что они по своей сути произвольны и могут быть полностью заменены другими пространствами имен. Для всех типов пространств имен в ядре есть так называемые -«начальные» пространства имен, но первый процесс PID 1 (, даже тот, что в initramfs), может переопределить их, простоunshare(2)-переопределив все (или даже несколько )из них перед запуском любого другого процесса. Ясно, что при таких (не слишком )гипотетических условиях поиск начальных пространств имен теряет всякий полезный смысл, поскольку важны скорее «хостовые» пространства имен. Это пространства имен, в которых голая ОС (, т.е.основной PID 1 initпроцесс)работает после начальной загрузки, даже если такие «хостовые» пространства имен уже могут быть дочерними пространствами имен в отношении ядра. Я не говорю, что процессы initдействительно все время переопределяют начальные пространства имен, но в принципе они могут, и этого достаточно, чтобы вывести из строя любой инструмент обнаружения пространств имен -.

По моему мнению, дело также в том, что для большинства практических случаев вас на самом деле не интересуют произвольные пространства имен. Почти наверняка вас вообще не интересуют пространства имен UTS, IPC, cgroup и time, и, вероятно, даже пространства имен пользователя и PID. Если когда-либо, вас могут заинтересовать только пространства имен монтирования и сети, потому что они имеют отношение к доступу к данным и подключению. Пространство имен PID часто ищут много только потому, что пространство имен PID (гораздо больше, чем пространство имен пользователя ), обычно подразумевает контейнер в его более широком смысле, а «более широкий» контейнер просто что приносит с собой интересные пространства имен mount и network. К сожалению, эти последние сложнее всего отследить, что, вероятно, является причиной того, что инструменты обнаружения предпочитают искать пространства имен PID в надежде на слабую -связанную, но хорошую связь между ними и пространствами имен mount/network.

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

ХТХ


1.Просто прочитайте файл /proc/self/uid_mapи посмотрите, точно ли он сообщает 0 0 4294967295

3
28.04.2021, 22:54

Теги

Похожие вопросы