Страницы

воскресенье, 5 ноября 2023 г.

Проверяемые адреса при работе с SYSTEM

Добавлено свойство проверяемости при работе с низкоуровневыми адресами в процедурах из SYSTEM — ADR, BIT, GET, PUT, COPY.

  • Проверка выхода за границы адресуемого объекта.
  • Проверка обращения к локальным объектам после выхода из содержащих их процедуры.
  • Проверка разрешённости записи в соответствии с правилами языка.
  • Запрет получения адреса от переменной, содержащей указатели.

Подход показывает возможность отказа от принципа «всё или ничего» в отношении безопасности указателей. В таком воплощении низкоуровневая адресация позволяет обойти типизацию в тех случаях, когда это может быть необходимо, но не предоставляет произвольный грубый доступ ко всей памяти, не позволяя также нарушить многие гарантии исходного языка, и помогая избежать ряда уязвимостей[0]. Правильный код, написанный под такое воплощение SYSTEM будет правилен и для бесконтрольного обращения к памяти. Обратное, естественно, верно не всегда.

Адрес, напрямую хранимый как 32-битный INTEGER, не предоставляет возможности осуществлять такие проверки, поэтому применяется косвенность. Сам адрес в старших разрядах хранит индекс от кольцевой таблицы, в которой сохранены обычные указатели и связанные с ними сведения. В младших разрядах хранится смещение от базового адреса, что позволяет проводить адресную арифметику так же, как в обычной бесконтрольной адресации, но в пределах объекта. Старые адреса по мере вызова SYSTEM.ADR приходят в негодность. Части диапазонов обеих частей адреса зарезервированы для вероятностного выявления выхода за пределы применимости. Адреса локальных объектов перед завершением процедуры помечаются как устаревшие. Параметры процедуры, ссылающиеся на глобальные объекты, всё равно считаются локальными.

Так как косвенность позволяет работать с указателями любой размерности, то теперь работа с псевдомодулем SYSTEM доступна не только для 32-битных указателей, но и для 64-битных и для более экзотичных, подобных 128-битным указателям Эльбруса в защищённом режиме.


[0] Пример на forum.oberoncore.ru возможного нарушения памяти при использовании SYSTEM из-за неточной проверки входных параметров.

15 комментариев:

  1. Вроде у RISC-V тоже 128 битная адресация.

    ОтветитьУдалить
    Ответы
    1. Как я понимаю, оставлена она как гипотетический вариант и кроме того является только экстраполяцией 32- и 64- битной адресации, а не содержит сведений для защиты от нарушения границ как сделано для Эльбрус.

      Удалить
    2. Я читал обсуждение на LOR-е, что разработчики RISC-V пытаются сделать нечто похожее на Эльбрусовскую адресацию.

      Удалить
    3. Вот вроде https://www.linux.org.ru/gallery/screenshots/16507064?cid=16510647 нашел обсуждение. Это начало.

      Удалить
    4. Тут же просто мечтания о частном расширении общей системы команд и желании на уровне аппаратуры решать то, что на уровне языка решать не получается(из-за плохого выбора языка). К самому стандарту RISC-V это не относится.
      Заодно отмечу, что такая аппаратная защита хуже адекватной программной.

      Удалить
    5. Ну, думаю, это лучше чем вообще и без аппаратной защиты и без программной. Софта на Си и Си++ понаписали много и этот софт будет безопаснее запускать на архитектурах с такими защитами как у Эльбруса. Хотя прочитав некоторые посты в вашем блоге понимаешь, что и Си можно сделать безопасным благодаря современным компиляторам.

      Удалить
    6. Верно, язык C вполне допускает сборку с защитой от многих ошибок. И такие возможности пусть и менее эффективней тех, что предоставляет Oberon, но всё равно эффективней, чем аппаратные проверки. Главная проблема в том, что большинство разработчиков и сопровождающих даже не пытается их использовать, из-за чего они оказываются неприменимыми из-за поломок, к которым они приводят. Но с аппаратными защитами было бы то же самое.

      Удалить
    7. Может быть появление и распространение аппаратных архитектур с защитами побудит разработчиков учитывать их в своих программах. А то как я понимаю пока таких архитектур в массовом сегменте нет, нет и стимула у разработчиков, чтобы программа работала корректно и в защищенных режимах. Я слышал, что разработчики Эльбруса или АльтЛинукса сталкивались с ошибками/уязвимостями в программах и ядре линукса, которые отлавливал защищенный режим и исправляли их.

      Удалить
    8. Так если более доступные и эффективные программные проверки не побуждают, то с чего бы аппаратные проверки побуждали? Защитные свойства зависят не от целевого кода, а от исходного. И если исходный код требует, чтобы проверок не было, то у транслятора нет другого выбора, кроме как перевести в машинный код без проверок. И на это никак не влияет, есть ли аппаратные проверки или нет. Незащищённый режим элементарно воспроизводится поверх защищённого. Из-за этого, а также из-за неэффективности и получается, что аппаратные проверки — это не более, чем тупик имени культа карго.

      Удалить
    9. Получается, что такие опции компилятора для Си как ЕМНИП addresssanitizer, stackprotecktor и быстрее для программы и эффективнее по защите, чем любая аппаратная защита?

      Удалить
    10. Они не эффективней по защите, а эффективней по скорости. Нельзя сказать, что любые, просто у программной защиты всегда есть возможность выбрать более эффективный подход, в том числе и аппаратный, если он подходит, а также есть возможность не проверять в динамике то, что известно по статике. А просто аппаратные проверки такие, какие есть и применяются даже тогда, когда не нужно.
      А наиболее эффективные проверки на данный момент получаются в такой комбинации "-fsanitize=undefined -fno-sanitize=alignment -fsanitize-undefined-trap-on-error"

      Удалить
    11. Верно. Программные проверки эффективней аппаратных. Приведённые опции позволяют отлавливать и выход за границы. Если точней, это делают опции -fsanitize=bounds, -fsanitize=bounds-strict, -fsanitize=object-size, включённые в -fsanitize=undefined, так как нарушения памяти — это тоже неопределённое поведение. Они не дают 100% в защите, но достаточно хороши.

      Удалить
    12. Еще пара вопросов. Вот ваш транслятор Восток. Нужно ли при программировании на Обероне соблюдать какие-нибудь нюансы, чтобы потом оттранслированный в Си код собрался компилятором с включенными защитами?
      Возможны ли уязвимости в приложениях написаных на Обероне с компилятором Акрона из-за ошибок use-after-free и double-free и если возможны, снижен ли в Акроновском Обероне риск их появления по сравнению с Си и С++? Как я понимаю подобные ошибки и в Си и С++ не всегда приводят к уязвимостям.

      Удалить
    13. В трансляторе Восток воплощена идеология защиты по умолчанию. Поэтому если и нужно учитывать какие-либо нюансы, так только в том, чтобы не выключать проверки самостоятельно при генерации кода С или в настройках компилятора C.
      Про транслятор Антона Кротова знаю не много, но вряд ли у него есть защита от уязвимостей, связанных с неправильным освобождением. Если риск и снижен в сравнении с C, то, скорее, из-за отсутствия перекрёстного влияния с некоторыми другими не проверяемыми в C ошибками, так как часть уязвимостей требует выполнения целого ряда ошибок.

      Удалить
    14. Спасибо, Константин, за ваши ответы.

      Удалить

Обработка ошибок

Тема корректной обработки ошибок в программе является довольно сложным вопросом в программировании. Отчасти от того, что и она сама являет...