unshare(2)

ИМЯ
unshare - отделяет части процесса контекста выполнения

БИБЛИОТЕКА
Стандартная библиотека языка C (libc, -lc)

СИНТАКСИС
#define _GNU_SOURCE
#include <sched.h>

int unshare(int flags);

ОПИСАНИЕ
Вызов unshare() позволяет процессу (или потоку) отделить части своего контекста выполнения, которые используются совместно с другими процессами (или потоками). Часть контекста выполнения, например пространство имён монтирования, неявно делается общей при создании нового процесса с помощью fork(2) или vfork(2), в то время как другие части, такие как виртуальная память, могут стать общими по явному запросу при создании процесса или потока с помощью clone(2).

Основное предназначение unshare() — позволить процессу контролировать свой общий контекст выполнения без создания нового процесса.

Значение аргумента flags представляет собой битовую маску, в которой указывается какие части контекста выполнения должны перестать быть общими. Значение составляется из нескольких следующих констант (через OR):

CLONE_FILES
    Обратный эффект флагу CLONE_FILES для clone(2). Отделяет таблицу файловых дескрипторов таким образом, что вызывающий процесс больше не имеет общих файловых дескрипторов с другими процессами.

CLONE_FS
    Обратный эффект флагу CLONE_FS для clone(2). Отделяет атрибуты файловой системы таким образом, что вызывающий процесс больше не имеет общих атрибутов корневого каталога (chroot(2)), текущего каталога (chdir(2)) и umask (umask(2)) с другими процессами.

CLONE_NEWCGROUP (начиная с Linux 4.6)
    Этот флаг имеет действие подобное флагу CLONE_NEWCGROUP для clone(2). Отделяет пространство имён cgroup. Для использования CLONE_NEWCGROUP требуется мандат CAP_SYS_ADMIN.

CLONE_NEWIPC (начиная с Linux 2.6.19)
    Этот флаг имеет действие подобное флагу CLONE_NEWIPC для clone(2). Отделяет пространство имён IPC таким образом, что вызывающий процесс будет иметь свою личную копию пространства имён IPC, неиспользуемую другими процессами. Задание данного флага автоматически устанавливает флаг CLONE_SYSVSEM. Для использования CLONE_NEWIPC требуется мандат CAP_SYS_ADMIN.

CLONE_NEWNET (начиная с Linux 2.6.24)
    Этот флаг имеет действие подобное флагу CLONE_NEWNET для clone(2). Отделяет сетевое пространство имён таким образом, что вызывающий процесс будет иметь свою личную копию сетевого пространства имён, неиспользуемую другими процессами. Для использования CLONE_NEWNET требуется мандат CAP_SYS_ADMIN.

CLONE_NEWNS
    Этот флаг имеет действие подобное флагу CLONE_NEWNS для clone(2). Отделяет пространство имён монтирования таким образом, что вызывающий процесс будет иметь свою личную копию данного пространства имён, неиспользуемую другими процессами. Задание данного флага автоматически устанавливает флаг CLONE_FS. Для использования CLONE_NEWNS требуется мандат CAP_SYS_ADMIN. Дополнительная информация доступна в mount_namespaces(7).

CLONE_NEWPID (начиная с Linux 3.8)
    Данный флаг позволяет то же что и CLONE_NEWPID у clone(2). Выполняется отключение от пространства имён PID; вызывающий процесс создаёт новое пространство имён PID для своих потомков, которые до этого не были объединены с существующим процессом. Вызывающий процесс не перемещается в новое пространство имён. Первый потомок, созданный вызывающим процессом, будет иметь ID процесса 1 и считаться init(1) в новом пространстве имён. Также флаг CLONE_NEWPID автоматически подразумевает CLONE_THREAD. Для использования CLONE_NEWPID требуется мандат CAP_SYS_ADMIN. Подробней смотрите pid_namespaces(7).

CLONE_NEWTIME (начиная с Linux 5.6)
    Unshare the time namespace, so that the calling process has a new time namespace for its children which is not shared with any previously existing process. The calling process is not moved into the new namespace. Use of CLONE_NEWTIME requires the CAP_SYS_ADMIN capability. For further information, see time_namespaces(7).

