12

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

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

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

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

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

Спасибо

2 ответа2

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 работать немного дольше и заставит его обнаруживать больше разломы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .