我发现mem::drop不必在调用它的位置附近运行,这很可能导致在昂贵的计算过程中保留了MutexRwLock保护。如何控制何时调用drop

作为一个简单的示例,我通过使用unsafe { ::std::intrinsics::drop_in_place(&mut s); }而不是简单的::std::mem::drop(s)对加密 Material 的零滴工作进行了以下测试。

#[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_placeMutex防护程序上调用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的回答:

在 Debug模式下,对::std::mem::drop(s)的任何调用实际上都会在堆栈上移动s,因此p指向不会被擦除的旧副本。 unsafe { ::std::intrinsics::drop_in_place(&mut s); }起作用是因为它不会移动s

通常,没有办法阻止LLVM在堆栈上移动值,或者在移动它们后将其设置为零,因此您绝不能将密码敏感的数据放在堆栈上。相反,您必须Box任何敏感数据,例如说

#[derive(Debug, Default)]
pub struct AnotherSecret(Box<[u8; 32]>);

impl Drop for AnotherSecret {
    fn drop(&mut self) {
        *self.0 = [0u8; 32];
    }
}
MutexRwLock应该没有问题,因为当它们被drop编码时,它们可以安全地在堆栈上留下残留物。

关于multithreading - 有什么安全的方法可以确保在进行一些昂贵的计算之前发生任意丢弃?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41560442/

10-12 12:53
查看更多