Безопасность памяти - Memory safety

Безопасность памяти состояние защищенности от различных программные ошибки и уязвимости безопасности при работе с объем памяти доступ, например переполнение буфера и висячие указатели.[1] Например, Ява считается безопасным для памяти, потому что его обнаружение ошибок времени выполнения проверяет границы массива и разыменование указателей.[1] В отличие, C и C ++ разрешить произвольный арифметика указателя с указателями, реализованными как прямые адреса памяти без предоставления проверка границ,[2] и поэтому потенциально небезопасный для памяти.[3]

История

Ошибки памяти впервые были рассмотрены в контексте Управление ресурсами и совместное времяпровождение систем, чтобы избежать таких проблем, как вилка бомбы.[4] Развитие было в основном теоретическим, пока Червь Морриса, который использовал переполнение буфера в палец.[5] Поле компьютерная безопасность впоследствии быстро развивался, увеличиваясь с появлением множества новых нападения такой как возврат к libc атака и методы защиты, такие как неисполняемый стек[6] и рандомизация разметки адресного пространства. Рандомизация предотвращает большинство переполнение буфера атакует и требует от злоумышленника использовать кучное опрыскивание или другие зависящие от приложения методы для получения адресов, хотя их внедрение было медленным.[5] Однако развертывание технологии обычно ограничивается рандомизацией библиотек и расположением стека.

Подходы

Живучи,[7] его редизайн DieHarder,[8] и Инструмент распределенной отладки Allinea - это специальные распределители кучи, которые выделяют объекты на своей странице случайной виртуальной памяти, позволяя останавливать и отлаживать недопустимые операции чтения и записи и выполнять отладку с помощью той инструкции, которая их вызывает. Защита зависит от аппаратной защиты памяти, поэтому накладные расходы обычно невелики, хотя они могут значительно возрасти, если программа интенсивно использует выделение памяти.[9] Рандомизация обеспечивает только вероятностную защиту от ошибок памяти, но часто может быть легко реализована в существующем программном обеспечении путем повторного связывания двоичного файла.

Инструмент memcheck из Валгринд использует симулятор набора команд и запускает скомпилированную программу на виртуальной машине с проверкой памяти, обеспечивая гарантированное обнаружение подмножества ошибок памяти во время выполнения. Однако обычно это замедляет программу в 40 раз,[10] и, кроме того, должен быть явно проинформирован о пользовательских распределителях памяти.[11][12]

Имея доступ к исходному коду, существуют библиотеки, которые собирают и отслеживают допустимые значения указателей («метаданные») и проверяют каждый доступ к указателю на предмет достоверности метаданных, таких как Сборщик мусора Boehm.[13] В общем, безопасность памяти можно безопасно обеспечить, используя отслеживание сборки мусора и вставка проверок времени выполнения при каждом доступе к памяти; у этого подхода есть накладные расходы, но меньше, чем у Valgrind. Все языки со сборкой мусора используют этот подход.[1] Для C и C ++ существует множество инструментов, которые выполняют преобразование кода во время компиляции для проверки безопасности памяти во время выполнения, например CheckPointer.[14] и AddressSanitizer что предполагает средний коэффициент замедления 2.[15]

Другой подход использует статический анализ программы и автоматическое доказательство теорем чтобы убедиться, что программа свободна от ошибок памяти. Например, Язык программирования Rust реализует средство проверки заимствований для обеспечения безопасности памяти.[16] Такие инструменты как Покровительство предлагают статический анализ памяти для C.[17] C ++ умные указатели являются ограниченной формой этого подхода.

Типы ошибок памяти

Может возникнуть много разных типов ошибок памяти:[18][19]

  • Ошибки доступа: недопустимое чтение / запись указателя
  • Неинициализированные переменные - используется переменная, которой не присвоено значение. Он может содержать нежелательное или, в некоторых языках, неверное значение.
    • Нулевой указатель разыменование - разыменование недопустимого указателя или указателя на память, которая не была выделена
    • Дикие указатели возникают, когда указатель используется до инициализации некоторого известного состояния. Они демонстрируют такое же неустойчивое поведение, что и висячие указатели, хотя с меньшей вероятностью останутся незамеченными.
  • Утечка памяти - когда использование памяти не отслеживается или отслеживается неправильно
    • Истощение стека - возникает, когда программе не хватает места в стеке, обычно из-за слишком большой рекурсия. А защитная страница обычно останавливает программу, предотвращая повреждение памяти, но работает с большими кадры стека может обойти страницу.
    • Исчерпание кучи - программа пытается выделить больше памяти, чем доступно. В некоторых языках это условие необходимо проверять вручную после каждого распределения.
    • Двойной бесплатно - неоднократные звонки на свободный может досрочно освободить новый объект по тому же адресу. Если точный адрес не использовался повторно, может произойти другое повреждение, особенно в распределителях, которые используют бесплатные списки.
    • Недействительно бесплатно - передача неверного адреса в свободный может испортить куча.
    • Несоответствие бесплатно - когда используются несколько распределителей, попытка освободить память с помощью функции освобождения другого распределителя[20]
    • Нежелательный сглаживание - когда одна и та же область памяти выделяется и изменяется дважды для несвязанных целей.

