Чи дд, якщо = / dev / urandom of = / dev / mem безпечний?


10

Що саме це робить? Я не розумію, як ви могли отримати доступ до базової пам'яті за допомогою цього ... здається дивним. Це безпечно?

dd if=/dev/urandom of=/dev/mem

Що це за "безпечний", про який ви говорите? Безпечно щодо чого?
waltinator

Чого ви хочете досягти за допомогою цієї команди?
jochen

Відповіді:


23

Не спробуйте цього вдома! Це може призвести до збою вашої системи, і якщо вам по-справжньому не пощастить, це може пошкодити периферійні пристрої або зробити комп'ютер незавантаженим.

Насправді, на більшості платформ воно просто не вдається з помилкою, але це залежить від апаратної архітектури. Однозначно немає гарантії, що це нешкідливо, якщо ви не виконаєте команду як непривілейований користувач. Для непривілейованого користувача команда є абсолютно нешкідливою, тому що ви не можете її відкрити /dev/mem.

Коли ви запускаєте команду як root, ви повинні знати, що ви робите. Ядро іноді заважатиме вам робити щось небезпечне, але не завжди. /dev/mem- це одна з тих потенційно небезпечних речей, де ти насправді повинен знати, що робиш.

Я збираюся ознайомитись із тим, як /dev/memпрацює запис на Linux. Загальний принцип був би таким же в інших Unices, але такі речі, як параметри ядра, зовсім інші.

Що відбувається, коли процес читає або записує у файл пристрою, залежить від ядра. Доступ до файлу пристрою виконує деякий код у драйвері, який обробляє цей файл пристрою. Наприклад, запис для /dev/memвиклику функції write_memвdrivers/char/mem.c . Ця функція бере 4 аргументи: структура даних, яка представляє відкритий файл, вказівник на дані, які потрібно записати, кількість байтів для запису та поточне положення у файлі.

Зауважте, що ви дістаєтесь так далеко, лише якщо абонент мав дозвіл на відкриття файлу. Файли пристрою зазвичай дотримуються дозволів файлів. Нормальні права дозволу /dev/memє crw-r-----власником root:kmem, тому якщо ви спробуєте відкрити його для запису, не використовуючи root, ви просто отримаєте "дозвіл відмовлено" (EACCESS). Але якщо ви root (або якщо root змінив дозволи цього файлу), відкриття проходить, і тоді ви можете спробувати записати.

Код у цій write_memфункції робить деякі перевірки правильності, але цих перевірок недостатньо для захисту від усього поганого. Перше, що він робить - перетворити поточну позицію файлу *pposу фізичну адресу. Якщо це не вдається (на практиці, оскільки ви знаходитесь на платформі з 32-бітовими фізичними адресами, але 64-розрядні зсуви файлів і зсув файлу більше 2 ^ 32), запис не вдається з EFBIG (файл занадто великий). Наступна перевірка полягає в тому, чи є діапазон фізичних адрес для запису дійсним для даної архітектури процесора, і чи є помилка результатом EFAULT (неправильна адреса).

Далі, на Sparc та m68k будь-яка частина запису на першій фізичній сторінці безшумно пропускається.

Зараз ми дійшли до основного циклу, який повторює дані в блоках, які можуть вміщуватися в межах однієї сторінки MMU . /dev/memотримує доступ до фізичної пам'яті, а не до віртуальної пам'яті, але вказівки процесора для завантаження та зберігання даних у пам'яті використовують віртуальні адреси, тому код потрібно організувати для відображення фізичної пам'яті за деякою віртуальною адресою. В Linux, залежно від архітектури процесора та конфігурації ядра, це відображення існує або постійно, або має бути зроблено на ходу; це робота xlate_dev_mem_ptrunxlate_dev_mem_ptrскасовує все, що xlate_dev_mem_ptrробить). Потім функція copy_from_userзчитується з буфера, який був переданий вwriteсистемний виклик і просто записується на віртуальну адресу, де фізична пам'ять на даний момент відображена. Код надсилає звичайні інструкції щодо зберігання пам’яті, а що це означає, залежить від обладнання.

Перш ніж я обговорюю, що записується на фізичну адресу, я обговорюю перевірку, що відбувається до цього запису. Всередині циклу функція page_is_allowedблокує доступ до певних адрес, якщо CONFIG_STRICT_DEVMEMвключена опція конфігурації ядра (що за замовчуванням є): через них devmem_is_allowedможна отримати лише ті адреси, дозволені якими /dev/mem, для інших запис не вдається з EPERM (операція не дозволена). В описі цього параметра зазначено:

Якщо цей параметр увімкнено, а IO_STRICT_DEVMEM = n, файл / dev / mem дозволяє лише користувачеві простору доступ до простору PCI та коду BIOS та областям даних. Цього достатньо для дозиму та X та всіх звичайних користувачів / dev / mem.

Це дуже орієнтований на x86 опис. Фактично, загалом, CONFIG_STRICT_DEVMEMблокує доступ до адрес фізичної пам'яті, які відображають в оперативній пам'яті, але дозволяє отримати доступ до адрес, які не відображаються в оперативній пам'яті. Деталі дозволених діапазонів фізичної адреси залежать від архітектури процесора, але всі вони виключають оперативну пам’ять, де зберігаються дані ядра та наземних процесів користувача. Додатковий параметр CONFIG_IO_STRICT_DEVMEM(відключений на Ubuntu 18.04) блокує доступ до фізичних адрес, які вимагає драйвер.

Адреси фізичної пам'яті, які відображають в ОЗП . Отже, є адреси фізичної пам'яті, які не відображаються в ОЗУ? Так. Це обговорення, яке я пообіцяв вище про те, що означає написати на адресу.

Інструкція сховища пам'яті не обов'язково записувати в оперативну пам'ять. Процесор розкладає адресу і вирішує, до якої периферії відправити магазин. (Коли я кажу "процесор", я охоплюю периферійні контролери, які можуть не надходити від одного виробника.) ОЗУ - це лише одна з таких периферійних пристроїв. Те, як здійснюється відправка, дуже залежить від архітектури процесора, але основи більш-менш однакові для всіх архітектур. Процесор в основному розбиває більш високі біти адреси і шукає їх у деяких таблицях, заповнених на основі жорстко кодованої інформації, інформації, отриманої зондуванням деяких шин, та інформації, налаштованої програмним забезпеченням. Можливо, буде задіяно багато кешування та буферизації, але в двох словах, після цього розкладання,автобус, і тоді до периферійних пристроїв впоратися з цим. (Або результатом пошуку таблиці може бути те, що за цією адресою немає периферійного пристрою; у цьому випадку процесор переходить у стан лову, де він виконує якийсь код у ядрі, що зазвичай призводить до SIGBUS для процесу виклику.)

Магазин на адресу, яка відображається в оперативній пам'яті, не "робить" нічого іншого, крім перезапис значення, яке раніше зберігалося за цією адресою, з обіцянкою, що наступне завантаження за тією ж адресою поверне останнє збережене значення. Але навіть ОЗУ має кілька адрес, які не так поводяться: у неї є кілька регістрів, які можуть контролювати такі речі, як частота оновлення та напруга.

Взагалі, читання або запис у реєстр апаратних засобів робить все те, що апаратно запрограмовано. Більшість доступів до апаратних засобів працює таким чином: програмне забезпечення (як правило, код ядра) отримує доступ до певної фізичної адреси, це доходить до шини, яка з'єднує процесор з периферією, а периферія робить свою справу. Деякі процесори (зокрема x86) також мають окремі інструкції процесора, які викликають читання / запис на периферійні пристрої, відмінні від завантаження та зберігання пам'яті, але навіть на x86 багато периферійних пристроїв досягаються через завантаження / зберігання.

Команда dd if=/dev/urandom of=/dev/memзаписує випадкові дані в будь-яку периферію, яка відображається за адресою 0 (та наступними адресами, доки успіх запису). На практиці я вважаю, що у багатьох архітектурах фізична адреса 0 не має певного периферійного відображення до неї або має оперативну пам’ять, і тому сама перша спроба запису не вдається. Але якщо є периферійна карта, відображена за адресою 0, або якщо ви змінили команду для запису на іншу адресу, ви запустите щось непередбачуване в периферії. З випадковими даними при збільшенні адрес навряд чи можна зробити щось цікаве, але в принципі це може вимкнути комп’ютер (можливо, це адреса, яка насправді робить це), перезаписати деякі настройки BIOS, які унеможливлюють завантаження або навіть натискають на деякі баггі периферійний таким чином, що шкодить йому.

alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'

Дякую! Це те, що я шукав! Мене просто збентежило, чи / dev / mem дозволяє доступ до пам'яті до таких речей, як периферія та речі, пов'язані з обладнанням!
Coder14

Периферія не може бути відображена за фізичною адресою 0 на x86 ПК; ця конфігурація ніколи не завантажиться.
Джошуа

