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); }
Русский перевод этой страницы руководства был сделан 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 |