Тільки так, як modprobe
"перемагає" безпеку, завантажуючи новий код у ядро.
З різних причин іноді має сенс мати напівпривілейований код (наприклад, графічні драйвери всередині сервера X), що працює в просторі користувача, а не в потоці ядра.
- Вміти
kill
це легше, якщо тільки він не замикає HW.
- Запросивши на сторінку запит свого коду / даних з файлів у файловій системі. (Пам'ять ядра не є сторінковим)
- Надаючи йому власний віртуальний адресний простір, де помилки на сервері X можуть просто зірвати X-сервер, не знімаючи ядро.
Це не дуже сприяє безпеці, але є великі переваги надійності та архітектури програмного забезпечення.
Введення графічних драйверів у ядро може зменшити контекстні комутації між клієнтами X та сервером X, як-от лише один користувач-> kernel-> користувач, замість того, щоб отримувати дані в інший процес використання простору використання, але X-сервери історично занадто великі і занадто глючні бажати їх повністю в ядрі.
Так, зловмисний код із цими приватними кодами може захопити ядро, якщо воно захоче, використовуючи /dev/mem
для зміни коду ядра.
Наприклад, на x86, запустіть cli
інструкцію щодо відключення переривань на цьому ядрі після iopl
виклику системи, щоб встановити рівень привілеїв вводу-виводу на дзвінок 0.
Але навіть x86 iopl
"тільки" надає доступ до деяких вказівок : вхід / вихід (і рядкові версії вводу / виходу) та cli / sti. Це не дозволяє використовувати rdmsr
або wrmsr
читати чи записувати "типові регістри моделей" (наприклад, IA32_LSTAR
яка встановлює адресу точки введення ядра для syscall
інструкції x86-64 ), або використовувати lidt
для заміни таблиці дескрипторів переривання (що дозволило б вам повністю прийняти над машиною з існуючого ядра, принаймні на цьому ядрі.)
Ви навіть не можете читати контрольні регістри (як, наприклад, CR3, який містить фізичну адресу сторінки-каталогу верхнього рівня, що атакувальний процес може бути корисним як зміщення /dev/mem
для зміни власних таблиць сторінок як альтернативу mmap
більшій кількості) /dev/mem
. )
invd
(недійсні всі кеші без зворотного запису !! ( використовуйте case = ранній BIOS до налаштування оперативної пам’яті)) - це ще одна забава, яка завжди потребує повного CPL 0 (поточний рівень привілеїв), а не лише IOPL. Навіть wbinvd
привілейований, тому що він такий повільний (і не перериваючий), і він повинен обмітати всі кеші по всіх ядрах. (Див Чи є спосіб , щоб очистити весь кеш процесора , пов'язаний з програмою? І використання інструкції WBINVD )
Помилки, які призводять до переходу на неправильну адресу, що працює з даними, як код, таким чином, не можуть виконати жодну з цих інструкцій випадково на сервері X-простору користувача.
Поточний рівень привілеїв (у захищеному та тривалому режимі) - це низькі 2 біти cs
(селектор кодового сегмента) . mov eax, cs
/ and eax, 3
працює в будь-якому режимі для читання рівня привілеїв.
Щоб записати рівень привілеїв, ви робите a jmp far
або call far
встановлюєте CS:RIP
(але запис GDT / LDT для цільового сегмента може обмежувати його на основі старого рівня привілеїв, через що користувальницький простір не може цього зробити, щоб підвищити себе). Або ви використовуєте int
або syscall
для переключення на дзвінок 0 у точці введення ядра.
iopl
не дає всіх привілейованих інструкцій, тому вона все ще корисна для того, щоб переконатися, що програма-баггі-простір користувача не випадково запускаєтьсяinvd
, перестрибуючи пошкоджений вказівник функції, який вказує на виконувану пам'ять, починаючи з0F 08
байтів. Я додав відповідь із деяких причин, що не стосуються безпеки, чому корисно, щоб процеси в просторі користувачів підвищували свої привілеї.