Безпека GPU: чи може статися «Spectre для графіки»?

Було корисно?

Ви купили GPU, щоб усе працювало швидше. Тепер ви дізнаєтеся, що вони також можуть прискорити ваш найгірший день — включно з витоками даних, шумними сусідами та інцидентами «чому вихід моделі інший?».

Неприємна правда: сучасні GPU дуже нагадують CPUs перед тим, як Spectre/Meltdown стали загальновідомими у каналах інцидентів. Їх ділять між орендарями, оптимізують заради продуктивності, вони напхані мікроархітектурною поведінкою, яку ніхто не документує, і керуються величезним, привілейованим кодом в ядрі.

Як виглядав би «Spectre для графіки»

Spectre — це було не просто «баг у CPU». Це була системна наука: якщо ви створюєте функції продуктивності, що залежать від поведінки, пов’язаної зі секретом, хтось рано чи пізно перетворить цю поведінку на примітив читання.
GPU сповнені поведінки, залежної від секретів. Вони також напхані «пріоритетом продуктивності» хитростями, які невидимі, поки поруч не запустять ненадійний код поруч із чутливими робочими навантаженнями.

«Spectre для графіки» не обов’язково буде одним CVE, що все ламатиме за ніч. Швидше це патерн:

  • Мікроархітектурний боковий канал (затримки кешу, конфлікти банків спільної пам’яті, ефекти зайнятості, артефакти планування інструкцій), що витікає цінну інформацію — ваги моделей, підказки, ембеддинги, криптоключі або фічі даних.
  • Перетікання між орендарями в хмарах або спільних кластерах (вузли Kubernetes з GPU, розділи Slurm, VDI-ферми або MLOps-платформи), де два клієнти ділять GPU або шляхи доступу до пам’яті хоста.
  • Реальність «драйвер як розширення ядра», коли помилка в масивному модулі драйвера GPU стає найпростіше способом втечі з контейнера на хості.
  • Операційний радіус ураження, бо пом’якшення коштує реальної продуктивності, і бізнес спробує домовитися з фізикою.

Найкраща ментальна модель — не «хакер читає регістри GPU». Це «сусід робить висновки про ваші секрети, вимірюючи спільні ресурси», плюс «патч від вендора, що змінює характеристики продуктивності і ламає вашу відтворюваність».

Якщо ви сьогодні працюєте з багатоорендним GPU-інфраструктурою, вважайте, що істинні три речі:

  1. Хтось знайде шлях витоку, про який ви не знали.
  2. Ваша історія ізоляції буде частково контрактною («ми цього не робимо») і частково технічною («ми не можемо цього зробити»).
  3. Більшість пом’якшень будуть негарними: планування, розподіл і відключення хитрощів.

Факти й історія: шлях до проблем з GPU

Факти важливі, бо вони не дозволяють ставитися до безпеки GPU як до фольклору. Ось конкретні контекстні пункти — короткі, нудні і тому корисні.

  1. GPU еволюціонували від фіксованих конвеєрів до універсальних обчислень протягом приблизно двох десятиліть, а моделі безпеки відставали від нової реальності «тут виконується ненадійний код».
  2. CUDA (2007) нормалізувала гпу-обчислення у масових системах, що також зробило стек драйвера цінною ціллю — великий, привілейований і відкритий до входів, контрольованих користувачем.
  3. Meltdown/Spectre (публічно у 2018) переосмислили «функції продуктивності» як поверхню атаки і підняли бокові канали до першокласної проблеми безпеки, а не академічного хобі.
  4. Сучасні GPU широко ділять на-чипові ресурси (L2-кеші, контролери пам’яті, інтерконектні тканини) між контекстами; спільне використання добре для завантаження і погано для «не дозволяйте сусідові дізнаватися речі».
  5. Пам’ять GPU часто керується драйвером і рантаймом замість апаратно-примусових таблиць сторінок так, щоб інженери CPU після цього спокійно спали; навіть коли є трансляція адрес, деталі відрізняються за архітектурою та режимом.
  6. SR-IOV і vGPU зробили розподіл часу GPU нормою в корпоративних VDI і хмарних пропозиціях, що збільшило кількість шляхів, де дані можуть витекти через віртуальні межі.
  7. Розподіл у стилі MIG — великий крок уперед (виділені частини обчислень і пам’яті), але це не магічна наліпка «нічого не спільного»; деякі компоненти лишаються спільними, а прошивка лишається прошивкою.
  8. DMA GPU потужний за дизайном: пристрій може читати/писати пам’ять хоста на великій швидкості. Без правильної конфігурації IOMMU ви фактично підключили дуже швидкий двигун корупції пам’яті до шини PCIe.
  9. Драйвери GPU рутинно належать до найбільших модулів ядра на Linux-хостах, що збільшує поверхню помилок і робить cadence патчів питанням надійності, а не лише гігієни безпеки.

Жодне з цього не доводить, що обов’язково буде один катастрофічний «GPU Meltdown». Але це доводить, що передумови існують: спільні ресурси, непрозора поведінка, привілейований код і величезні стимули оптимізувати.

Модель загроз: що реально ламається в продакшені

Визначимо «Spectre для графіки» в операційних термінах. Вам не потрібен технічний документ. Потрібно знати, чого боятися і що ігнорувати.

Модель загроз A: багатоорендний вузол з GPU

Два робочі навантаження ділять один фізичний GPU у часі (time-slicing), або ділять той самий вузол з passthrough/vGPU, або ділять шлях доступу до пам’яті CPU вузла через pinned memory і DMA.
Атакувальник контролює одне навантаження, жертва — інше.

Ціль: вивести секрети (ваги моделі, властивості вхідних даних або ключі) за допомогою бокових каналів або залишкового стану.

Модель загроз B: ненадійний код GPU всередині контейнера

Контейнер виконує CUDA, ROCm, Vulkan або OpenCL. Він має доступ до /dev/nvidia* або /dev/dri*.
Драйвер розміщений в ядрі хоста.

Ціль: вийти з контейнера, отримати root або прочитати дані інших орендарів, експлуатуючи баг у драйвері.

Модель загроз C: «довірений» код тренування, який насправді не довірений

Бібліотека від вендора, pip-залежність, плагін для моделі або «корисний» патч продуктивності виконує ядра GPU і хост-код.
Ніхто не зловмисний; багато хто недбалий.

Ціль: випадковий витік або втрата цілісності — тихо неправильні результати або дані, що лишилися в пам’яті GPU.

Модель загроз D: ланцюжок постачання і прошивка

Прошивка GPU, підписані бінарники, контролери управління та агенти хоста (DCGM, persistence-демони, експортери моніторингу) — частина вашого TCB, подобається вам це чи ні.

Якщо ви запускаєте одноорендні вузли (один клієнт на фізичний хост, без винятків), ви можете значно зменшити ризик.
Якщо ви ділите GPU — ви займаєтесь інженерією безпеки. Можливо, ви цього не передбачали в бюджеті. Шкода.

Де відбуваються витоки даних GPU: реальні лінії розлому

1) Залишкова пам’ять GPU (клас «забули витерти»)

Найпростіший витік також найпащиться: одне завдання звільняє пам’ять, інше завдання її виділяє, і виявляються застарілі байти.
На CPU аллокатори ОС і політики зневаджування сторінок це зменшують. На GPU поведінка різниться між драйверами й режимами.

Для продакшену: припускайте, що залишкова пам’ять можлива, якщо ви не довели протилежне для свого стека. «Драйвер, напевно, очищає її» — не контроль. Це мрія з проханням про бюджет.

2) Спільні кеші, спільна пам’ять і таймінг

Бокові канали процвітають на спільних ресурсах. GPU мають L2-кеші, шари спільної пам’яті, кеші текстур (у графічних контекстах) і контролери пам’яті, які можуть витікати інформацію через затримки і патерни конкуренції.

Атакувальнику не потрібно напряму читати вашу пам’ять. Достатньо знати, скільки часу щось зайняло, скільки наборів кешу було витіснено або чи стався банковий конфлікт, що корелює з доступом, залежним від секрету.

3) Unified virtual addressing і pinned host memory

UVA і pinned memory — це функції продуктивності. Вони також є «застрілкою» для безпеки, якщо ви не контролюєте, хто може що й коли виділяти, бо вони розширюють досяжність GPU у шляхах пам’яті хоста.

DMA без правильної IOMMU — класична історія: пристрій може отримати доступ до фізичної пам’яті хоста поза тим, що ви планували. Іноді «атакувальник» — просто баг.

4) Поверхня атаки драйвера та рантайму

Стек драйверів GPU — музей сумісних шарів: рантайм CUDA, модуль ядра, бібліотеки користувача, JIT-компіляція, компілятори шейдерів, Vulkan ICD і ще багато чого.
Він великий. Він парсить ненадійні входи (ядра, шейдери, PTX, SPIR-V). Саме там історично живуть баги переповнення пам’яті.

Жарт №1 (коротко, по суті): драйвери GPU як антикварні годинники — гарна інженерія, багато рухомих деталей і якщо ви їх зачепите невміло, час піде боком.

5) Розділення — не ізоляція, якщо ви не можете пояснити залишки

MIG, профілі vGPU і політики планувальника можуть зменшити перехресний шум, але вам потрібно знати, що все ще спільне:
двигуни копіювання, L2-розділи, контролери пам’яті, інтерконектні шляхи та пули під управлінням прошивки.

Ваша позиція безпеки залежить від того, які ручки ви можете крутити, а які мусите прийняти. Якщо ви не можете це описати — ви не зможете захистити це на аудиті чи у постмортемі.

Три корпоративні міні-історії (анонімізовані)

Міні-історія 1: Інцидент через хибне припущення

Середньої величини SaaS-компанія розгорнула вузли для inference на GPU, щоб підтримати корпоративних клієнтів «bring your own model».
Вони зробили розумні речі: кожен клієнт отримав namespace у Kubernetes, політики мережі, окреме сховище об’єктів і суворий RBAC.
Але зробили одну нерозумну річ: припустили, що GPU — «просто ще один пристрій» і що контейнер — достатня межа.

Один клієнт повідомив про дивні, слабо структуровані артефакти у виходах, які виглядали як частини підказок інших клієнтів.
Спочатку звучало як галюцинація моделі. Підтримка записала це як «плутанина клієнта». Клієнт настоював, надіслав відтворювані приклади, і тон різко змінився.

