ioctl_ns(2) - wariua/manpages-ko GitHub Wiki

NAME

ioctl_ns - λ¦¬λˆ…μŠ€ λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό μœ„ν•œ ioctl() λ™μž‘λ“€

DESCRIPTION

λ„€μž„μŠ€νŽ˜μ΄μŠ€ 관계 μ•Œμ•„λ‚΄κΈ°

λ„€μž„μŠ€νŽ˜μ΄μŠ€ 관계(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κ°€ μ‚¬μš©μž λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό 가리킀고 μžˆμ§€ μ•Šλ‹€.

ERRORS

μœ„μ˜ ioctl() λ™μž‘λ“€ μ–΄λŠ 것이든 λ‹€μŒ 였λ₯˜λ₯Ό λ°˜ν™˜ν•  수 μžˆλ‹€.

ENOTTY
fdκ°€ /proc/[pid]/ns/* νŒŒμΌμ„ 가리킀고 μžˆμ§€ μ•Šλ‹€.

CONFORMING TO

이 νŽ˜μ΄μ§€μ—μ„œ μ„€λͺ…ν•˜λŠ” λ„€μž„μŠ€νŽ˜μ΄μŠ€ 및 λ™μž‘λ“€μ€ λ¦¬λˆ…μŠ€ μ „μš©μ΄λ‹€.

EXAMPLE

μ•„λž˜ μžˆλŠ” μ˜ˆμ‹œ ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” μœ„μ— μ„€λͺ…ν•œ 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);
}

SEE ALSO

fstat(2), ioctl(2), proc(5), namespaces(7)


2019-03-06

⚠️ **GitHub.com Fallback** ⚠️