Как memset обеспечивает более высокий уровень безопасности, чем bzero илиlicit_bzero? - PullRequest
0 голосов
/ 15 декабря 2018

Справочная страница из bzero гласит, что по различным причинам безопасности она устарела, и вместо нее следует использовать memset.
Они в основном относятся к проблеме, что bzero илиexplicit_bzero не может найти все копии данных (особенно данных, которые достаточно малы, чтобы поместиться в регистр) и, возможно, не полностью удаляет или перезаписывает, как ожидалось.
Но memset принимает только адрес указателя.Как memset сможет найти все копии, чтобы закрыть это отсутствие безопасности?

1 Ответ

0 голосов
/ 15 декабря 2018

Я думаю, вы неправильно прочитали справочную страницу.Предполагая, что вы говорите о man-странице Linux, она утверждает (правильно), что explicit_bzero и memset_explicit и memset_s более безопасны (для определенных целей), чем memset и bzero.Это не требует никакой разницы в безопасности между memset и bzero.Причина, по которой bzero устарела, заключается в том, что это просто тривиальная оболочка вокруг memset, и все реализации C имеют memset, поэтому программисты могут также использовать memset.

Разница между memset / *Варианты 1015 * и explicit_ / _s заключаются в том, что компиляторам запрещено оптимизировать явные варианты.Это делает явные варианты подходящими для очистки конфиденциальных данных.Например, рассмотрим следующий фрагмент программы:

bzero(password, password_length);
free(password);

Просто с bzero или memset многие современные компиляторы видят «о, вы пишете в память, а затем освобождаете ее.Нет возможности прочитать только что написанное bzero, поэтому вызов bzero равносилен бездействию.Ничего не делать быстрее, чем вызывать bzero, поэтому я не буду генерировать код для вызова bzero ».

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

Так что для инженера по безопасности оптимизация memset является неудачной.Специалист по безопасности хочет гарантировать, что после освобождения памяти ее прежнее содержимое не будет вытекать, даже, скажем, из-за переполнения буфера .Следовательно, explicit_bzero: компиляторы получают указание обрабатывать содержимое целевой памяти, когда эта функция возвращается как наблюдаемая, поэтому им не разрешается оптимизировать обратный вызов на том основании, что программа не читает с нее.Семантически, explicit_bzero(buffer, length) эквивалентно

bzero(buffer, length);
for (size_t i = 0; i < length; i++) __observe__(buffer[i]);

, где __observe__ не имеет никакого эффекта, но, тем не менее, зависит от значения его аргумента.Поэтому компилятору не разрешается удалять вызов bzero, потому что тогда __observe__ не будет считывать правильные значения.

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

Другое ограничение явного обнуления состоит в том, что он применяется только на уровне программы, а не на уровне системы.Копии данных могут оставаться в кэш-памяти, в подкачке и т. Д. Цель обнуления памяти в вашей программе - защита от взлома безопасности в вашей программе.Он не защищает от больших системных компромиссов.

Обратите внимание, что написание собственного explicit_bzero невозможно сделать переносимым .Лучшее, что вы можете сделать, - это заставить его работать с конечным набором версий конечного набора компиляторов, без гарантии того, что в следующей версии не будет более интересного оптимизатора, который проследит за вашей попыткой.Вот почему C11 добавил его в качестве стандартной функции с memset_s.

¹ Почти.Технически автономные реализации не обязательно должны иметь memset, но это такая простая и полезная функция, которая есть у большинства, и она обычно предоставляется компилятором, поэтому она доступна даже при сборке без обычной среды выполнения Си.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...