Внутрішнє розслідування виявило, що джоби планувалися підряд на тому самому GPU. Процес inference використовував пул алокації пам’яті на GPU, щоб зменшити накладні витрати malloc/free.
За певних шляхів відмов (таймаути та ранні виходи) буфери звільняли, але не перезаписувалися явно.
Нового орендаря перші алокації інколи повторно використовували ті сторінки, а норма для налагодження (debug endpoint), призначена для інспекції моделі, повертала сирі проміжні тензори.

Проблема не була хитрим боковим каналом. Це був нудний, старий «data remanence» витік у GPU-і.
Виправлення було так само нудним: видалити endpoint для налагодження з релізів, спрямованих на орендарів, додати обов’язкове занулення чутливих буферів і ввести правило «один орендар на фізичний GPU», доки не перевірять міцнішу модель ізоляції.

Найбільший урок у постмортемі: вони ставилися до «GPU-пам’яті», ніби це поведінка приватної оперативної пам’яті процесу.
Так не було. І інцидент не спричинив зловмисник — його спричинив клієнт, який уважно подивився.

Міні-історія 2: Оптимізація, що обернулася проти

Фінтех-компанія запускала GPU-прискорені симуляції ризиків вночі. Навантаження були передбачувані, контрольовані і не мультиорендні.
Потім бізнес попросив «швидше відгукування» і «краще завантаження», і хтось запропонував підмішувати ad-hoc аналітику в те саме вікно.

Команда ввімкнула агресивне тайм-слайсинг GPU і упакувала більше контейнерів на вузол.
Також включили режим продуктивності, який утримував контексти теплими і уникали ресетів між джобами.
Коефіцієнт використання покращився на дашборді. Латентність покращилася. Усім аплодували.

Через два тижні у них стався інцидент надійності: результати симуляцій інколи відрізнялися тонко. Жодних падінь, просто неправильні відповіді.
О третьій ранку — найгірший тип помилок.

Корінь: взаємодія через спільні ресурси. Ad-hoc роботи змінили резидентність кешу і доступність пропускної здатності пам’яті в патернах, що впливали на числову стабільність.
Деякі ядра були чутливі до недетермінованого порядку виконання; інші покладалися на гонки в редукціях, які «достатньо хороші», коли GPU був інакше простий.
Коли все упакували й почали тайм-слайсити, джиттер порядку виконання зріс, і результати зійшлися за межі прийнятної похибки.

Вони відкотили оптимізацію, розділили навантаження по пулу вузлів і вимагали детермінованих математичних флагів для будь-якої задачі з регульованим виходом.
Висновок для безпеки: мислення про бокові канали і мислення про цілісність — родичі. Спільні ресурси не лише витікають; вони також спотворюють.

Міні-історія 3: Нудна, але правильна практика, що врятувала день

Команда платформ підприємства керувала GPU-кластером для внутрішніх ML-команд. Вони не були відомими, не залипали на конференціях і не блищали.
Вони мали одну суперсилу: алергію на «особливі випадки».

Кожен GPU-вузол завантажувався з увімкненим IOMMU, примусовим Secure Boot і політикою lockdown ядра.
Версії драйверів були зафіксовані для кожного пулу вузлів. Розгортання патчів відбувалось із канарою, з автоматизованим відкатом у разі зростання помилок.
Профілі MIG були стандартизовані, а планувальник розміщував лише сумісні за мітками безпеки робочі навантаження на спільні GPU.

Одного кварталу оновлення драйвера GPU внесло регресію, що спричиняла спорадичні підвішування під певною комбінацією pinned host memory і peer-to-peer трансферів.
ML-команди були засмучені, бо їхні тренування сповільнилися через те, що платформа втримала оновлення.
Але у платформи була телеметрія: канарні вузли показали зростання помилок Xid і підвищення кількості коректованих помилок PCIe. Вони призупинили розгортання.

Через два тижні вийшло advisory з безпеки для тієї самої гілки драйвера, пов’язаний з шляхом, контрольованим користувачем, що може привести до підвищення привілеїв.
Вони вже не запускали ту версію. Вони виправилися на фіксованому білді, з тими самими канарами.

Мораль: нудні контролі не лише запобігають зламу; вони запобігають панічним вихідним у вихідні. Єдине краще за швидку реакцію на інцидент — це відсутність інциденту.

Практичні завдання: команди, виводи й рішення (12+)

Це не «запустіть сканер і моліться» завдання. Це жорсткі перевірки, що кажуть, чи дійсно ваш парк GPU ізольований, пропатчений і поводиться як треба.
Кожне завдання включає: команду, приклад виводу, що це означає і яке рішення прийняти.

Завдання 1: Інвентаризація моделі GPU, драйвера і рантайму

cr0x@server:~$ nvidia-smi
Wed Jan 17 10:21:32 2026
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.14    Driver Version: 550.54.14    CUDA Version: 12.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA A100-SXM4-40GB  On| 00000000:81:00.0 Off |                    0 |
| N/A   46C    P0   165W / 400W |   8200MiB / 40960MiB |     72%      Default |
|                               |                      |              Enabled |
+-------------------------------+----------------------+----------------------+

Що це означає: Ви підтверджуєте точну гілку драйвера, сумісність CUDA, режим персистентності і чи увімкнено MIG.

Рішення: Зафіксуйте цю трійку (модель GPU + версія драйвера + версія CUDA) у вашому CMDB і маніфестах розгортання. Якщо вона змінюється несподівано — поводьтеся з цим як з продакшен-змінною.

Завдання 2: Перевірте інстанси MIG і підтвердіть відсутність випадкового шарингу

cr0x@server:~$ nvidia-smi -L
GPU 0: NVIDIA A100-SXM4-40GB (UUID: GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)
  MIG 1g.5gb Device 0: (UUID: MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/1/0)
  MIG 1g.5gb Device 1: (UUID: MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/2/0)
  MIG 2g.10gb Device 2: (UUID: MIG-GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/3/0)

Що це означає: GPU розділено на частини. Робочі навантаження можна призначати на UUID інстансів MIG.

Рішення: Якщо ви робите мультиорендне планування, розміщуйте орендарів лише на виділені інстанси MIG. Якщо ви не можете пояснити, що саме спільне між інстансами у вашій архітектурі — не називайте це «жорсткою ізоляцією».

Завдання 3: Підтвердіть, які процеси використовують GPU

cr0x@server:~$ nvidia-smi pmon -c 1
# gpu        pid  type    sm   mem   enc   dec   jpg   ofa   command
    0      19423     C     78    20     0     0     0     0   python
    0      20110     C      5     2     0     0     0     0   tritonserver

Що це означає: Ви бачите активні compute-процеси і приблизне використання ресурсів.

Рішення: Якщо ви очікуєте одноорендну поведінку і бачите невідомі процеси — зупиніться і розслідуйте. Якщо ви мультиорендні — перевірте, що процеси відповідають очікуваним pod/job.

Завдання 4: Змоделюйте файлові пристрої GPU і права доступу (поверхня втечі з контейнера)

cr0x@server:~$ ls -l /dev/nvidia* /dev/dri/*
crw-rw-rw- 1 root root 195,   0 Jan 17 10:15 /dev/nvidia0
crw-rw-rw- 1 root root 195, 255 Jan 17 10:15 /dev/nvidiactl
crw-rw-rw- 1 root root 195, 254 Jan 17 10:15 /dev/nvidia-modeset
crw-rw---- 1 root video 226,   0 Jan 17 10:15 /dev/dri/card0
crw-rw---- 1 root render 226, 128 Jan 17 10:15 /dev/dri/renderD128

Що це означає: Світоводозаписувані (world-writable) вузли пристроїв GPU — тривожний сигнал. Вони розширюють, хто може звертатися до драйвера ядра.

Рішення: Загостріть права (групи як video/render), і переконайтесь, що контейнери отримують лише конкретні пристрої, що їм потрібні. «chmod 666» — для лабораторій, не для проду.

Завдання 5: Перевірте, чи увімкнено IOMMU (контейнмент DMA)

cr0x@server:~$ dmesg | grep -E "IOMMU|DMAR" | head
[    0.812345] DMAR: IOMMU enabled
[    0.812900] DMAR: Host address width 46
[    0.813210] DMAR: DRHD base: 0x000000fed90000 flags: 0x0

Що це означає: Платформа має DMA remapping. Це базовий контроль проти «пристрій може читати усе».

Рішення: Якщо ви цього не бачите — виправте параметри завантаження (Intel: intel_iommu=on; AMD: amd_iommu=on) і валідуйте в staging. Нема IOMMU + ненадійні робочі навантаження = виклик.

Завдання 6: Підтвердіть, що GPU у групі IOMMU (саніті для passthrough)

cr0x@server:~$ for d in /sys/kernel/iommu_groups/*/devices/*; do echo "$(basename "$(dirname "$d")") $(basename "$d")"; done | grep -i nvidia | head
27 0000:81:00.0
27 0000:81:00.1

Що це означає: GPU і пов’язані з ним функції згруповані для ізоляції.

Рішення: Якщо ваш GPU ділить групу IOMMU з випадковими пристроями, passthrough і сильна ізоляція ускладнюються. Налаштуйте BIOS/ACS або обирайте інші слоти/платформи.

Завдання 7: Перевірте забруднення модуля ядра і версії модулів

cr0x@server:~$ uname -r
6.5.0-27-generic
cr0x@server:~$ modinfo nvidia | egrep "version:|srcversion|vermagic"
version:        550.54.14
srcversion:     1A2B3C4D5E6F7890ABCD123
vermagic:       6.5.0-27-generic SMP preempt mod_unload

Що це означає: Підтверджує точний білд модуля ядра і сумісність з ядром. Допомагає під час триажу інциденту («чи цей вузол на дивному драйвері?»).

Рішення: Якщо у вас у пулі змішані версії драйверів — припиніть так робити. Це перетворює дебаг на археологію.

Завдання 8: Слідкуйте за помилками Xid (сигнали апаратних/драйверних збоїв)

cr0x@server:~$ journalctl -k -g "NVRM: Xid" -n 5
Jan 17 09:58:01 server kernel: NVRM: Xid (PCI:0000:81:00): 31, pid=19423, name=python, Ch 0000003a
Jan 17 09:58:01 server kernel: NVRM: Xid (PCI:0000:81:00): 13, Graphics Exception: ESR 0x404600=0x80000002

Що це означає: Коди Xid вказують на збої GPU. Деякі — помилки додатків; деякі — регресії драйвера; деякі — апаратні.

Рішення: Якщо Xid корелюють з оновленням драйвера — відкотіть канару. Якщо з певними навантаженнями — ізолюйте і відтворіть. Якщо з температурою/живленням — перевірте охолодження і подачу живлення.

Завдання 9: Перевірте стан PCIe (коректовані помилки натякають на нестабільність)

cr0x@server:~$ journalctl -k -g "PCIe Bus Error" -n 5
Jan 17 09:57:49 server kernel: pcieport 0000:80:01.0: PCIe Bus Error: severity=Corrected, type=Physical Layer
Jan 17 09:57:49 server kernel: pcieport 0000:80:01.0: device [8086:2030] error status/mask=00000001/00002000

Що це означає: Коректовані помилки — не «гарно». Це провісник поганих ліній, неякісних riser-ів, маргінальної цілісності сигналу або проблем з живленням.

Рішення: Якщо лічильники зростають — заплануйте техобслуговування до появи некоректованих помилок і зупинки тренувань. Надійність — нудний родич безпеки.

Завдання 10: Перевірте ізоляцію пристроїв cgroup на вузлі Kubernetes

cr0x@server:~$ kubectl get pods -A -o wide | grep gpu
mlteam-a   infer-7d9c6f6d7d-9p2kq   1/1   Running   0   2d   10.42.3.19   gpu-node-03
mlteam-b   train-0                  1/1   Running   0   1d   10.42.3.20   gpu-node-03
cr0x@server:~$ kubectl exec -n mlteam-a infer-7d9c6f6d7d-9p2kq -- ls -l /dev/nvidia0
crw-rw---- 1 root video 195, 0 Jan 17 10:15 /dev/nvidia0

Що це означає: Два поди ділять вузол; ви перевіряєте, чи контрольовано експозицію пристрою і чи не світоводозаписуваний він.

Рішення: Якщо ви мультиорендні — впровадьте node pools + taints/tolerations + політики device plugin, щоби несуміжні орендарі не співіснували, якщо ви цього явно не допустили.

Завдання 11: Підтвердіть, чи можливий скидання GPU і чи використовується він між орендарями

cr0x@server:~$ nvidia-smi --gpu-reset -i 0
GPU 00000000:81:00.0 is currently in use by one or more processes.
Reset could not be performed.

Що це означає: Ви не можете скинути GPU, що використовується; скиди дисраптивні і вимагають оркестрації.

Рішення: Якщо ви покладаєтесь на скиди як «витирач», реалізуйте хук у планувальник: дренуйте навантаження, скиньте, потім запускайте наступного орендаря. Інакше — ставтеся до «скидання між орендарями» як до фантазії.

Завдання 12: Перевірте режим персистентності і вирішіть, чи він шкодить ізоляції

cr0x@server:~$ nvidia-smi -q | grep -A2 "Persistence Mode"
    Persistence Mode                    : Enabled
    Accounting Mode                     : Disabled

Що це означає: Persistence mode тримає стан драйвера «теплим» для швидкого старту. Він також може зберігати більше стану між межами джобів.

Рішення: Для суворої багатоорендної ізоляції розгляньте відключення persistence mode у спільних пулах і виміряйте втрату продуктивності. Не робіть це бездумно; робіть це свідомо.

Завдання 13: Перевірте hugepages і тиск pinned memory (продуктивність + побічні ефекти)

cr0x@server:~$ grep -E "HugePages|Hugetlb" /proc/meminfo
HugePages_Total:       8192
HugePages_Free:        1024
HugePages_Rsvd:         512
Hugetlb:           16777216 kB

Що це означає: Навантаження GPU часто опосередковано використовують pinned memory і hugepages. Тиск тут може викликати стрибки латентності і дивні відмови, що виглядають як «GPU повільний».

Рішення: Якщо HugePages_Free колапсує під час старту джобу — налаштуйте розподіл hugepage на пул вузлів і припиніть oversubscribe пам’ять як хобі.

Завдання 14: Виявіть підозріле мапування пристроїв всередині контейнера

cr0x@server:~$ kubectl exec -n mlteam-b train-0 -- sh -lc 'mount | grep -E "nvidia|dri" || true; ls -l /dev | grep -E "nvidia|dri"'
tmpfs on /dev type tmpfs (rw,nosuid,strictatime,mode=755,size=65536k)
crw-rw---- 1 root video 195, 0 Jan 17 10:15 nvidia0
crw-rw---- 1 root video 195, 255 Jan 17 10:15 nvidiactl

Що це означає: Ви перевіряєте, чи контейнер бачить більше вузлів пристроїв, ніж потрібно. Деякі рантайми випадково монтують зайві контролі.

Рішення: Якщо контейнери бачать /dev/nvidiactl і ви цього не очікували — перегляньте конфіг рантайма. Мінімізуйте експозицію пристроїв. Поверхня атаки масштабується з дескрипторами файлів.

Завдання 15: Підтвердіть стан lockdown ядра / Secure Boot (перешкоджає деяким змінам ядра)

cr0x@server:~$ cat /sys/kernel/security/lockdown
integrity
cr0x@server:~$ mokutil --sb-state
SecureBoot enabled

Що це означає: Lockdown режим і Secure Boot ускладнюють завантаження непідписаних модулів ядра або підміну ядра — корисно, коли ваш драйвер GPU — привілейований бінарник.

Рішення: Якщо Secure Boot вимкнено у середовищах з ненадійними навантаженнями, ви погоджуєтесь на більший радіус ураження. Увімкніть його, а потім налаштуйте підписування драйверів.

Завдання 16: Перевірте, що робить планувальник (чи ви ко-локуєте орендарів?)

cr0x@server:~$ kubectl describe node gpu-node-03 | egrep -A3 "Taints|Labels"
Labels:             nodepool=gpu-shared
                    accelerator=nvidia
Taints:             dedicated=gpu-shared:NoSchedule

Що це означає: Мітки/taints вузла інформують, чи кластер призначений для спільного використання.

Рішення: Якщо чутливі навантаження потрапляють на gpu-shared, це політична помилка. Виправляйте обмеження планування і admission controls, а не просто «кажіть людям бути обережнішими».

Це більше ніж десяток перевірок. Запускайте їх регулярно. Автоматизуйте те, що можете, і ставте алерти на дрейф. Безпека GPU — це 30% архітектура і 70% не дозволяти парку тихо змінюватися під вами.

Швидкий план діагностики

Коли щось пахне проблемою — несподівані виходи, необґрунтована латентність, дивні кореляції між орендарями — вам потрібен швидкий шлях до «це вузьке місце, це баг чи це порушення меж?»
Ось план, що працює під час інциденту.

Перше: класифікуйте відмову (конфіденційність vs цілісність vs доступність)

  • Конфіденційність: підказки, ембеддинги, тензори або ваги з’являються там, де не повинні; логи показують неочікуваний доступ; орендарі скаржаться, що «бачать інших».
  • Цілісність: результати дрейфують, недетерміновані виходи, приховане зниження точності, невідповідність контрольних сум артефактів.
  • Доступність: підвішування GPU, ресети, шторм Xid, різке падіння продуктивності, таймаути.

Друге: визначте, чи відбувається шаринг

  • Чи увімкнено MIG і правильно призначено, або ви тайм-слайсите повні GPU?
  • Чи два орендарі на тому самому фізичному вузлі? На тому самому GPU? Один за одним на тому самому GPU?
  • Чи режим персистентності зберігає контексти теплими?

Третє: шукайте «класичні сигнали»

  • Логи ядра: помилки Xid, помилки шини PCIe, IOMMU-фолти.
  • Мапування процесів: неочікувані PIDs на GPU, зомбі-контексти.
  • Дрейф планувальника: змінені taints/labels, некоректна конфігурація пулів, нова версія GPU-плагіна.

Четверте: ізолюйте шляхом віднімання

  1. Перемістіть навантаження на відомий одноорендний вузол і порівняйте поведінку.
  2. Відключіть «корисну» оптимізацію: persistence mode, агресивні пули пам’яті, тайм-слайсинг.
  3. Зафіксуйте версії драйвера/рантайму і відтворіть. Якщо не можете відтворити детерміновано — ви не можете стверджувати, що виправили проблему.

П’яте: вирішіть, чи ви в «режимі інциденту безпеки»

Якщо є правдоподібне перехресне витікання даних між орендарями — припиніть ставитися до цього як до багу продуктивності. Заморозьте зміни планування, збережіть логи, снапшоти конфігурацій і ескалюйте.
Тут хочеться парафразу Генна Кранца: будь твердим і компетентним — без драм, без заперечень, лише дисциплінована відповідь.

Типові помилки: симптом → корінь проблеми → виправлення

Невдачі в безпеці GPU часто маскуються під «дивну продуктивність» або «ML недетермінований». Деякі — так. Деякі — ні. Ось польовий гайд.

Помилка 1: «Нам безпечно, бо це контейнер»

Симптоми: под може бачити вузли пристроїв GPU, які він не повинен бачити; неочікувані краші ядра; команда безпеки питає «який модуль ядра парсить вхідні дані орендаря?» і всі дивляться у підлогу.

Корінь: Доступ до GPU мостить прямо в драйвер ядра хоста. Контейнери не віртуалізують ядро.

Виправлення: обмежте експозицію /dev, використовуйте виділені пул вузлів для ненадійних орендарів і ставтесь до оновлень драйвера GPU як до оновлень ядра — з канарами і відкатами.

Помилка 2: «Нам не потрібен IOMMU; він повільніший»

Симптоми: незрозумілі корупції пам’яті, рідкі паніки хоста, страшні результати аудиту або неможливість захистити межі DMA.

Корінь: DMA remapping вимкнено. GPU може доступатися до пам’яті хоста занадто вільно.

Виправлення: увімкніть IOMMU у BIOS і параметрах ядра; перевірте групування пристроїв; заміряйте реальний вплив замість припущень.

Помилка 3: «Скидання GPU — це безпечне витирання»

Симптоми: «ми скидаємо між орендарями», але насправді не можемо скинути під навантаженням; періодичні відмови після примусових скидань; зберігається залишковий контекст.

Корінь: скиди операційно важкі; деякий стан може зберігатися в інших місцях; і не можна скинути те, що не можемо дренувати.

Виправлення: реалізуйте дренування джобів + оркестрацію скидання або перейдіть до жорсткої ізоляції (виділені GPU/MIG) і явного занулення буферів у коді.

Помилка 4: «Режим продуктивності нешкідливий»

Симптоми: зростання кореляції між джобами, дивна поведінка теплих стартів і дрейф, що зникає при перезавантаженні вузлів.

Корінь: persistence mode, кешуючі аллокатори і розігріті контексти тримають більше стану, ніж ви думаєте.

Виправлення: визначте рівні безпеки. Для високочутливих навантажень відключіть теплий стан або ізолюйте на одноорендному обладнанні.

Помилка 5: «MIG означає ідеальну ізоляцію»

Симптоми: орендарі все ще впливають на продуктивність один одного; аудитори питають, що спільне; ви не можете відповісти без слайд-дека від вендора.

Корінь: MIG зменшує спільність, але не стирає її. Деякі компоненти лишаються спільними, а прошивка — спільний шар.

Виправлення: ставтесь до MIG як до інструменту зниження ризику, а не як до доказу. Додайте політики планування, моніторинг і обмеження, які орендарі можуть співжити.

Помилка 6: «Це просто недетермінованість»

Симптоми: регульовані або бізнес-критичні виходи дрейфують; різні запуски дають різні рішення; «відбувається лише під навантаженням».

Корінь: конкуренція за спільні ресурси змінює порядок виконання, таймінг і поведінку плаваючих точок у редукціях.

Виправлення: увімкніть детерміновані режими, де доступні, ізолюйте критичні навантаження і припиніть змішувати ad-hoc роботи з регульованими пайплайнами на спільних GPU.

Помилка 7: «Ми пропатчимо драйвер пізніше; GPU крихкі»

Симптоми: гілки драйверів розходяться; ви боїтесь апгрейдів; advisory з безпеки накопичуються; зрештою вас прив’язує до старого стека, що не може запускати нові фреймворки.

Корінь: відсутність дисципліни канарів і відкатів, плюс недостатнє тестування GPU-навантажень.

Виправлення: побудуйте пайплайн патчування GPU з автоматичними smoke-тестами (прості ядра, схеми алокації пам’яті, NCCL колективи) і поетапним розгортанням.

Жарт №2 (коротко, по суті): «Ми оновимо драйвер GPU наступного кварталу» — інфраструктурна версія «Я почну робити бекапи завтра».

Чек-листи / покроковий план

Покроково: загартуйте пул багатоорендних GPU-вузлів

  1. Визначте рівень безпеки: одноорендні вузли для чутливих навантажень; спільні вузли лише для довірених внутрішніх навантажень або для орендарів, яких ви готові обмежувати сильнішими контролями.
  2. Увімкніть IOMMU і перевірте в логах. Підтвердіть сані групи IOMMU. Це базова умова для безпеки DMA.
  3. Стандартизуйте матрицю драйвер/рантайм для кожного пулу. Один пул — одна гілка драйвера, одна ціль CUDA/ROCm. Дрейф — де ховаються інциденти.
  4. Заблокуйте права на пристрої для /dev/nvidia* та /dev/dri/*. Переконайтесь, що контейнери отримують лише потрібні пристрої.
  5. Використовуйте розподіл свідомо: профілі MIG для контрольованого шарингу; уникайте ad-hoc тайм-слайсингу між несуміжними орендарями.
  6. Впровадьте admission controls так, щоб лише схвалені namespace могли запитувати GPU, і лише в затверджених пулах (через node selectors, taints і runtime class).
  7. Відключіть «корисні» persistence-функції для пулів високої чутливості, або доведіть, що вони не зберігають чутливий стан у вашому середовищі.
  8. Занулюйте чутливі буфери в коді в шляхах помилок і при ранніх виходах. Не покладайтеся на поведінку аллокатора.
  9. Інструментуйте логи ядра для Xid, IOMMU-фолтів і PCIe-помилок. Ставте алерти на зміни, не лише на абсолютні значення.
  10. Канарьте кожне оновлення драйвера з репрезентативними навантаженнями, потім поступово розкочуйте. Ставтесь до GPU-вузлів як до спеціального флоту ядер — бо вони такі.

Чек-лист: ознаки, що вам слід негайно припинити шаринг GPU

  • Ви не можете гарантувати, який орендар запускався перед іншим на тому самому GPU.
  • У вас не увімкнено IOMMU або ви не перевірили його роботу.
  • Вузли пристроїв GPU у вас світоводозаписувані або широко доступні для подів.
  • Ви не можете швидко зіставити PIDs GPU з pod/job під час реагування на інцидент.
  • У вас немає канарного пайплайна для оновлень драйверів і ви боїтесь патчів.
  • Ви обробляєте регульовані дані або контрактні секрети і ваша історія ізоляції — «повірте нам».

Чек-лист: мінімальна телеметрія для безпеки й надійності GPU

  • Версія драйвера, версія прошивки (де доступно) і версія ядра по вузлу.
  • Використання GPU, використання пам’яті, ECC-події і події скидання.
  • Логи ядра: події Xid, IOMMU-фолти, помилки PCIe.
  • Логи розміщення планувальника: орендар → вузол → GPU/MIG інстанс.
  • Життєвий цикл джобу: часи старт/стоп, класифікація режиму відмови і чи було дренування/скидання між орендарями.

Поширені запитання

1) Чи вже існує еквівалент «Spectre для GPU»?

Були дослідження та advisory щодо бокових каналів і питань ізоляції GPU, але більшою є структурна думка: GPU ділять ресурси й запускають привілейовані драйвери.
Умови для великого класового порушення існують, навіть якщо заголовного CVE поки немає.

2) Чи практичні бокові канали у реальному світі?

Якщо атакувальник може запускати код на тому ж фізичному GPU (або на тому самому хості з спільними шляхами), практичність значно зростає.
Найскладніша частина зазвичай — співрозміщення; планування в хмарі і спільні кластери роблять це простішим, ніж хотілося б визнати.

3) Чи вирішує MIG проблему мультиорендної безпеки?

Воно допомагає — суттєво — розподілом ресурсів. Але «вирішує» — занадто сильне слово.
У вас усе ще є прошивка, драйвери і деякі спільні апаратні шляхи. Ставтесь до MIG як до «зниження ризику + кращі примітиви для планування», а не як до магічної повітряної прогалини.

4) Який найбільший ризик безпеки GPU у Kubernetes?

Межа — драйвер ядра хоста. Якщо ви даєте поду доступ до GPU — ви даєте йому складну поверхню атаки ядра.
Інший поширений ризик — дрейф політик: поди потрапляють на спільні вузли, бо labels/taints не застосовано.

5) Чи відключити persistence mode?

Для пулів високої чутливості багатоорендних — відключення є розумним дефолтом, а далі міряйте вплив на старт. Для одноорендних вузлів persistence mode зазвичай прийнятний і покращує надійність, зменшуючи churn драйвера.

6) Як запобігти витокам через залишкову пам’ять GPU?

Не покладайтеся на «мабуть, очищається». Додавайте явне занулення чутливих буферів в коді, особливо в шляхах помилок.
Операційно — ізолюйте орендарів (виділений GPU або інстанс MIG) і розгляньте оркестрацію дренування/скидання, де це можливо.

7) Оновлення драйвера GPU — це головно проблема безпеки чи надійності?

І те, й інше. Драйвер — привілейований код. advisory з безпеки важливі.
Але на практиці більшість команд спочатку страждають від регресій і підвішувань. Побудуйте канарний пайплайн, щоб патчити без азарту.

8) Чи може confidential computing захистити GPU-навантаження?

CPU-сторона confidential computing допомагає захищати пам’ять хоста і межі VM, що корисно.
GPU додає складності: DMA-пристрої, спільні кеші і модель довіри вендора. Вважайте це «покращує картину», а не «вирішує проблему».

9) Яке найшвидше зниження ризику, якщо ми не можемо переробити все?

Припиніть співрозміщення несуміжних орендарів на тому самому фізичному GPU. Використовуйте виділені GPU або інстанси MIG з суворим плануванням.
Потім увімкніть IOMMU і заблокуйте доступ до пристроїв. Ці два кроки усувають багато простих шляхів відмов.

10) Що казати аудиторам і клієнтам?

Розкажіть, що ви реально робите: чи GPU виділені, чи розподілені, чи тайм-слайсовані; як ви контролюєте доступ до пристроїв; ваш графік патчів; і ваш план реагування на інциденти.
Не перебільшуйте «ізоляцію», якщо не можете пояснити її до рівня пристрою і драйвера.

Наступні кроки, які можна зробити цього тижня

Якщо хочете одну практичну пораду: припиніть ставитися до GPU як до «простих акселераторів». Це спільні комп’ютери з дивною ієрархією пам’яті і привілейованим драйвером розміром із маленьке місто.

  1. Проінвентаризуйте і зафіксуйте версії GPU/драйвера/рантайму по пулу вузлів. Зробіть дрейф видимим.
  2. Увімкніть і перевірте IOMMU. Потім підтвердіть сані групи IOMMU.
  3. Аудитуйте права /dev і експозицію пристроїв у контейнерах. Заберіть широкий доступ.
  4. Визначте політику сусідства: одноорендність, лише MIG-шеринг або тайм-слайсинг як крайній захід.
  5. Додайте канарний пайплайн для оновлень драйверів GPU з критеріями відкату.
  6. Інструментуйте сигнали: помилки Xid, помилки PCIe, IOMMU-фолти і мапування планувальника.

Якщо завтра станеться «Spectre для графіки», ви не переможете найкращим прес-релізом.
Ви переможете, маючи менше спільних меж, кращу телеметрію і дисципліну шипити пом’якшення, не знімаючи продакшен.

← Попередня
Proxmox ZFS «не вдається імпортувати пул»: причини, перевірки та варіанти відновлення
Наступна →
Ера 14 нм: як техпроцес перетворився на бізнес-драму

Залишити коментар