Skip to content

X509StoreRef::objects violates Rust safety guarantees #2096

Closed
@davidben

Description

@davidben

Haven't had time to put together a full TSan PoC here, but I'll just file the bug because it's fairly self-explanatory. X509StoreRef::objects wraps X509_STORE_get0_objects. As OpenSSL documents:

X509_STORE_get0_objects() retrieves an internal pointer to the store's X509 object cache. The cache contains X509 and X509_CRL objects. The returned pointer must not be freed by the calling application.

https://www.openssl.org/docs/man3.0/man3/X509_STORE_get0_objects.html

As it's an internal cache, this is of course inappropriate for rust-openssl to export in a public API. In particular, other operations in OpenSS update that cache. The directory-based X509_LOOKUP adds things to the cache as it finds them:
https://github.com/openssl/openssl/blob/master/crypto/x509/by_dir.c#L332
https://github.com/openssl/openssl/blob/master/crypto/x509/by_file.c#L127
https://github.com/openssl/openssl/blob/master/crypto/x509/x509_lu.c#L430
https://github.com/openssl/openssl/blob/master/crypto/x509/x509_lu.c#L419

Although OpenSSL internally locks this, it cannot synchronize this with someone poking around with X509_STORE_get0_objects's return value. As a result, rust-openssl's API here is not safe: it takes a shared reference to the X509_STORE, but it races with APIs like X509StoreContextRef::init which also take a shared reference to the X509_STORE but may trigger the above code.

(Really, X509_STORE_get0_objects shouldn't have been part of OpenSSL public API either, but it's a consequence of, before opaquification, legacy code reaching into the library internals. Looks like it was added to appease CPython per openssl/openssl@f0c58c3. Rust, however, has much more stringent threading expectations than CPython, so it should not have been used here.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions