ioctl_ns(2) - wariua/manpages-ko GitHub Wiki
ioctl_ns - 리λ μ€ λ€μμ€νμ΄μ€λ₯Ό μν ioctl() λμλ€
λ€μμ€νμ΄μ€ κ΄κ³(user_namespaces(7) λ° pid_namespaces(7) μ°Έκ³ )λ₯Ό μμλΌ μ μλλ‘ λ€μ ioctl(2)
λμμ μ 곡νλ€. νΈμΆ ννλ μ΄λ λ€.
new_fd = ioctl(fd, request);
κ° κ²½μ°μμ fd
λ /proc/[pid]/ns/*
νμΌμ κ°λ¦¬ν¨λ€. μ±κ³΅ μ λ λμ λͺ¨λ μ νμΌ λμ€ν¬λ¦½ν°λ₯Ό λ°ννλ€.
-
NS_GET_USERNS
(리λ μ€ 4.9λΆν°) -
fd
κ° κ°λ¦¬ν€λ λ€μμ€νμ΄μ€λ₯Ό μμ ν μ¬μ©μ λ€μμ€νμ΄μ€λ₯Ό κ°λ¦¬ν€λ νμΌ λμ€ν¬λ¦½ν°λ₯Ό λ°ννλ€. -
NS_GET_PARENT
(리λ μ€ 4.9λΆν°) -
fd
κ° κ°λ¦¬ν€λ λ€μμ€νμ΄μ€μ λΆλͺ¨ λ€μμ€νμ΄μ€λ₯Ό κ°λ¦¬ν€λ νμΌ λμ€ν¬λ¦½ν°λ₯Ό λ°ννλ€. κ³μΈ΅μ λ€μμ€νμ΄μ€(μ¦ PID λ€μμ€νμ΄μ€μ μ¬μ©μ λ€μμ€νμ΄μ€)μλ§ μ΄ λμμ΄ μ ν¨νλ€. μ¬μ©μ λ€μμ€νμ΄μ€μμNS_GET_PARENT
μNS_GET_USERNS
λ κ°μ μλ―Έμ΄λ€.
μ΄ λμλ€μ΄ λ°ννλ μ νμΌ λμ€ν¬λ¦½ν°λ O_RDONLY
λ° O_CLOEXEC
(execμμ λ«κΈ°, fcntl(2) μ°Έκ³ ) νλκ·Έλ‘ μ΄λ € μλ€.
λ°νλ νμΌ λμ€ν¬λ¦½ν°μ fstat(2) νλ©΄ μ»λ stat
ꡬ쑰체μ st_dev
(κ±°μ£Ό μ₯μΉ) λ° st_ino
(μμ΄λ
Έλ λ²νΈ) νλλ‘ μμ /λΆλͺ¨ λ€μμ€νμ΄μ€λ₯Ό μλ³νλ€. κ·Έ μμ΄λ
Έλ λ²νΈλ₯Ό λ€λ₯Έ /proc/[pid]/ns/{pid,user}
νμΌμ μμ΄λ
Έλ λ²νΈμ λ§μΆ° λ΄μ μμ /λΆλͺ¨ λ€μμ€νμ΄μ€μΈμ§λ₯Ό μμλΌ μ μλ€.
μ΄λ μͺ½ ioctl(2)
λμμ΄λ λ€μ μ€λ₯λ‘ μ€ν¨ν μ μλ€.
EPERM
- μμ²ν λ€μμ€νμ΄μ€κ° νΈμΆμμ λ€μμ€νμ΄μ€ λ²μ λ°μ μλ€. μλ₯Ό λ€μ΄ μμ μ¬μ©μ λ€μμ€νμ΄μ€κ° νΈμΆμμ νμ¬ μ¬μ©μ λ€μμ€νμ΄μ€μ μ‘°μμ΄λ©΄ μ΄ μ€λ₯κ° λ°μν μ μλ€. μ΅μ΄ μ¬μ©μ λ΄μ§ PID λ€μμ€νμ΄μ€μ λΆλͺ¨λ₯Ό μ»μΌλ €κ³ ν λμλ λ°μν μ μλ€.
ENOTTY
- ν 컀λ λ²μ μμ λμμ μ§μνμ§ μλλ€.
μΆκ°λ‘ NS_GET_PARENT
λμμ΄ λ€μ μ€λ₯λ‘ μ€ν¨ν μ μλ€.
EINVAL
-
fd
κ° λΉκ³μΈ΅μ λ€μμ€νμ΄μ€λ₯Ό κ°λ¦¬ν€κ³ μλ€.
μ΄ λμλ€μ μ¬μ© μμλ EXAMPLE μ μ°Έκ³ .
NS_GET_NSTYPE
λμ(리λ
μ€ 4.11λΆν° μ¬μ© κ°λ₯)μ μ΄μ©ν΄ νμΌ λμ€ν¬λ¦½ν° fd
κ° κ°λ¦¬ν€λ λ€μμ€νμ΄μ€μ μ νμ μμλΌ μ μλ€.
nstype = ioctl(fd, NS_GET_NSTYPE);
fd
λ /proc/[pid]/ns/*
νμΌμ κ°λ¦¬ν¨λ€.
λ°ν κ°μ λ€μμ€νμ΄μ€λ₯Ό λ§λ€κΈ° μν΄ clone(2)μ΄λ unshare(2)μ μ§μ ν μ μλ CLONE_NEW*
κ°λ€ μ€ νλμ΄λ€.
NS_GET_OWNER_UID
λμ(리λ
μ€ 4.11λΆν° μ¬μ© κ°λ₯)μ μ΄μ©ν΄ μ¬μ©μ λ€μμ€νμ΄μ€λ₯Ό μμ ν μ¬μ©μ IDλ₯Ό (μ¦ μ¬μ©μ λ€μμ€νμ΄μ€λ₯Ό μμ±ν νλ‘μΈμ€μ μ€ν¨ μ¬μ©μ IDλ₯Ό) μμλΌ μ μλ€. λ€μμ²λΌ νΈμΆνλ€.
uid_t uid;
ioctl(fd, NS_GET_OWNER_UID, &uid);
fd
λ /proc/[pid]/ns/user
νμΌμ κ°λ¦¬ν¨λ€.
μΈ λ²μ§Έ μΈμκ° κ°λ¦¬ν€λ uid_t
λ‘ μμ μ¬μ©μ IDκ° λ°νλλ€.
μ΄ λμμ΄ λ€μ μ€λ₯λ‘ μ€ν¨ν μ μλ€.
EINVAL
-
fd
κ° μ¬μ©μ λ€μμ€νμ΄μ€λ₯Ό κ°λ¦¬ν€κ³ μμ§ μλ€.
μμ ioctl()
λμλ€ μ΄λ κ²μ΄λ λ€μ μ€λ₯λ₯Ό λ°νν μ μλ€.
ENOTTY
-
fd
κ°/proc/[pid]/ns/*
νμΌμ κ°λ¦¬ν€κ³ μμ§ μλ€.
μ΄ νμ΄μ§μμ μ€λͺ νλ λ€μμ€νμ΄μ€ λ° λμλ€μ 리λ μ€ μ μ©μ΄λ€.
μλ μλ μμ νλ‘κ·Έλ¨μμλ μμ μ€λͺ
ν ioctl(2)
λμλ€μ μ¬μ©ν΄ κ°λ¨ν λ€μμ€νμ΄μ€ κ΄κ³ νμμ μννλ€. λ€μ μ
Έ μΈμ
λ€μ μ΄ νλ‘κ·Έλ¨μ λ€μν μ¬μ© λ°©μμ λ³΄μ¬ μ€λ€.
μ΅μ΄ μ¬μ©μ λ€μμ€νμ΄μ€μ λΆλͺ¨λ₯Ό μ»μΌλ €κ³ μλνλ©΄ λΆλͺ¨κ° μμΌλ―λ‘ μ€ν¨νλ€.
$ ./ns_show /proc/self/ns/user p
The parent namespace is outside your namespace scope
μλ‘μ΄ μ¬μ©μ λ° UTS λ€μμ€νμ΄μ€ λ΄μμ sleep(1)
μ μ€ννλ νλ‘μΈμ€λ₯Ό λ§λ λ€. κ·Έλ¦¬κ³ μ UTS λ€μμ€νμ΄μ€κ° μ μ¬μ©μ λ€μμ€νμ΄μ€μ μ°κ³λΌ μμμ 보μΈλ€.
$ unshare -Uu sleep 1000 &
[1] 23235
$ ./ns_show /proc/23235/ns/uts u
Device/Inode of owning user namespace is: [0,3] / 4026532448
$ readlink /proc/23235/ns/user
user:[4026532448]
κ·Έλ¦¬κ³ μ μμ μ μ¬μ©μ λ€μμ€νμ΄μ€μ λΆλͺ¨κ° μ΅μ΄ μ¬μ©μ λ€μμ€νμ΄μ€μμ 보μΈλ€.
$ readlink /proc/self/ns/user
user:[4026531837]
$ ./ns_show /proc/23235/ns/user p
Device/Inode of parent namespace is: [0,3] / 4026531837
μ μ¬μ©μ λ€μμ€νμ΄μ€μμ μ Έμ μμνλ€. κ·Έλ¦¬κ³ κ·Έ μ Έ λ΄μμ λΆλͺ¨ μ¬μ©μ λ€μμ€νμ΄μ€λ₯Ό μμλΌ μ μμμ 보μΈλ€. λ§μ°¬κ°μ§λ‘ (μ΅μ΄ μ¬μ©μ λ€μμ€νμ΄μ€μ μ°κ³λΌ μλ) UTS λ€μμ€νμ΄μ€λ μμλΌ μ μλ€.
$ PS1="sh2$ " unshare -U bash
sh2$ ./ns_show /proc/self/ns/user p
The parent namespace is outside your namespace scope
sh2$ ./ns_show /proc/self/ns/uts u
The owning user namespace is outside your namespace scope
/* ns_show.c
Licensed under the GNU General Public License v2 or later.
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/sysmacros.h>
#ifndef NS_GET_USERNS
#define NSIO 0xb7
#define NS_GET_USERNS _IO(NSIO, 0x1)
#define NS_GET_PARENT _IO(NSIO, 0x2)
#endif
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);
}
/* argv[1]μ μ§μ λ 'ns' νμΌμ λν νμΌ λμ€ν¬λ¦½ν° μ»κΈ° */
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("The owning user namespace is outside "
"your namespace scope\n");
else
perror("ioctl-NS_GET_USERNS");
exit(EXIT_FAILURE);
}
if (fstat(userns_fd, &sb) == -1) {
perror("fstat-userns");
exit_EXIT_FAILURE);
}
printf("Device/Inode of owning user namespace is: "
"[%lx,%lx] / %ld\n",
(long) major(sb.st_dev), (long) minor(sb.st_dev),
(long) 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't 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("Device/Inode of parent namespace is: [%lx,%lx] / %ld\n",
(long) major(sb.st_dev), (long) minor(sb.st_dev),
(long) sb.st_ino);
close(parent_fd);
}
exit(EXIT_SUCCESS);
}
fstat(2), ioctl(2)
, proc(5), namespaces(7)
2019-03-06