std.ns — Namespaces & pidfd
import std.ns;
Zwei Mechanismen zur Prozess-Isolation:
- pidfd: Stabiler Prozess-Deskriptor — bleibt gültig auch wenn die PID wiederverwendet wird. Race-condition-freie Signal-Zustellung und fd-Duplikation.
- Namespaces: Isolieren Systemressourcen (PID, Netzwerk, Mounts, User, UTS, IPC) zwischen Prozessgruppen.
Syscalls: pidfd_open(434), pidfd_send_signal(424), pidfd_getfd(438), unshare(272), setns(308).
→ std.debug · std.security_ext · std.ipc_sysv
Namespace-Konstanten
CLONE_NEW*-Flags
| Konstante | Wert | Namespace-Typ |
|---|---|---|
CLONE_NEWNS | 131072 | Mount-Namespace |
CLONE_NEWUTS | 67108864 | UTS (Hostname/Domainname) |
CLONE_NEWIPC | 134217728 | IPC-Namespace |
CLONE_NEWUSER | 268435456 | User-Namespace |
CLONE_NEWPID | 536870912 | PID-Namespace |
CLONE_NEWNET | 1073741824 | Netzwerk-Namespace |
CLONE_NEWCGROUP | 33554432 | cgroup-Namespace |
CLONE_NEWTIME | 128 | Zeit-Namespace (Kernel 5.6+) |
Namespace-Typen für NamespaceJoin
| Konstante | Wert | Bedeutung |
|---|---|---|
NSTYPE_ANY | 0 | Automatisch vom fd ableiten |
NSTYPE_IPC | 134217728 | IPC-Namespace beitreten |
NSTYPE_UTS | 67108864 | UTS-Namespace beitreten |
NSTYPE_NET | 1073741824 | Netz-Namespace beitreten |
NSTYPE_PID | 536870912 | PID-Namespace beitreten |
NSTYPE_USER | 268435456 | User-Namespace beitreten |
NSTYPE_MNT | 131072 | Mount-Namespace beitreten |
pidfd-Funktionen
| Funktion | Signatur | Beschreibung |
|---|---|---|
PidFdOpen | (pid: int64, flags: int64): int64 | Öffnet stabilen Prozess-Deskriptor für pid; flags=0 |
PidFdSendSignal | (pidfd: int64, sig: int64): int64 | Sendet Signal race-condition-frei; sig=0 = Existenz-Check |
PidFdGetFd | (pidfd: int64, targetFd: int64): int64 | Dupliziert fd des Zielprozesses in aktuellen Prozess |
Namespace-Funktionen
| Funktion | Signatur | Beschreibung |
|---|---|---|
NamespaceUnshare | (flags: int64): int64 | Erzeugt neue Namespaces für aktuellen Prozess |
NamespaceJoin | (fd: int64, nsType: int64): int64 | Tritt bestehendem Namespace bei (via Namespace-fd) |
Verwendung
Race-freies Signal senden
import std.ns;
fn KillSafely(pid: int64): int64 {
// PID kann wiederverwendet werden — pidfd bleibt eindeutig
var pidfd: int64 := PidFdOpen(pid, 0);
if (pidfd < 0) { return pidfd; }
var r: int64 := PidFdSendSignal(pidfd, 15); // SIGTERM
close(pidfd);
return r;
}
fd eines anderen Prozesses duplizieren
import std.ns;
fn StealFd(targetPid: int64, targetFdNum: int64): int64 {
// Erfordert CAP_SYS_PTRACE oder gleicher User-Namespace
var pidfd: int64 := PidFdOpen(targetPid, 0);
if (pidfd < 0) { return pidfd; }
var newFd: int64 := PidFdGetFd(pidfd, targetFdNum);
close(pidfd);
return newFd; // Eigener fd auf die Datei des Zielprozesses
}
Netzwerk-Namespace isolieren
import std.ns;
fn IsolateNetwork(): int64 {
// Neuen Netz-Namespace für diesen Prozess erzeugen
// (nur eigene Loopback-Schnittstelle sichtbar)
return NamespaceUnshare(CLONE_NEWNET);
}
User-Namespace (ohne root)
import std.ns;
fn UnprivilegedNamespace(): int64 {
// CLONE_NEWUSER benötigt kein root (Kernel 3.8+, sofern aktiviert)
var r: int64 := NamespaceUnshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWPID);
return r;
}
Bestehendem Namespace beitreten
import std.ns;
import std.fs;
fn JoinContainerNet(containerPid: int64): int64 {
// /proc/<pid>/ns/net öffnen
// Pfad muss manuell aufgebaut werden (kein sprintf in dieser Unit)
var fd: int64 := OpenFile("/proc/1/ns/net", 0);
if (fd < 0) { return fd; }
var r: int64 := NamespaceJoin(fd, NSTYPE_NET);
close(fd);
return r;
}
Hinweise
- pidfd vs. PID: PIDs werden nach Prozessende wiederverwendet. Ein pidfd bleibt eindeutig für die Lebensdauer des Prozesses — unverzichtbar wenn zwischen
getpid()und Signal-Send ein Prozess sterben kann. - PidFdGetFd: Erfordert
CAP_SYS_PTRACEoder dass beide Prozesse im selben User-Namespace laufen. Nutzbar um Dateideskriptoren aus Containern zu extrahieren. - CLONE_NEWUSER: Einziger Namespace der ohne root erzeugt werden kann (wenn
kernel.unprivileged_userns_clone=1). Ubuntu deaktiviert das standardmäßig. - Namespace-fd-Pfad: Für
NamespaceJoinmuss/proc/<pid>/ns/<type>manuell als Pfad geöffnet werden; die Unit stellt kein Pfad-Bauen bereit. - NamespaceUnshare + fork(): Namespaces werden von Kindprozessen geerbt. Erzeugt der Elternprozess zuerst Namespaces, gelten diese für alle fork()-Kinder.
Letzte Aktualisierung: 2026-06-06
