Безопасное освобождение boost :: asio :: const_buffer

Для целей PA: DSS я должен быть уверен, что boost :: asio :: const_buffer (например, в boost :: asio :: async_write) будет обнуляться при выходе из области видимости.

С контейнерами STL я могу заменить распределитель / освобождающий объект следующим образом:

    void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
::operator delete(p);
}

Однако я понятия не имею, как добиться того же с помощью boost :: asio :: const_buffer, по крайней мере, не так, чтобы это позволяло boost :: asio :: async_write потреблять его. Также я не хочу изобретать велосипед (если есть).

1

Решение

Короткий ответ: Буферы Asio не владеют своей памятью, поэтому они не должны нести ответственность за их удаление.

Во-первых, вы должны не использование

std::memset(p, 0, n * sizeof(T));

Используйте функцию как SecureZeroMemory вместо: Как обеспечить, чтобы оптимизация компилятора не создавала угрозы безопасности?

Я понимаю, что вы имели volatile по этой причине, но это не всегда можно почитать так, как вы ожидаете:

Ваш secure_memset функция может быть недостаточной. В соответствии с http://open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf есть оптимизирующие компиляторы, которые обнуляют только первый байт — Даниэль Треббиен, 9 ноября ’12 в 12:50

Фоновое чтение:


На ASIO

Убедитесь, что вы полностью понимаете, что Boost Asio буферы не иметь семантики владения. Они только когда-либо ссылка данные, принадлежащие другому объекту.

Что более важно, чем поставленный вопрос, вы можете проверить, достаточно ли долго хранятся данные буфера. Распространенной ловушкой является передача локального в качестве буфера:

std::string response = "OK\r\n\r\n";
asio::async_write(sock_, asio::buffer(response), ...); // OOOPS!!!

Это ведет к Неопределенное поведение немедленно.

IOW const_buffer это концепция. Существует множество способов построить его поверх (ваших) объектов:

документация

Буферный объект представляет непрерывную область памяти в виде 2-х кортежей, состоящих из указателя и размера в байтах. Кортеж формы {void*, size_t} определяет изменяемую (модифицируемую) область памяти. Аналогично, кортеж в форме {const void*, size_t} определяет постоянную (неизменяемую) область памяти. Эти две формы соответствуют классам mutable_buffer а также const_bufferсоответственно

Итак, давайте предположим, что у вас есть тип буфера

struct SecureBuffer
{
~SecureBuffer() { shred(); }
size_t      size() const { return length_; }
char const* data() const { return data_; }

// ...
private:
void shred(); // uses SecureZeroMemory etc.

std::array<char, 1024> data_ = {0};
size_t length_ = 0u;
};

Затем вы можете просто передать его туда, где вы хотите его использовать:

SecureBuffer secret; // member variable (lifetime exceeds async operation)
// ... set data
boost::asio::async_write(sock_,
boost::asio::buffer(secret.data(), secret.size()),
/*...*/
);
1

Другие решения


По вопросам рекламы [email protected]