Как ОС обнаруживает нарушения доступа к памяти

12

Как операционная система (предпочтительно Linux) узнает, что вы получили доступ к области памяти, к которой у вас нет доступа?

Этот вопрос был вдохновлен этими чертовыми указателями! Я вижу это так: все в компьютерах - это компромисс между скоростью, безопасностью, целостностью и тому подобным.

Я хорошо осведомлен о картах памяти в Linux, но мне кажется немного смешным, что ядро ​​проверяет, находится ли местоположение, к которому вы пытаетесь получить доступ, в допустимом диапазоне КАЖДЫЙ РАЗ, когда вы делаете доступ. Похоже, это потратило бы так много времени, которое можно было бы потратить на то, чтобы сделать что-то более продуктивное (но, возможно, менее безопасное без проверки!). Или, может быть, он запоминает все недавние обращения и проверяет их при каждом тике аппаратного таймера? (Но это звучит небезопасно и, опять же, медленно.)

Я был удивлен, что этот вопрос, кажется, остается без ответа в любом месте. Это то, что я всегда задавался вопросом. Это заставляет меня думать, что есть раздел аппаратного обеспечения, который будет делать это от имени ОС, на хорошем и удобном уровне абстракции. Но все же, возможно, потребуется загрузка карт памяти следующих процессов при каждом переключении контекста, что опять-таки звучит медленно.

Так что да, в любом случае, я продолжаю: как ОС обнаруживает нарушение памяти?

Благодарность

Doddy
источник

Ответы:

11

(Следующий ответ предполагает «современную» настольную, серверную или вышестоящую встроенную платформу (такую ​​как смартфоны, а также все более и более мелкие системы). Для систем x86 современные средства 386 и выше. Следующий ответ также предполагает «Современные» ОС, такие как практически любой Unix или Windows начиная с 95 года.)

Это не происходит в ОС, это происходит в процессоре, особенно в MMU ( блок управления памятью ) . MMU поддерживает виртуальную адресацию, в результате чего биты, составляющие указатель, напрямую не указывают физическое расположение битов в памяти.

В типичном MMU, когда указатель разыменовывается, MMU разбивает биты на две группы: старшие биты составляют номер страницы , а младшие биты составляют адрес внутри страницы. Большинство компьютеров и серверов используют страницы размером 4 КБ. MMU ищет номер виртуальной страницы в таблице с именем TLB (это то, что вы назвали «картами памяти процесса»). TLB указывает номер физической страницы, которая соответствует этой виртуальной странице. Затем MMU извлекает данные из физической страницы в памяти.

Если TLB не содержит запись для этого конкретного номера виртуальной страницы, MMU уведомляет процессор о недопустимом доступе; это обычно называется исключением.

Обратите внимание, что я не упомянул ОС до сих пор. Это потому, что вся эта операция не зависит от ОС. ОС вступает в игру, потому что она настраивает вещи двумя способами:

  • ОС отвечает за переключение задач. При этом, как вы и подозревали, он сохраняет текущий TLB и заменяет его сохраненным TLB для следующей запланированной задачи. Таким образом, каждый процесс имеет TLB, поэтому адрес 0x123456в процессе X может не указывать на то же фактическое место в ОЗУ, что и тот же адрес в процессе Y, или может просто быть недействительным. Если процесс пытается разыменовать указатель за пределами своего адресного пространства, он не достигает другого пространства процесса, скорее, он не достигает нигде .

  • ОС решает, что произойдет, когда возникнет исключение. Это может прервать процесс для недопустимого доступа к памяти (ошибка сегментации, общая ошибка защиты, ...). Это также способ реализации перестановки: обработчик исключений может решить извлечь некоторые данные из пространства подкачки, соответствующим образом обновить TLB и снова выполнить доступ.

Обратите внимание, что MMU обеспечивает безопасность, потому что процесс не может изменить свой собственный TLB. Только ядро ​​ОС может изменять TLB. Как работают разрешения на изменение TLB, выходит за рамки этого ответа.

Жиль "ТАК - перестань быть злым"
источник
6

1) Сбойные ошибки обнаруживаются блоком управления памятью. Когда вы запрашиваете память, ОС просит модуль управления памятью получить некоторые из аппаратных средств. Должно быть что-то, что отслеживает все большие блоки памяти, которые дает вам ОС. ОС как бы передает это MMU. Так как он знает всю память, которую он дал вам, он также может сказать вам, когда вы пытаетесь получить доступ к области памяти, которую вы не получили из распределений, ОС специально имеет для этого событие, память, которой вы не владеете. В конце концов, ОС убивает ваше приложение, вызывая либо segfault, либо эквивалент в других ОС.

Не все ОС имеют такую ​​защиту. MacOS до 9 не имел ничего подобного, хотя MMU действительно поддерживал это. Также как и Win 3.1. У Win95 была некоторая защита, так как она переходила между отсутствием защиты и добавлением новой.

2) ОС не знает никаких деталей, кроме этой. Если у вас есть случайный указатель, который обращается к памяти, которую вы никогда не выделяли, он знает. Если у вас есть тот, который входит в другую часть вашего приложения, он, конечно, не знает. Это позволяет вам испортить это. Именно здесь вы получаете поврежденные стеки, а случайные указатели из вашего приложения перезаписывают другие части вашего приложения.

Так что, да, вы можете прикрутить свои собственные данные. Если у вас есть блуждающий указатель, который перезаписывает ваше собственное приложение, вы НАДЕЕТСЯ, что попадете в свой стек, поскольку это, вероятно, приведет к другому нарушению при попытке вернуться из стека, но если вы попадете в свои собственные данные, вы никогда не узнаете.

Вы можете попытаться быть более строгим, чем «отсутствие защиты», есть инструмент Electric Fence ( http://perens.com/FreeSoftware/ElectricFence/ ), который заставит ваш MMU работать немного дольше и заставит его обнаруживать больше разломы.

Рич Гомолка
источник
Хорошо, вы можете более конкретно рассказать, как это работает? Например, откуда он знает, что конкретный процесс не может получить доступ к определенному месту? Что говорит ему, какие процессы могут получить доступ куда? Как это отличить? Спасибо
Додди
1
@panic - найдите Memory_management_unit в википедии и ссылки с этой страницы. Обратите внимание, что состояние процесса включает статус MMU. Вы можете потратить семестры на дизайн MMU, функции и интеграцию.
mpez0