Isolatie van AI-workloads
Isolatietechnieken voor AI-workloads met VM's, containers en trusted execution environments (TEE's).
Overzicht
AI-workloads brengen unieke isolatie-uitdagingen met zich mee die standaard cloudbeveiligingspatronen niet volledig aanpakken. GPU-passthrough doorbreekt traditionele container-isolatiegrenzen, gedeeld GPU-geheugen maakt cross-tenant datalekkage mogelijk, en model serving-frameworks vereisen vaak verhoogde privileges die sandboxing verzwakken. Wanneer meerdere AI-workloads dezelfde infrastructuur delen — of dat nu in multi-tenant cloud-omgevingen, gedeelde trainingsclusters of edge-deployments is — wordt de isolatiegrens tussen workloads een kritieke beveiligingszorg.
Dit artikel onderzoekt de isolatietechnieken die beschikbaar zijn voor AI-workloads op elke laag van de stack: procesisolatie, containerisolatie, VM-isolatie en isolatie op hardwareniveau via trusted execution environments (TEE's). Voor elke techniek analyseren we de beveiligingsgaranties die deze biedt, de specifieke manieren waarop die garanties afbrokkelen voor GPU-versnelde AI-workloads, en de praktische tegenmaatregelen die beschikbaar zijn. De inhoud sluit aan op de NIST AI RMF-governancevereisten voor isolatie van AI-systemen en op MITRE ATLAS-aanvalstechnieken op infrastructuurniveau.
De isolatie-uitdaging voor AI-workloads
Waarom AI-workloads anders zijn
Standaard webapplicaties draaien op CPU's, gebruiken goed begrepen syscall-interfaces en interageren met geïsoleerde geheugenruimtes. AI-workloads verschillen op verschillende belangrijke manieren:
| Eigenschap | Standaard workload | AI-workload |
|---|---|---|
| Rekeneenheid | Alleen CPU | CPU + GPU/TPU |
| Geheugenmodel | Virtueel geheugen in user-space | User-space + GPU-VRAM (gedeeld) |
| Toegang tot devices | Minimaal (/dev/null, enz.) | /dev/nvidia*, DMA-toegang |
| Privilegevereisten | Onbevoorrechte gebruiker | Vereist vaak --privileged of device-plugins |
| Datagevoeligheid | Applicatiedata | Modelgewichten, trainingsdata, inferentie-invoer |
| Netwerkvereisten | Standaard TCP/IP | NCCL, RDMA, InfiniBand voor gedistribueerde training |
De GPU is het belangrijkste isolatiedoorbrekende component. NVIDIA-GPU's die via CUDA worden benaderd, bieden niet dezelfde geheugenisolatiegaranties als CPU-virtueel geheugen. Wanneer meerdere containers een GPU delen via time-slicing of MPS (Multi-Process Service), kan het ene proces mogelijk restdata observeren die door een ander proces in het GPU-geheugen is achtergelaten.
Overzicht van het aanvalsoppervlak
┌─────────────────────────────────────────────────┐
│ Application Layer │
│ Model serving framework (vLLM, Triton, TGI) │
├─────────────────────────────────────────────────┤
│ Container Runtime │
│ Docker / containerd / CRI-O │
│ ┌──────────────────────────────────────────┐ │
│ │ GPU Device Plugin / NVIDIA Container │ │
│ │ Toolkit (nvidia-container-toolkit) │ │
│ └──────────────────────────────────────────┘ │
├─────────────────────────────────────────────────┤
│ Host OS / Hypervisor │
│ NVIDIA kernel driver (nvidia.ko) │
├─────────────────────────────────────────────────┤
│ Hardware │
│ GPU VRAM, PCIe bus, NVLink, DMA engines │
└─────────────────────────────────────────────────┘
Containerisolatie voor AI-workloads
Standaard containerisolatie
Linux-containers gebruiken namespaces (PID, netwerk, mount, user), cgroups (resourcelimieten) en seccomp-profielen (syscall-filtering) om workloads te isoleren. Voor workloads met alleen CPU bieden deze mechanismen sterke isolatie wanneer ze correct geconfigureerd zijn.
import subprocess
import json
from typing import Dict, List
class ContainerSecurityAuditor:
"""Audit container security configuration for AI workloads."""
def __init__(self, container_id: str):
self.container_id = container_id
def inspect_container(self) -> Dict:
"""Retrieve container configuration."""
result = subprocess.run(
["docker", "inspect", self.container_id],
capture_output=True, text=True, check=True,
)
return json.loads(result.stdout)[0]
def check_gpu_isolation(self) -> List[Dict]:
"""Check for GPU isolation weaknesses in the container configuration."""
config = self.inspect_container()
findings = []
# Controleer op privileged-modus
if config.get("HostConfig", {}).get("Privileged", False):
findings.append({
"severity": "critical",
"finding": "Container running in privileged mode",
"detail": "Privileged mode disables all container isolation. "
"GPU workloads should use --gpus flag instead.",
"remediation": "Use 'docker run --gpus device=0' instead of '--privileged'",
})
# Controleer op device-mappings
devices = config.get("HostConfig", {}).get("Devices", []) or []
nvidia_devices = [d for d in devices if "nvidia" in str(d)]
if nvidia_devices:
findings.append({
"severity": "medium",
"finding": f"Direct NVIDIA device access: {len(nvidia_devices)} devices",
"detail": "Direct device mapping bypasses NVIDIA container toolkit isolation",
"remediation": "Use NVIDIA container toolkit with --gpus flag",
})
# Controleer op host-PID-namespace
if config.get("HostConfig", {}).get("PidMode") == "host":
findings.append({
"severity": "high",
"finding": "Container shares host PID namespace",
"detail": "Host PID namespace allows observing GPU processes from other containers",
"remediation": "Remove --pid=host flag",
})
# Controleer seccomp-profiel
seccomp = config.get("HostConfig", {}).get("SecurityOpt", [])
if any("seccomp=unconfined" in str(s) for s in seccomp):
findings.append({
"severity": "high",
"finding": "Seccomp profile disabled",
"detail": "Unconfined seccomp allows all syscalls including ioctl for GPU manipulation",
"remediation": "Apply a custom seccomp profile that allows required GPU ioctls only",
})
# Controleer op SYS_ADMIN-capability
caps = config.get("HostConfig", {}).get("CapAdd", []) or []
if "SYS_ADMIN" in caps:
findings.append({
"severity": "high",
"finding": "SYS_ADMIN capability granted",
"detail": "SYS_ADMIN enables mount namespace escapes and device access",
"remediation": "Remove SYS_ADMIN and use specific capabilities instead",
})
return findingsGPU-specifieke container-escape-vectoren
De NVIDIA container toolkit (nvidia-container-toolkit, voorheen nvidia-docker2) biedt een runtime-hook die GPU-devices in containers mapt. Hoewel dit veiliger is dan het gebruik van --privileged, creëert het nog steeds aanvalsoppervlak:
-
NVIDIA driver-ioctls: De container communiceert met de host-GPU-driver via ioctl-syscalls op
/dev/nvidia*-devices. Kwetsbaarheden in de NVIDIA-kernel-driver kunnen vanuit een container worden misbruikt om code-uitvoering op de host te bereiken. CVE-2024-0132 (TOCTOU-kwetsbaarheid in de NVIDIA Container Toolkit) demonstreerde hoe een speciaal vervaardigde container image uit de container kon ontsnappen door een time-of-check-time-of-use race condition in de toolkit zelf te misbruiken. -
GPU-geheugenresiduen: Wanneer een container GPU-geheugen toewijst en vrijgeeft, kan de data in het VRAM blijven staan tot deze wordt overschreven. Een volgende container die dezelfde GPU gebruikt, kan scannen naar restdata.
-
PCIe-DMA-toegang: GPU's gebruiken DMA om data over te dragen tussen hostgeheugen en GPU-geheugen. In sommige configuraties zou een gecompromitteerde GPU-workload DMA kunnen gebruiken om willekeurig hostgeheugen te lezen of te schrijven.
#!/bin/bash
# Audit NVIDIA container toolkit configuration
# Run on the host system
echo "=== NVIDIA Container Toolkit Security Audit ==="
# Controleer toolkit-versie
echo "[*] NVIDIA Container Toolkit version:"
nvidia-container-cli --version 2>/dev/null || echo " Not found"
# Controleer of CDI (Container Device Interface) is ingeschakeld
echo "[*] CDI configuration:"
if [ -f /etc/nvidia-container-runtime/config.toml ]; then
grep -i "cdi" /etc/nvidia-container-runtime/config.toml
else
echo " Config file not found"
fi
# Controleer GPU-isolatiemodus
echo "[*] GPU isolation mode:"
nvidia-smi -q | grep -i "MIG\|isolation\|accounting" || echo " Could not query GPU"
# Controleer of MIG (Multi-Instance GPU) beschikbaar en ingeschakeld is
echo "[*] MIG (Multi-Instance GPU) status:"
nvidia-smi mig -lgi 2>/dev/null || echo " MIG not available on this GPU"
# Controleer op IOMMU (vereist voor DMA-bescherming)
echo "[*] IOMMU status:"
if dmesg | grep -qi "IOMMU enabled"; then
echo " IOMMU is enabled (good)"
else
echo " WARNING: IOMMU may not be enabled"
fi
# Lijst alle NVIDIA-devicebestanden op
echo "[*] NVIDIA device files:"
ls -la /dev/nvidia* 2>/dev/null || echo " No NVIDIA devices found"Multi-Instance GPU (MIG)
NVIDIA A100-, A30- en H100-GPU's ondersteunen Multi-Instance GPU (MIG)-technologie, die een enkele GPU in hardware partitioneert in maximaal zeven geïsoleerde instances. Elke MIG-instance heeft zijn eigen toegewijde geheugen, cache en rekeneenheden. Anders dan GPU-deling op softwareniveau (time-slicing of MPS) biedt MIG hardware-afgedwongen isolatie.
import subprocess
import json
from typing import List, Dict
class MIGSecurityManager:
"""Manage and audit MIG instances for workload isolation."""
def list_mig_instances(self) -> List[Dict]:
"""List all MIG GPU instances and their configuration."""
result = subprocess.run(
["nvidia-smi", "mig", "-lgi"],
capture_output=True, text=True,
)
# Parse nvidia-smi-uitvoer
instances = []
for line in result.stdout.strip().split("\n"):
if "MIG" in line or "GPU" in line:
instances.append({"raw": line.strip()})
return instances
def verify_memory_isolation(self, instance_id: int) -> Dict:
"""
Verify that a MIG instance cannot access memory from other instances.
Returns test results.
"""
# Deze test wijst geheugen toe op de ene MIG-instance en verifieert
# dat het niet vanaf een andere instance kan worden gelezen
test_script = f"""
import torch
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "MIG-{instance_id}"
# Allocate and fill a tensor with known pattern
t = torch.full((1024, 1024), 42.0, device="cuda")
print(f"Allocated on MIG instance {instance_id}: {{t.sum().item()}}")
# Free the tensor
del t
torch.cuda.empty_cache()
"""
result = subprocess.run(
["python3", "-c", test_script],
capture_output=True, text=True, timeout=30,
)
return {
"instance_id": instance_id,
"success": result.returncode == 0,
"output": result.stdout.strip(),
"error": result.stderr.strip() if result.returncode != 0 else None,
}MIG is de sterkste GPU-isolatie die vandaag de dag beschikbaar is voor multi-tenant omgevingen. Het heeft echter beperkingen: niet alle GPU-modellen ondersteunen het, de vaste partitiegroottes komen mogelijk niet overeen met de workloadvereisten, en het vermindert de totale rekenkracht die per workload beschikbaar is. Voor red teams is de sleutelvraag of MIG daadwerkelijk is ingeschakeld en correct geconfigureerd in de doelomgeving, of dat de infrastructuur leunt op zwakkere isolatiemechanismen.
VM-isolatie
GPU-passthrough naar VM's
Virtuele machines bieden sterkere isolatie dan containers, omdat de hypervisor alle hardwaretoegang bemiddelt. Voor GPU-workloads kunnen GPU's aan VM's worden toegewezen met PCIe-passthrough (VFIO) of SR-IOV (Single Root I/O Virtualization).
Met PCIe-passthrough wordt een hele GPU toegewijd aan een enkele VM. Dit biedt sterke isolatie — de GPU-driver van de VM communiceert rechtstreeks met de hardware en kan het GPU-geheugen van andere VM's niet benaderen. Het beperkt echter GPU-deling: één GPU per VM.
SR-IOV virtualiseert een enkele fysieke GPU in meerdere virtuele functies (VF's), elk toegewezen aan een andere VM. NVIDIA ondersteunt dit op geselecteerde datacenter-GPU's. SR-IOV biedt betere isolatie dan deling op containerniveau, omdat elke VF hardware-afgedwongen geheugengrenzen heeft, maar het is minder flexibel dan MIG en vereist specifieke hardware-ondersteuning.
#!/bin/bash
# Configure SR-IOV for NVIDIA GPU (A100 example)
# Must be run on the bare-metal host with root privileges
# Schakel SR-IOV in op het GPU-PCI-device
GPU_PCI_ID="0000:3b:00.0" # Voorbeeld — vind met lspci | grep NVIDIA
echo "=== Configuring GPU SR-IOV ==="
# Controleer of SR-IOV wordt ondersteund
echo "[*] Checking SR-IOV capability:"
lspci -vvv -s "$GPU_PCI_ID" | grep -i "single root"
# Schakel virtuele functies in (bijv. 4 VF's)
echo 4 > "/sys/bus/pci/devices/$GPU_PCI_ID/sriov_numvfs"
# Verifieer dat de VF's zijn aangemaakt
echo "[*] Virtual functions:"
lspci | grep -i nvidia | grep "Virtual Function"
# Wijs VF's toe aan VM's met VFIO
echo "[*] Binding VF to VFIO driver for VM assignment:"
VF_PCI_ID="0000:3b:00.1" # Eerste VF
echo "vfio-pci" > "/sys/bus/pci/devices/$VF_PCI_ID/driver_override"
echo "$VF_PCI_ID" > /sys/bus/pci/drivers/vfio-pci/bindConfidential VM's
Cloudproviders bieden nu confidential VM's aan die hardware-versleuteling gebruiken om VM-geheugen te beschermen tegen de hypervisor en het host-OS. AMD SEV-SNP (Secure Nested Paging) en Intel TDX (Trust Domain Extensions) versleutelen VM-geheugen met sleutels die de hypervisor niet kan benaderen.
Voor AI-workloads beschermen confidential VM's:
- Modelgewichten geladen in CPU-geheugen
- Inferentie-invoer en -uitvoer tijdens de verwerking
- Trainingsdata tijdens preprocessing
Confidential VM's beschermen echter momenteel geen GPU-geheugen. Data die naar de GPU wordt overgedragen voor berekening verlaat de versleutelde geheugenruimte van de CPU en komt terecht in onversleuteld GPU-VRAM. Dit is een kritiek gat dat de bescherming beperkt die confidential VM's bieden voor AI-workloads.
Trusted Execution Environments voor AI
CPU-gebaseerde TEE's
Intel SGX (Software Guard Extensions) en ARM TrustZone bieden enclave-gebaseerde isolatie waarbij code en data in het geheugen worden versleuteld en beschermd tegen het OS en de hypervisor. Voor AI-workloads kunnen TEE's het volgende beschermen:
from typing import Dict, Any
import hashlib
class TEEAttestationVerifier:
"""
Verify TEE attestation for AI workloads.
Ensures the inference environment is genuine and unmodified.
"""
def __init__(self, expected_measurements: Dict[str, str]):
"""
Args:
expected_measurements: Expected hash values for TEE measurements.
Keys are measurement names (e.g., 'mrenclave', 'mrsigner'),
values are expected hex-encoded hash values.
"""
self.expected = expected_measurements
def verify_sgx_attestation(self, attestation_report: Dict[str, Any]) -> Dict:
"""Verify an Intel SGX attestation report."""
results = {"verified": True, "checks": []}
# Verifieer MRENCLAVE (hash van de enclave-code en initiële data)
mrenclave = attestation_report.get("mrenclave", "")
if mrenclave != self.expected.get("mrenclave", ""):
results["verified"] = False
results["checks"].append({
"check": "mrenclave",
"status": "FAIL",
"detail": "Enclave measurement does not match expected value. "
"The inference code may have been modified.",
})
else:
results["checks"].append({
"check": "mrenclave",
"status": "PASS",
})
# Verifieer MRSIGNER (hash van de enclave-signing-sleutel)
mrsigner = attestation_report.get("mrsigner", "")
if mrsigner != self.expected.get("mrsigner", ""):
results["verified"] = False
results["checks"].append({
"check": "mrsigner",
"status": "FAIL",
"detail": "Signer identity does not match. "
"The enclave was not signed by the expected party.",
})
else:
results["checks"].append({
"check": "mrsigner",
"status": "PASS",
})
# Controleer op debug-modus (zou uitgeschakeld moeten zijn in productie)
if attestation_report.get("attributes", {}).get("debug", False):
results["verified"] = False
results["checks"].append({
"check": "debug_mode",
"status": "FAIL",
"detail": "Enclave is running in debug mode. "
"Memory can be inspected by the host.",
})
return results
def verify_model_integrity_in_tee(
self, model_bytes: bytes, expected_hash: str
) -> bool:
"""Verify model integrity inside the TEE before loading."""
actual_hash = hashlib.sha256(model_bytes).hexdigest()
return actual_hash == expected_hashGPU-TEE's en confidential computing
NVIDIA H100-GPU's introduceerden ondersteuning voor confidential computing die TEE-bescherming uitbreidt naar GPU-geheugen. Met NVIDIA Confidential Computing wordt data versleuteld wanneer deze van CPU naar GPU wordt overgedragen en alleen ontsleuteld binnen de beveiligde uitvoeringsomgeving van de GPU. Dit dicht het kritieke gat waarbij confidential VM's geen data konden beschermen die zich op de GPU bevond.
De architectuur werkt als volgt:
- De CPU-TEE (AMD SEV-SNP of Intel TDX) brengt een beveiligde sessie tot stand met de GPU
- Er wordt een beveiligd kanaal opgezet over PCIe met geauthenticeerde versleuteling
- Data die naar de GPU wordt overgedragen, wordt in transit versleuteld en alleen ontsleuteld binnen de beschermde geheugenregio van de GPU
- GPU-berekeningsresultaten worden versleuteld voordat ze terug naar de CPU worden gestuurd
Dit is een aanzienlijke vooruitgang voor het beschermen van modelgewichten en inferentiedata, maar het heeft prestatie-implicaties (5-15% overhead afhankelijk van de workload) en vereist specifieke hardware (H100 of later).
Methodologie voor red team-assessment
Fase 1: Ontdekking van de isolatiearchitectuur
#!/bin/bash
# Discover the isolation architecture of the target AI infrastructure
echo "=== AI Workload Isolation Assessment ==="
# Bepaal of we in een container draaien
echo "[*] Container detection:"
if [ -f /.dockerenv ]; then
echo " Running inside Docker container"
elif grep -q "containerd" /proc/1/cgroup 2>/dev/null; then
echo " Running inside containerd"
elif [ -f /run/secrets/kubernetes.io ]; then
echo " Running inside Kubernetes pod"
else
echo " Not detected as container"
fi
# Controleer GPU-toegangsmethode
echo "[*] GPU access method:"
if [ -e /dev/nvidia0 ]; then
echo " Direct GPU device access"
ls -la /dev/nvidia*
fi
# Controleer op MIG
echo "[*] MIG configuration:"
nvidia-smi mig -lgi 2>/dev/null || echo " MIG not available/enabled"
# Controleer capabilities
echo "[*] Container capabilities:"
cat /proc/self/status | grep -i cap
# Controleer mount-namespace
echo "[*] Mount namespace:"
ls -la /proc/self/ns/mnt
# Controleer op gedeeld GPU-geheugen dat toegankelijk is vanuit deze context
echo "[*] GPU memory status:"
nvidia-smi --query-gpu=memory.used,memory.free --format=csv 2>/dev/nullFase 2: Testen van de isolatiegrens
Test of de isolatiegrenzen daadwerkelijk cross-workload-toegang voorkomen:
- Scannen van GPU-geheugen: Wijs GPU-geheugen toe en controleer op restdata van eerdere workloads
- Pogingen tot container-escape: Test op bekende container-escape-vectoren in de GPU-runtime
- Netwerkisolatie: Verifieer dat NCCL-verkeer voor gedistribueerde training is geïsoleerd van andere workloads
- Filesysteemisolatie: Controleer op gedeelde modelopslag die vergiftiging mogelijk zou kunnen maken
Fase 3: Privilege-escalatie
AI-workloads vereisen vaak verhoogde privileges. Test of deze privileges kunnen worden ingezet voor laterale beweging:
- Kan de GPU-devicetoegang worden gebruikt om hostgeheugen te lezen via DMA?
- Kan de netwerk-namespace van de container de control plane van het trainingscluster benaderen?
- Kan het mountpunt van de modelopslag worden gebruikt om de modellen van andere workloads te wijzigen?
Defensieve aanbevelingen
- Gebruik MIG voor multi-tenant GPU-deling in plaats van time-slicing of MPS
- Gebruik nooit
--privilegedvoor AI-containers; gebruik in plaats daarvan de NVIDIA container toolkit met--gpus - Schakel IOMMU in om DMA-gebaseerde aanvallen vanaf GPU-devices te voorkomen
- Pas seccomp-profielen toe die alleen vereiste GPU-ioctls op de whitelist zetten
- Gebruik confidential computing (NVIDIA H100 CC) voor gevoelige inferentie-workloads
- Verifieer attestation voordat je modelgewichten of gevoelige data naar externe TEE's stuurt
- Wis GPU-geheugen tussen workloads door te dealloceren en opnieuw toe te wijzen met genuld geheugen
- Isoleer NCCL-verkeer op toegewijde netwerkinterfaces met versleuteling ingeschakeld
Referenties
- CVE-2024-0132 — NVIDIA Container Toolkit TOCTOU vulnerability enabling container escape
- NVIDIA Confidential Computing — https://developer.nvidia.com/confidential-computing
- NVIDIA Multi-Instance GPU (MIG) — https://docs.nvidia.com/datacenter/tesla/mig-user-guide/
- AMD SEV-SNP — https://www.amd.com/en/developer/sev.html
- Intel TDX — https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/overview.html
- NIST AI RMF — Govern 1.7 (AI system isolation requirements)
- MITRE ATLAS — AML.T0040 (ML-Enabled Product/Service), infrastructure attack techniques