diff options
author | Azul <azul@riseup.net> | 2020-12-09 20:26:52 +0100 |
---|---|---|
committer | Azul <azul@riseup.net> | 2020-12-10 13:57:19 +0100 |
commit | 227db80b9d40526387f1e4a64f90464618fb885b (patch) | |
tree | bcf1ab1ed4d61fffea8d382872262650c5f49d86 /openpgp-ffi | |
parent | 80b59ecf7b33dcd2392eee8b4e2def4101410749 (diff) |
buffered-reader: Require Cookies to be Send and Sync.
- This way the entire `BufferedReader<C>` will be `Send` and `Sync`.
- Modify all other crates accordingly.
- See #615.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r-- | openpgp-ffi/include/sequoia/io.h | 8 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp.h | 18 | ||||
-rw-r--r-- | openpgp-ffi/src/io.rs | 25 | ||||
-rw-r--r-- | openpgp-ffi/src/parse/stream.rs | 49 |
4 files changed, 82 insertions, 18 deletions
diff --git a/openpgp-ffi/include/sequoia/io.h b/openpgp-ffi/include/sequoia/io.h index e574aefb..35c397dc 100644 --- a/openpgp-ffi/include/sequoia/io.h +++ b/openpgp-ffi/include/sequoia/io.h @@ -36,7 +36,13 @@ typedef ssize_t (*pgp_reader_cb_t) (void *cookie, const void *buf, size_t len); /*/ /// Creates an reader from a callback and cookie. /// -/// This reader calls the given callback to write data. +/// This reader calls the given callback to read data. +/// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callback and cookie support that as well. /*/ pgp_reader_t pgp_reader_from_callback (pgp_reader_cb_t, void *); diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h index cb6bc31d..82506efd 100644 --- a/openpgp-ffi/include/sequoia/openpgp.h +++ b/openpgp-ffi/include/sequoia/openpgp.h @@ -1999,6 +1999,12 @@ bool pgp_verification_result_bad_signature (pgp_verification_result_t, /// first parameter to each of them. /// /// Note: all of the parameters are required; none may be NULL. +/// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callbacks and cookie support that as well. /*/ pgp_reader_t pgp_decryptor_new (pgp_error_t *errp, pgp_policy_t policy, @@ -2014,6 +2020,12 @@ pgp_reader_t pgp_decryptor_new (pgp_error_t *errp, /// /// No attempt is made to decrypt any encryption packets. These are /// treated as opaque containers. +/// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callbacks and cookie support that as well. /*/ pgp_reader_t pgp_verifier_new (pgp_error_t *errp, pgp_policy_t policy, @@ -2025,6 +2037,12 @@ pgp_reader_t pgp_verifier_new (pgp_error_t *errp, /*/ /// Verifies a detached OpenPGP signature. +/// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callbacks and cookie support that as well. /*/ pgp_detached_verifier_t pgp_detached_verifier_new (pgp_error_t *errp, pgp_policy_t policy, diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs index 484615cf..3c5668d6 100644 --- a/openpgp-ffi/src/io.rs +++ b/openpgp-ffi/src/io.rs @@ -26,7 +26,7 @@ pub struct Reader(ReaderKind); /// In some cases, we want to call functions on concrete types. To /// avoid nasty hacks, we have specialized variants for that. pub(crate) enum ReaderKind { - Generic(Box<dyn io::Read>), + Generic(Box<dyn io::Read + Send + Sync>), Armored(openpgp::armor::Reader<'static>), } @@ -80,26 +80,39 @@ type ReaderCallbackFn = extern fn(*mut c_void, *const c_void, size_t) -> ssize_t /// Creates an reader from a callback and cookie. /// /// This reader calls the given callback to write data. +/// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callback and cookie support that as well. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_reader_from_callback(cb: ReaderCallbackFn, cookie: *mut c_void) -> *mut Reader { - let r: Box<dyn io::Read> = Box::new(ReaderCallback { - cb, cookie, - }); + let r: Box<dyn io::Read + Send + Sync> = + Box::new(ReaderCallback(Mutex::new(ReaderClosure { + cb, cookie, + }))); ReaderKind::Generic(r).move_into_raw() } /// A generic callback-based reader implementation. -struct ReaderCallback { +struct ReaderCallback(Mutex<ReaderClosure>); + +struct ReaderClosure { cb: ReaderCallbackFn, cookie: *mut c_void, } +unsafe impl Send for ReaderClosure {} + impl Read for ReaderCallback { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + let closure = self.0.get_mut().expect("Mutex not to be poisoned"); let r = - (self.cb)(self.cookie, buf.as_mut_ptr() as *mut c_void, buf.len()); + (closure.cb)(closure.cookie, + buf.as_mut_ptr() as *mut c_void, buf.len()); if r < 0 { use std::io as stdio; Err(stdio::Error::new(stdio::ErrorKind::Other, diff --git a/openpgp-ffi/src/parse/stream.rs b/openpgp-ffi/src/parse/stream.rs index 747452a0..16fb1829 100644 --- a/openpgp-ffi/src/parse/stream.rs +++ b/openpgp-ffi/src/parse/stream.rs @@ -11,6 +11,7 @@ //! [`sequoia-openpgp::parse::stream`]: ../../../../sequoia_openpgp/parse/stream/index.html use std::ptr; +use std::sync::Mutex; use libc::{c_int, c_void, time_t}; use sequoia_openpgp as openpgp; @@ -430,13 +431,16 @@ type CheckCallback = extern fn(*mut HelperCookie, -> Status; // This fetches keys and computes the validity of the verification. -struct VHelper { +struct VHelper(Mutex<VHelperClosure>); +struct VHelperClosure { inspect_cb: Option<InspectCallback>, get_certs_cb: GetPublicKeysCallback, check_signatures_cb: CheckCallback, cookie: *mut HelperCookie, } +unsafe impl Send for VHelperClosure {} + impl VHelper { fn new(inspect_cb: Option<InspectCallback>, get_certs: GetPublicKeysCallback, @@ -444,19 +448,20 @@ impl VHelper { cookie: *mut HelperCookie) -> Self { - VHelper { + VHelper(Mutex::new(VHelperClosure { inspect_cb, get_certs_cb: get_certs, check_signatures_cb: check_signatures, - cookie, - } + cookie: cookie, + })) } } impl VerificationHelper for VHelper { fn inspect(&mut self, pp: &PacketParser) -> openpgp::Result<()> { - if let Some(cb) = self.inspect_cb { - match cb(self.cookie, pp) { + let closure = self.0.get_mut().expect("Mutex not to be poisoned"); + if let Some(cb) = closure.inspect_cb { + match cb(closure.cookie, pp) { Status::Success => Ok(()), // XXX: Convert the status to an error better. status => Err(anyhow::anyhow!( @@ -481,8 +486,9 @@ impl VerificationHelper for VHelper { let mut free : FreeCallback = |_| {}; - let result = (self.get_certs_cb)( - self.cookie, + let closure = self.0.get_mut().expect("Mutex not to be poisoned"); + let result = (closure.get_certs_cb)( + closure.cookie, ids.as_ptr(), ids.len(), &mut cert_refs_raw, &mut cert_refs_raw_len as *mut usize, &mut free); @@ -515,8 +521,9 @@ impl VerificationHelper for VHelper { fn check(&mut self, structure: stream::MessageStructure) -> Result<(), anyhow::Error> { - let result = (self.check_signatures_cb)(self.cookie, - structure.move_into_raw()); + let closure = self.0.get_mut().expect("Mutex not to be poisoned"); + let result = (closure.check_signatures_cb)(closure.cookie, + structure.move_into_raw()); if result != Status::Success { // XXX: We need to convert the status to an error. A // status contains less information, but we should do the @@ -535,6 +542,12 @@ impl VerificationHelper for VHelper { /// No attempt is made to decrypt any encryption packets. These are /// treated as opaque containers. /// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callbacks and cookie support that as well. +/// /// # Examples /// /// ```c @@ -663,6 +676,12 @@ pub struct DetachedVerifier(openpgp::parse::stream::DetachedVerifier<'static, VH /// Verifies a detached OpenPGP signature. /// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callbacks and cookie support that as well. +/// /// # Examples /// /// ```c @@ -871,8 +890,10 @@ impl DecryptionHelper for DHelper { (*closure)(algo.into(), sk.ref_raw()) } + let closure = + self.vhelper.0.get_mut().expect("Mutex not to be poisoned"); let result = (self.decrypt_cb)( - self.vhelper.cookie, + closure.cookie, pkesks.as_ptr(), pkesks.len(), skesks.as_ptr(), skesks.len(), sym_algo.map(|s| u8::from(s)).unwrap_or(0), trampoline::<D>, @@ -904,6 +925,12 @@ impl DecryptionHelper for DHelper { /// /// Note: all of the parameters are required; none may be NULL. /// +/// # Sending objects across thread boundaries +/// +/// If you send a Sequoia object (like a pgp_verifier_t) that reads +/// from an callback across thread boundaries, you must make sure that +/// the callbacks and cookie support that as well. +/// /// # Examples /// /// ```c |