Це неправда
Іван

1
Звичайно, ви можете пошкодити ядро, але не біос
Yvain

1
@Yvain Що не відповідає дійсності? І насправді ви не можете пошкодити ядро, якщо CONFIG_STRICT_DEVMEMвоно включене.
Жиль "ТАК - перестань бути злим"

12

Це безпечно, якщо ви правильно налаштували ядро ​​(безпечне, оскільки воно не працюватиме)

На пам'ять сторінки вручну (4) :

/ dev / mem - це файл пристрою символів, який є зображенням основної пам'яті комп'ютера. Він може бути використаний, наприклад, для вивчення (і навіть виправлення) системи.

Тож теоретично dd if=/dev/urandom of=/dev/memслід перезаписати весь адресний простір встановленої фізичної пам'яті, а оскільки ядро ​​та інші програми працюють із пам'яті, це повинно ефективно руйнувати систему. На практиці існує обмеження. З тієї ж сторінки чоловіка:

Оскільки Linux 2.6.26 і залежно від архітектури, опція конфігурації ядра CONFIG_STRICT_DEVMEM обмежує області, до яких можна отримати доступ через цей файл.

Спробувавши це на віртуальній машині Ubuntu 18.04, він повертає помилку dd: writing to '/dev/mem': Operation not permittedнавіть з sudoі незважаючи на дозволи для root crw-r-----. З Ubuntu Wiki :

/ dev / mem захист

Деякі програми (Xorg) потребують прямого доступу до фізичної пам'яті з користувальницького простору. Для забезпечення цього доступу існує спеціальний файл / dev / mem. Раніше можна було переглядати та змінювати пам'ять ядра з цього файлу, якщо зловмисник мав кореневий доступ. Параметр ядра CONFIG_STRICT_DEVMEM був введений для блокування доступу до пам'яті пристрою (спочатку називався CONFIG_NONPROMISC_DEVMEM).

Таким чином, технічно, ні це не є безпечним (оскільки це призведе до виходу з ладу системи), і якщо параметр ядра CONFIG_STRICT_DEVMEMвідключений, це отвір для безпеки, але, як я бачу, команда не запустилася, якщо цю опцію ввімкнено. Згідно з дублікатом між веб-сайтів , перезавантаження виправить будь-які проблеми з нею, але, звичайно, дані в оперативній пам’яті в цей час будуть втрачені і не видаляються на диск (якщо такі були).

Існує запропонований метод на дублікаті, пов'язаному раніше, використовуючи, busybox devmemтому якщо ви вирішили возитися з оперативною пам’яттю, все-таки може бути спосіб.


6
"Це безпечно" Ні, це, безумовно, це не так. Навіть за допомогою CONFIG_STRICT_DEVMEM, ви можете отримати доступ до областей пам'яті, де відображена периферія, що є сутністю /dev/mem. Якщо ви запишете випадкові речі на периферійні пристрої, все може статися. Якщо ви намагаєтеся отримати доступ до адреси, яка не відображається, ви отримуєте "операцію не дозволено", і команда починається з адреси 0. Будь-яка адреса 0 відображається на щось погане, залежить від апаратної архітектури. Наскільки я знаю, це може ніколи не підключатися ні до чого на ПК, але це взагалі не безпечно.
перестань бути злим"

1
@Gilles На x86 (не впевнений у x86-64) перший 1 KiB оперативної пам’яті (адреси 0x0 до 0x3ff) містить вектори переривання; вартість байта на чотири байти на вектор. Якщо вам вдасться замінити тих, хто випадковим сміттям, всілякі цікаві речі, швидше за все, трапляться дуже скоро. Швидше за все, у вас виникла подвійна або потрійна несправність, і система вийде з ладу, але гарантій немає ...
CVn

@aCVn Звичайно, що-небудь відображено ( head -c 1024 </dev/mem | od -tx1), але я не знаю, чи використовуються вони, коли процесор не знаходиться в реальному режимі (режим 8088). Я не думаю, що їх можна використовувати в 64-бітному режимі: зрештою, вектори переривання 8088 мають лише 32 біти для адреси. І, до речі, це доступно з CONFIG_STRICT_DEVMEMнабором, тому я думаю, що Linux не використовує його.
перестань бути злим"

@Gilles: сторінка 0 на x86 зарезервована для v86, завантажувача тощо; ось справжня векторна таблиця переривань режиму. У захищеному режимі IVT десь інше (машинний реєстр говорить де).
Джошуа
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.