CLONE_NEWUSER (начиная с Linux 3.8)
    Данный флаг позволяет то же что и CLONE_NEWUSER у clone(2). Выполняется отключение от пользовательского пространства имён; вызывающий процесс перемещается в новое пользовательское пространство имён, которое до этого не был общим для существующего процесса. Как потомок процесса, созданный clone(2) с флагом CLONE_NEWUSER, вызывающий получает полный набор мандатов в новом пользовательском пространстве имён.

    Для CLONE_NEWUSER требуется, чтобы вызывающий процесс не имел нитей; указание CLONE_NEWUSER автоматически подразумевает CLONE_THREAD. Начиная с Linux 3.9, CLONE_NEWUSER также автоматически подразумевает CLONE_FS. Для CLONE_NEWUSER требуется, чтобы ID пользователя и группы вызывающего процесса отображались в ID пользователя и группы в пользовательском пространстве имён вызывающего процесса на момент вызова.

    Дополнительную информацию о пространствах имён пользователя смотрите в user_namespaces(7).

CLONE_NEWUTS (начиная с Linux 2.6.19)
    Этот флаг имеет действие подобное флагу CLONE_NEWUTS для clone(2). Отделяет пространство имён UTS IPC таким образом, что вызывающий процесс будет иметь свою личную копию пространства имён UTS, неиспользуемую другими процессами. Для использования CLONE_NEWUTS требуется мандат CAP_SYS_ADMIN.

CLONE_SYSVSEM (начиная с Linux 2.6.26)
    С данным флагом выполняется обратное действие clone(2) с флагом CLONE_SYSVSEM. Выполняется отмена изменения значений семафоров System V (semadj) таким образом, что вызывающий процесс получает новый пустой список semadj, который не является общим ни с одним другим процессом. Если это последний процесс, который ссылается на текущий список semadj процесса, то изменения (adjustments) в этом списке применяются к соответствующим семафорам как описано в semop(2).

Также в flags могут быть указаны флаги CLONE_THREAD, CLONE_SIGHAND и CLONE_VM, если вызывающий состоит из одной нити (т. е., он не делит своё адресное пространство с другим процессом или нитью). Иначе данные флаги не работают (также заметим, что указание CLONE_THREAD автоматически подразумевает CLONE_VM, а указание CLONE_VM автоматически подразумевает CLONE_SIGHAND). Если процесс состоит из нескольких нитей, то использование данных флагов приведёт к ошибке.

Если значение flags равно нулю, то unshare() ничего не делает, то есть в контексте выполнения вызывающего процесса ничего не изменяется.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. При ошибке возвращается -1, а errno присваивается значение ошибки.

ОШИБКИ

EINVAL
    В значении flags установлен недопустимый бит.

EINVAL
    В flags указан CLONE_THREAD, CLONE_SIGHAND или CLONE_VM, а вызывающий состоит из нескольких нитей.

EINVAL
    Указан флаг CLONE_NEWIPC в flags, но ядро собрано без параметров CONFIG_SYSVIPC и CONFIG_IPC_NS.

EINVAL
    Указан флаг CLONE_NEWNET в flags, но ядро собрано без параметра CONFIG_NET_NS.

EINVAL
    Указан флаг CLONE_NEWPID в flags, но ядро собрано без параметра CONFIG_PID_NS.

EINVAL
    Указан флаг CLONE_NEWUSER в flags, но ядро собрано без параметра CONFIG_USER_NS.

EINVAL
    Указан флаг CLONE_NEWUTS в flags, но ядро собрано без параметра CONFIG_UTS_NS.

EINVAL
    Указан флаг CLONE_NEWPID в flags, но процесс был ранее вызван unshare() с флагом CLONE_NEWPID.

ENOMEM
    Не удалось выделить достаточно памяти для копирования части контекста вызывающего, которая должна быть отделена.

ENOSPC (начиная с Linux 3.7)
    В флагах указан CLONE_NEWPID, но вызов привёл бы к превышению ограничения на количество вложенных имён PID; смотрите pid_namespaces(7).

ENOSPC (начиная с Linux 4.9; до этого EUSERS)
    Флаг CLONE_NEWUSER указан в flags, и вызов привёл бы к превышению ограничения на количество вложенных пользовательских пространств имён. Смотрите user_namespaces(7).

    В этом случае в Linux 3.11 по Linux 4.8 возвращалась ошибка EUSERS.

ENOSPC (начиная с Linux 4.9)
    Одним из значений в flags задаётся создание нового пространства пространства имён пользователя, но это превысило бы ограничение, определённое в соответствующем файле в каталоге /proc/sys/user. Дополнительную информацию смотрите в namespaces(7).

EPERM
    Вызывающий процесс не имеет требуемых привилегий для этой операции.

EPERM
    Флаг CLONE_NEWUSER указан в flags, но эффективный пользовательский ID или эффективный ID группы вызывающего не отображён в родительское пространство имён (смотрите user_namespaces(7)).