Рекомендации

  1. ^ а б c Дурджати, Динакар; Ковшик, Сумант; Адве, Викрам; Латтнер, Крис (1 января 2003 г.). «Безопасность памяти без проверок времени выполнения или сборки мусора» (PDF). Труды конференции ACM SIGPLAN 2003 года по языку, компилятору и инструментам для встроенных систем. ACM: 69–80. Дои:10.1145/780732.780743. ISBN  1581136471. Получено 13 марта 2017.
  2. ^ Кениг, Эндрю. «Как C затрудняет проверку границ массива». Доктора Добба. Получено 13 марта 2017.
  3. ^ Акритидис, Периклис (июнь 2011 г.). «Практическая безопасность памяти для C» (PDF). Технический отчет - Кембриджский университет. Компьютерная лаборатория. Кембриджский университет, компьютерная лаборатория. ISSN  1476-2986. UCAM-CL-TR-798. Получено 13 марта 2017.
  4. ^ Андерсон, Джеймс П. «Исследование планирования компьютерной безопасности» (PDF). 2. Центр электронных систем. ESD-TR-73-51. Цитировать журнал требует | журнал = (помощь)
  5. ^ а б ван дер Вин, Виктор; дутт-Шарма, Нитиш; Кавалларо, Лоренцо; Бос, Герберт (2012). «Ошибки памяти: прошлое, настоящее и будущее» (PDF). Конспект лекций по информатике. 7462 (RAID 2012): 86–106. Дои:10.1007/978-3-642-33338-5_5. ISBN  978-3-642-33337-8. Получено 13 марта 2017.
  6. ^ Войтчук, Рафаль. «Победа над неисполняемым патчем стека Solar Designer». insecure.org. Получено 13 марта 2017.
  7. ^ Бергер, Эмери Д .; Цорн, Бенджамин Г. (1 января 2006 г.). "DieHard: вероятностная безопасность памяти для небезопасных языков" (PDF). Труды 27-й конференции ACM SIGPLAN по проектированию и реализации языков программирования. ACM: 158–168. Дои:10.1145/1133981.1134000. Получено 14 марта 2017.
  8. ^ Новарк, Джин; Бергер, Эмери Д. (1 января 2010 г.). «DieHarder: защита кучи» (PDF). Материалы 17-й конференции ACM по компьютерной и коммуникационной безопасности. ACM: 573–584. Дои:10.1145/1866307.1866371. Получено 14 марта 2017.
  9. ^ «Отладка памяти в Allinea DDT». Архивировано из оригинал на 03.02.2015.
  10. ^ Джилленхол, Джон. «Использование инструмента Valgrind Memcheck для поиска ошибок и утечек памяти». computing.llnl.gov. Архивировано из оригинал 7 ноября 2018 г.. Получено 13 марта 2017.
  11. ^ «Memcheck: детектор ошибок памяти». Руководство пользователя Valgrind. valgrind.org. Получено 13 марта 2017.
  12. ^ Крейнин, Йоси. «Почему сложно настраиваемые распределители / пулы». Правильная фиксация. Получено 13 марта 2017.
  13. ^ «Использование сборщика мусора в качестве детектора утечек». www.hboehm.info. Получено 14 марта 2017.
  14. ^ «Семантические конструкции: CheckPointer по сравнению с другими инструментами проверки безопасности». www.semanticdesigns.com. Semantic Designs, Inc.
  15. ^ "AddressSanitizerPerformanceNumbers".
  16. ^ "Рекомендации". Рустономикон. Rust.org. Получено 13 марта 2017.
  17. ^ Bessey, Al; Энглер, Доусон; Блок, Кен; Шельф, Бен; Чоу, Энди; Фултон, Брайан; Халлем, Сет; Анри-Гро, Шарль; Камский, Ася; Макпик, Скотт (1 февраля 2010 г.). «Через несколько миллиардов строк кода». Коммуникации ACM. 53 (2): 66–75. Дои:10.1145/1646353.1646374. Получено 14 марта 2017.
  18. ^ Gv, Naveen. «Как избежать, найти (и исправить) ошибки памяти в коде C / C ++». Cprogramming.com. Получено 13 марта 2017.
  19. ^ «CWE-633: Слабости, влияющие на память». Подсчет слабых сторон сообщества. МИТРА. Получено 13 марта 2017.
  20. ^ «CWE-762: Несоответствующие процедуры управления памятью». Подсчет слабых сторон сообщества. МИТРА. Получено 13 марта 2017.