ioctl_ns(2) | System Calls Manual | ioctl_ns(2) |
ioctl_ns - операции ioctl() для пространств имён Linux
Следующие операции ioctl(2) позволяют определить порядок отношений между пространствами имён (смотрите user_namespaces(7) и pid_namespaces(7)). Форма вызовов:
new_fd = ioctl(fd, request);
Здесь в каждом случае fd ссылается на файл /proc/pid/ns/*. При успешном выполнении обе операции возвращают новый файловый дескриптор.
Новый файловый дескриптор, возвращаемый этими операциями, открывается с флагами O_RDONLY и O_CLOEXEC (close-on-exec; смотрите fcntl(2)).
Применив fstat(2) к возвращаемому файловому дескриптору, можно получить структуру stat, в которой поля st_dev (подлежащее устройство) и st_ino (номер иноды) вместе отождествляют владельческое/родительское пространство имён. Этот номер иноды можно сравнить с номером иноды другого файла /proc/pid/ns/{pid,user}, чтобы определить то же ли это владельческое/родительское пространство имён.
Эти операции ioctl(2) могут завершаться со следующими ошибками:
Также, операция NS_GET_PARENT может завершиться со следующей ошибкой:
Использование этих операций смотрите в разделе ПРИМЕРЫ.
Операция NS_GET_NSTYPE (доступна, начиная с Linux 4.11) позволяет определять тип пространства имён, на которое ссылается файловый дескриптор fd:
nstype = ioctl(fd, NS_GET_NSTYPE);
Значение fd ссылается на файл /proc/pid/ns/*.
Возвращаемым значением является одно из CLONE_NEW*, которое может указываться clone(2) или unshare(2) для создания пространства имён.
Операция NS_GET_OWNER_UID (доступна, начиная с Linux 4.11) позволяет определять пользовательский ID владельца пространства имён пользователя (т. е., эффективный пользовательский ID процесса, который создал пространство имён пользователя). Формат вызова:
uid_t uid; ioctl(fd, NS_GET_OWNER_UID, &uid);
Значение fd ссылается на файл /proc/pid/ns/user.
Возвращаемый пользовательский ID владельца находится в третьем аргументе с типом uid_t.
Данная операция может завершиться со следующей ошибкой:
Любая из этих операций ioctl() может завершаться со следующими ошибками:
Пространства имён и операции, описанные здесь, есть только в Linux.
В примере, показанном ниже, используются описанные выше операции ioctl(2), с помощью которых определяются отношения между пространствами имён. Далее показаны сценарии запуска этой программы.
Попытка определить родителя изначального пространства имён пользователя завершается ошибкой, так как родителя нет:
$ ./ns_show /proc/self/ns/user p Родительское пространство имён находится вне области вашего пространства имён
Создаётся процесс, выполняющий sleep(1), который располагается в новом пространстве имён пользователя и UTS, и показывается, что новое пространство имён UTS связано с новым пространством имён пользователя:
$ unshare -Uu sleep 1000 & [1] 23235 $ ./ns_show /proc/23235/ns/uts u Устройство/инода, владеющая пространством имён пользователя: [0,3] / 4026532448 $ readlink /proc/23235/ns/user user:[4026532448]
Теперь покажем, что родителем нового пространства имён пользователя из предыдущего примера является начальное пространство имён пользователя:
$ readlink /proc/self/ns/user user:[4026531837] $ ./ns_show /proc/23235/ns/user p Устройство/инода родительского пространства имён: [0,3] / 4026531837
Запустим оболочку в новом пространстве имён пользователя и покажем, что внутри оболочки родительское пространство имён пользователя невозможно определить. Также невозможно определить пространство имён UTS (которое связано с изначальным пространством имён пользователя).
$ PS1="sh2$ " unshare -U bash sh2$ ./ns_show /proc/self/ns/user p Родительское пространство имён находится вне области вашего пространства имён sh2$ ./ns_show /proc/self/ns/uts u Владеющее пространство имён пользователя находится вне области вашего пространства имён
/* ns_show.c Лицензируется под GNU General Public License v2 или новее. */ #include <errno.h> #include <fcntl.h> #include <linux/nsfs.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/sysmacros.h> #include <unistd.h> int main(int argc, char *argv[]) { int fd, userns_fd, parent_fd; struct stat sb; if (argc < 2) { fprintf(stderr, "Usage: %s /proc/[pid]/ns/[file] [p|u]\n", argv[0]); fprintf(stderr, "\nDisplay the result of one or both " "of NS_GET_USERNS (u) or NS_GET_PARENT (p)\n" "for the specified /proc/[pid]/ns/[file]. If neither " "'p' nor 'u' is specified,\n" "NS_GET_USERNS is the default.\n"); exit(EXIT_FAILURE); } /* Obtain a file descriptor for the 'ns' file specified in argv[1]. */ fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } /* получаем файловый дескриптор владельческого пространства имён пользователя и затем показываем номер иноды этого пространства имён */ if (argc < 3 || strchr(argv[2], 'u')) { userns_fd = ioctl(fd, NS_GET_USERNS); if (userns_fd == -1) { if (errno == EPERM) printf("Родительское пространство имён находится " "вне области вашего пространства имён\n"); else perror("ioctl-NS_GET_USERNS"); exit(EXIT_FAILURE); } if (fstat(userns_fd, &sb) == -1) { perror("fstat-userns"); exit(EXIT_FAILURE); } printf("Устройство/инода, владеющая пространством имён пользователя: " "[%x,%x] / %ju\n", major(sb.st_dev), minor(sb.st_dev), (uintmax_t) sb.st_ino); close(userns_fd); } /* получаем файловый дескриптор родительского пространства имён пользователя и затем показываем номер иноды этого пространства имён */ if (argc > 2 && strchr(argv[2], 'p')) { parent_fd = ioctl(fd, NS_GET_PARENT); if (parent_fd == -1) { if (errno == EINVAL) printf("Can' get parent namespace of a " "nonhierarchical namespace\n"); else if (errno == EPERM) printf("The parent namespace is outside " "your namespace scope\n"); else perror("ioctl-NS_GET_PARENT"); exit(EXIT_FAILURE); } if (fstat(parent_fd, &sb) == -1) { perror("fstat-parentns"); exit(EXIT_FAILURE); } printf("Устройство/инода родительского пространства имён: [%x,%x] / %ju\n", major(sb.st_dev), minor(sb.st_dev), (uintmax_t) sb.st_ino); close(parent_fd); } exit(EXIT_SUCCESS); }
fstat(2), ioctl(2), proc(5), namespaces(7)
Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
5 февраля 2023 г. | Linux man-pages 6.03 |