dmytrish (dmytrish) wrote,
dmytrish
dmytrish

COMEFROM memory protection

Недавно стукнула мені в голову одна ідейка щодо memory protection у операційних системах. Мабуть, я перевинайшов якийсь велосипед або в цій ідеї є якась принципова хріновість, — це я і хочу зрозуміти за допомогою шановної публіки.

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

Тому мікроядра примушені ходити довгою дорогою: «відіслали повідомлення в ядро, syscall» — «ядро копіює його собі і кладе в чергу, yield процеса або context switch на процес-адресат» — «повернулись у процес-адресат, скопіювали собі, обробили запит, відіслали відповідь, syscall» — «ядро копіює відповідь собі і кладе у чергу повідомлень, yield або виклик адресанта, копіювання в віртуальну пам’ять адресанта, context switch» — «адресант приймає відповідь».

Просто віртуальну пам’ять я б назвав GOTO memory protection: вона заснована на тому, *куди* направлений стрибок коду або звернення за даними, незалежно від того, звідки переходять або звертаються.

А що ж протилежністю GOTO? Правильно, інструкція COMEFROM, яка існує в деяких езотеричних мовах і досі здавалась мені абсолютно безглуздою. Як вона працює: COMEFROM 0xdeadbeef в будь-якому місці програми створює стрибок із 0xdeadbeef у це місце.

Ідея полягає в тому, щоб перевіряти *звідки* прийшов control flow або звернення за даними, і для певних ділянок дозволяти такі звернення. для інших ні. Таким чином, можна в одному адресному просторі тримати багато доменів коду-даних, у яких немає прямого доступу один до одного, але можуть бути публічні інтерфейси.

Тобто, якщо ми хочемо файлову систему як сервіс у юзерспейсі, ми створюємо в фізичній пам’яті домен коду «інтерфейс», доступ до якого можливий із будь-якої адреси, домен «код реалізації» та «дані реалізації», доступ до якого можливий лише лише із фізичної пам’яті ділянки «інтерфейс». Далі ми мапимо ці домени в адресний простір усіх зацікавлених процесів. Коли процесу необхідно, для прикладу, прочитати файл, він просто робить виклик функції із «інтерфейсу», вона валідує дані і викликає функцію із «реалізації». Прямий виклик неможливий і призводить до PageFault/DomainFault. Спроба записати дані із стороннього коду в «дані реалізації» також повинна закінчуватись DomainFault.

Таким чином, сервіс, подібний до мікроядерного, стає просто спільним кодом усіх клієнтів, які для нього виглядають як треди, які працюють із спільним станом. І виклик цього сервісу перетворюється в два виклики функцій в юзерспейсі. Проблеми синхронізації спільних даних, звичайно, гидкі, але сішників це не зупиняє і інструментарій є (м’ютекси-семафори-бар’єри-conditionals).

Найбільша проблема цієї ідеї — що DomainFault має реалізовуватись у залізі додатково до PageFault та всієї існуючої віртуальної пам’яті.
Крім того, неясно, наскільки витратна така модель по пам’яті. В принципі, для кожної ділянки фізичної пам’яті (сторінки або сегмента?) було б достатньо вказати, чи публічний доступ до неї, чи тільки із якогось одного діапазону/сегмента.

P.S. В певному розумінні ця ідея є ідеєю security capabilities. Код, який прийшов із «інтерфейсу», має capability доступу до даних та коду реалізації, будь-який інший виклик — ні.
Tags: osdev, ОСебудівництво, думки вголос, програмістське, процес
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 16 comments