6.9 KiB

PID Namespace

{{#include ../../../../banners/hacktricks-training.md}}

Basic Information

PID (Process IDentifier) 네임스페이스는 Linux 커널의 기능으로, 프로세스 격리를 제공하여 프로세스 그룹이 다른 네임스페이스의 PID와 분리된 고유한 PID 집합을 가질 수 있게 합니다. 이는 보안 및 자원 관리에 필수적인 프로세스 격리가 중요한 컨테이너화에서 특히 유용합니다.

새로운 PID 네임스페이스가 생성되면, 해당 네임스페이스의 첫 번째 프로세스는 PID 1이 할당됩니다. 이 프로세스는 새로운 네임스페이스의 "init" 프로세스가 되며, 네임스페이스 내의 다른 프로세스를 관리하는 역할을 합니다. 네임스페이스 내에서 생성된 각 후속 프로세스는 해당 네임스페이스 내에서 고유한 PID를 가지며, 이러한 PID는 다른 네임스페이스의 PID와 독립적입니다.

PID 네임스페이스 내의 프로세스 관점에서 볼 때, 동일한 네임스페이스의 다른 프로세스만 볼 수 있습니다. 다른 네임스페이스의 프로세스는 인식하지 못하며, 전통적인 프로세스 관리 도구(예: kill, wait 등)를 사용하여 상호작용할 수 없습니다. 이는 프로세스 간의 간섭을 방지하는 데 도움이 되는 격리 수준을 제공합니다.

How it works:

  1. 새로운 프로세스가 생성될 때(예: clone() 시스템 호출을 사용하여), 프로세스는 새로운 또는 기존의 PID 네임스페이스에 할당될 수 있습니다. 새로운 네임스페이스가 생성되면, 프로세스는 해당 네임스페이스의 "init" 프로세스가 됩니다.
  2. 커널새로운 네임스페이스의 PID와 부모 네임스페이스의 해당 PID 간의 매핑을 유지합니다(즉, 새로운 네임스페이스가 생성된 네임스페이스). 이 매핑은 커널이 필요할 때 PID를 변환할 수 있게 합니다, 예를 들어 서로 다른 네임스페이스의 프로세스 간에 신호를 보낼 때.
  3. PID 네임스페이스 내의 프로세스는 동일한 네임스페이스의 다른 프로세스만 보고 상호작용할 수 있습니다. 그들은 다른 네임스페이스의 프로세스를 인식하지 못하며, 그들의 PID는 네임스페이스 내에서 고유합니다.
  4. PID 네임스페이스가 파괴될 때(예: 네임스페이스의 "init" 프로세스가 종료될 때), 해당 네임스페이스 내의 모든 프로세스가 종료됩니다. 이는 네임스페이스와 관련된 모든 자원이 적절히 정리되도록 보장합니다.

Lab:

Create different Namespaces

CLI

sudo unshare -pf --mount-proc /bin/bash
Error: bash: fork: Cannot allocate memory

unshare-f 옵션 없이 실행될 때, Linux가 새로운 PID (Process ID) 네임스페이스를 처리하는 방식 때문에 오류가 발생합니다. 주요 세부사항과 해결책은 아래에 설명되어 있습니다:

  1. 문제 설명:
  • Linux 커널은 프로세스가 unshare 시스템 호출을 사용하여 새로운 네임스페이스를 생성할 수 있도록 허용합니다. 그러나 새로운 PID 네임스페이스를 생성하는 프로세스(이를 "unshare" 프로세스라고 함)는 새로운 네임스페이스에 들어가지 않으며, 오직 그 자식 프로세스만 들어갑니다.
  • %unshare -p /bin/bash%를 실행하면 /bin/bashunshare와 동일한 프로세스에서 시작됩니다. 결과적으로 /bin/bash와 그 자식 프로세스는 원래 PID 네임스페이스에 있습니다.
  • 새로운 네임스페이스에서 /bin/bash의 첫 번째 자식 프로세스는 PID 1이 됩니다. 이 프로세스가 종료되면, 다른 프로세스가 없을 경우 네임스페이스의 정리가 트리거됩니다. PID 1은 고아 프로세스를 입양하는 특별한 역할을 가지고 있습니다. 그러면 Linux 커널은 해당 네임스페이스에서 PID 할당을 비활성화합니다.
  1. 결과:
  • 새로운 네임스페이스에서 PID 1의 종료는 PIDNS_HASH_ADDING 플래그의 정리를 초래합니다. 이로 인해 새로운 프로세스를 생성할 때 alloc_pid 함수가 새로운 PID를 할당하는 데 실패하여 "Cannot allocate memory" 오류가 발생합니다.
  1. 해결책:
  • 이 문제는 unshare와 함께 -f 옵션을 사용하여 해결할 수 있습니다. 이 옵션은 unshare가 새로운 PID 네임스페이스를 생성한 후 새로운 프로세스를 포크하도록 만듭니다.
  • %unshare -fp /bin/bash%를 실행하면 unshare 명령 자체가 새로운 네임스페이스에서 PID 1이 됩니다. /bin/bash와 그 자식 프로세스는 이 새로운 네임스페이스 내에서 안전하게 포함되어 PID 1의 조기 종료를 방지하고 정상적인 PID 할당을 허용합니다.

unshare-f 플래그와 함께 실행되도록 함으로써 새로운 PID 네임스페이스가 올바르게 유지되어 /bin/bash와 그 하위 프로세스가 메모리 할당 오류 없이 작동할 수 있습니다.

새로운 /proc 파일 시스템 인스턴스를 마운트하면 --mount-proc 매개변수를 사용하여 새로운 마운트 네임스페이스가 해당 네임스페이스에 특정한 프로세스 정보에 대한 정확하고 격리된 뷰를 갖도록 보장합니다.

Docker

docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash

프로세스가 어떤 네임스페이스에 있는지 확인하기

ls -l /proc/self/ns/pid
lrwxrwxrwx 1 root root 0 Apr  3 18:45 /proc/self/ns/pid -> 'pid:[4026532412]'

모든 PID 네임스페이스 찾기

sudo find /proc -maxdepth 3 -type l -name pid -exec readlink {} \; 2>/dev/null | sort -u

루트 사용자는 초기(기본) PID 네임스페이스에서 모든 프로세스를 볼 수 있으며, 새로운 PID 네임스페이스의 프로세스도 볼 수 있습니다. 그래서 모든 PID 네임스페이스를 볼 수 있습니다.

PID 네임스페이스 내부로 들어가기

nsenter -t TARGET_PID --pid /bin/bash

PID 네임스페이스에 들어가면 기본 네임스페이스에서 모든 프로세스를 여전히 볼 수 있습니다. 그리고 해당 PID 네임스페이스의 프로세스는 PID 네임스페이스에서 새로운 bash를 볼 수 있습니다.

또한, 루트 사용자일 경우에만 다른 프로세스 PID 네임스페이스에 들어갈 수 있습니다. 그리고 디스크립터가 없으면 다른 네임스페이스에 들어갈 수 없습니다 (예: /proc/self/ns/pid).

References

{{#include ../../../../banners/hacktricks-training.md}}