EPERM (начиная с Linux 3.9)
    В flags был указан флаг CLONE_NEWUSER и вызывающий выполняется в окружении chroot (т. е. корневой каталог вызывающего не совпадает с корневым каталогом пространства имён монтирования, в котором он находится).

EUSERS (Linux 3.11 по Linux 4.8)
    Флаг CLONE_NEWUSER указан в flags, и вызов привёл бы к превышению ограничения на количество вложенных пользовательских пространств имён. Смотрите описание ошибки ENOSPC, представленное выше.

СТАНДАРТЫ
Linux.

ИСТОРИЯ
Linux 2.6.16.

ПРИМЕЧАНИЯ
Не все атрибуты процесса, которые могут использоваться совместно при создании нового процесса с помощью clone(2), могут быть отделены с помощью unshare(). В частности, начиная с ядра 3.8 в unshare() не реализована поддержка флагов, которые были имели обратное действие CLONE_SIGHAND, CLONE_THREAD или CLONE_VM. Эти возможности могут быть добавлены позднее, если потребуется.

Creating all kinds of namespace, except user namespaces, requires the CAP_SYS_ADMIN capability. However, since creating a user namespace automatically confers a full set of capabilities, creating both a user namespace and any other type of namespace in the same unshare() call does not require the CAP_SYS_ADMIN capability in the original namespace.

ПРИМЕРЫ
Программа, представленная далее, предоставляет простую реализацию команды unshare(1), которая отключает использование одного или более пространств имён и выполняет команду, переданную в аргументах командной строки. Вот пример использования этой программы; запускается оболочка в новом пространстве имён монтирования и проверяется, что первоначальная оболочка и новая оболочка находятся в разных пространствах имён монтирования:

    $ readlink /proc/$$/ns/mnt
    mnt:[4026531840]
    $ sudo ./unshare -m /bin/bash
    # readlink /proc/$$/ns/mnt
    mnt:[4026532325]

Различающийся вывод двух команд readlink(1) показывает, что две оболочки находятся в разных пространствах имён монтирования.

  Исходный код программы
    /* unshare.c

       A simple implementation of the unshare(1) command: unshare
       namespaces and execute a command.
    */
    #define _GNU_SOURCE
    #include <err.h>
    #include <sched.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    static void
    usage(char *pname)
    {
        fprintf(stderr, "Usage: %s [options] program [arg...]\n", pname);
        fprintf(stderr, "Options can be:\n");
        fprintf(stderr, "    -C   unshare cgroup namespace\n");
        fprintf(stderr, "    -i   unshare IPC namespace\n");
        fprintf(stderr, "    -m   unshare mount namespace\n");
        fprintf(stderr, "    -n   unshare network namespace\n");
        fprintf(stderr, "    -p   unshare PID namespace\n");
        fprintf(stderr, "    -t   unshare time namespace\n");
        fprintf(stderr, "    -u   unshare UTS namespace\n");
        fprintf(stderr, "    -U   unshare user namespace\n");
        exit(EXIT_FAILURE);
    }

    int
    main(int argc, char *argv[])
    {
        int flags, opt;

        flags = 0;

        while ((opt = getopt(argc, argv, "CimnptuU")) != -1) {
            switch (opt) {
            case 'C': flags |= CLONE_NEWCGROUP;     break;
            case 'i': flags |= CLONE_NEWIPC;        break;
            case 'm': flags |= CLONE_NEWNS;         break;
            case 'n': flags |= CLONE_NEWNET;        break;
            case 'p': flags |= CLONE_NEWPID;        break;
            case 't': flags |= CLONE_NEWTIME;       break;
            case 'u': flags |= CLONE_NEWUTS;        break;
            case 'U': flags |= CLONE_NEWUSER;       break;
            default:  usage(argv[0]);
            }
        }

        if (optind >= argc)
            usage(argv[0]);

        if (unshare(flags) == -1)
            err(EXIT_FAILURE, "unshare");

        execvp(argv[optind], &argv[optind]);
        err(EXIT_FAILURE, "execvp");
    }

СМОТРИТЕ ТАКЖЕ
unshare(1), clone(2), fork(2), kcmp(2), setns(2), vfork(2), namespaces(7)

Файл Documentation/userspace-api/unshare.rst из дерева исходного кода ядра Linux (или Documentation/unshare.txt до Linux 4.12)

ПЕРЕВОД
Русский перевод этой страницы руководства разработал(и) Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy Ovchinnikov <dmitriyxt5@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Katrin Kutepova <blackkatelv@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (<debian-l10n-russian@lists.debian.org>).