Я обнаружил, что mem::drop
не нужно бегать рядом с тем, где его зовут, что, вероятно, приводит к Mutex
или RwLock
охранникам, которые проводятся во время дорогостоящих вычислений. Как я могу управлять при вызове drop
?Есть ли какой-либо безопасный способ гарантировать, что произвольное падение произойдет до дорогостоящих вычислений?
В качестве простого примера я сделал следующий тест для обнуления падения работы криптографического материала, используя unsafe { ::std::intrinsics::drop_in_place(&mut s); }
, а не просто ::std::mem::drop(s)
.
#[derive(Debug, Default)]
pub struct Secret<T>(pub T);
impl<T> Drop for Secret<T> {
fn drop(&mut self) {
unsafe { ::std::intrinsics::volatile_set_memory::<Secret<T>>(self, 0, 1); }
}
}
#[derive(Debug, Default)]
pub struct AnotherSecret(pub [u8; 32]);
impl Drop for AnotherSecret {
fn drop(&mut self) {
unsafe { ::std::ptr::write_volatile::<$t>(self, AnotherSecret([0u8; 32])); }
assert_eq!(self.0,[0u8; 32]);
}
}
#[cfg(test)]
mod tests {
macro_rules! zeroing_drop_test {
($n:path) => {
let p : *const $n;
{
let mut s = $n([3u8; 32]); p = &s;
unsafe { ::std::intrinsics::drop_in_place(&mut s); }
}
unsafe { assert_eq!((*p).0,[0u8; 32]); }
}
}
#[test]
fn zeroing_drops() {
zeroing_drop_test!(super::Secret<[u8; 32]>);
zeroing_drop_test!(super::AnotherSecret);
}
}
Этот тест завершается неудачей, если я использую ::std::mem::drop(s)
или даже
#[inline(never)]
pub fn drop_now<T>(_x: T) { }
Это, очевидно, прекрасно использовать drop_in_place
для теста, что буфер получает нулевую отметку, но я бы беспокоиться, что вызов drop_in_place
на Mutex
или RwLock
гвардия может привести к использованию после бесплатного.
Эти два охранника могли возможно обращаться с этим подходом:
#[inline(never)]
pub fn drop_now<T>(t: mut T) {
unsafe { ::std::intrinsics::drop_in_place(&mut t); }
unsafe { ::std::intrinsics::volatile_set_memory::<Secret<T>>(&t, 0, 1); }
}
Я понял это как проблему с компилятором ржавчины https://github.com/rust-lang/rfcs/issues/1850 после определения того, что конвейерная обработка ЦП и т. Д. Не были виновниками. –
Ответ: никогда не кладите секретный материал в стек, потому что что-то в стеке копируется. –
возможно добавить [забор] (https://doc.rust-lang.org/std/sync/atomic/fn.fence.html). AIUI, который должен предотвратить переупорядочение. – the8472