Skip to content

Conversation

@newpavlov
Copy link
Member

@newpavlov newpavlov commented Dec 20, 2025

The function was added in #1252.

TODO: update changelog, add test

@newpavlov
Copy link
Member Author

newpavlov commented Dec 20, 2025

Marking this function public allows to implement zeroization more efficiently. For example: https://rust.godbolt.org/z/neEn8s1ze

Additionally, it allows to implement erasure for (plain) external types which haven't implemented zeroization support for some reason:

struct Foo {
    a: ExternalType,
    b: u32,
}

impl Default for Foo {
    fn drop(&mut self) {
        self.a = Default::default();
        self.b = 0;
        zeroize::optimization_barrier(self);
    }
}

It could be a bit fragile (e.g. if type uses MaybeUninit internally), but should work fine in most cases.

@newpavlov newpavlov requested a review from tarcieri December 20, 2025 01:43
@tarcieri
Copy link
Member

Okay, interesting, if we leave the volatile writes as-is, but make optimization_barrier public, we can pitch that as an alternative strategy for people who are more interested in performance than guarantees without losing the guarantees we do have today.

@newpavlov
Copy link
Member Author

newpavlov commented Dec 20, 2025

Unless there is a practical demonstration of optimization_barrier not working as we expect, I personally prefer to use simple writes + optimization_barrier instead of volatile writes. It results in a simpler and easier to understand code with less unsafe and results in a more efficient codegen.

As I wrote previously, I think that we misuse volatile writes in zeroize, since they are explicitly documented as intended for MMIO. Relying on those obviously does not cause UB or correctness issues, but it's still arguably a wrong tool for the job. IMO it's similar to how it's wrong to use volatile ops as a replacement for (relaxed) atomics, though it "works" in practice.

But we can leave this discussion for a separate issue or PR.

@tarcieri
Copy link
Member

The documentation has been edited in the past to make zeroize's usage seem less off-label. I think they would probably accept a change that says something to the effect of "Writing to I/O memory is the main intended use case for volatile operations".

Without write_volatile or asm! we don't actually have guarantees, and guarantees are what this crate advertises, which is something I would not like to see regress.

Making this function public seems like a reasonable enough middle ground between actually removing any of the primitives that provide actual guarantees.

@newpavlov
Copy link
Member Author

newpavlov commented Dec 20, 2025

Ideally, we would just use core::hint::black_box instead of inventing our own optimization_barrier, but IIRC from previous discussions with Ralf the main difficulty here is how to specify the guarantees exactly. Frankly, I find it annoying that we have guarantees for volatile writes (developed because they are critical for embedded programming) and nothing similar for cryptographic code be it a const time code or erasure of secrets...

Maybe we could propose addition of a block_box variant with semantics of "whatever the empty asm! blocks does"? It would allow to reduce number of target arches dependent on the fallback since its implementation would be able to use unstable asm!.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants