From 0c18a13cc056d4d54ca7261289615b2d03769a76 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 16 May 2023 01:21:28 +0200 Subject: [PATCH] rp/multicore: fix undefined behavior in multicore spawn. It is UB to pass `entry` to core1 as `&mut`, because core0 keeps an aliasing pointer to that memory region, and actually writes to it (when `spawn_core1` returns, the stack frame gets deallocated and the memory gets reused). This violates noalias requirements. Added the fence just in case, een though it works without. --- embassy-rp/src/multicore.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index c84fea5c..9a445c26 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -122,11 +122,16 @@ where extern "C" fn core1_startup bad::Never>( _: u64, _: u64, - entry: &mut ManuallyDrop, + entry: *mut ManuallyDrop, stack_bottom: *mut usize, ) -> ! { core1_setup(stack_bottom); - let entry = unsafe { ManuallyDrop::take(entry) }; + + let entry = unsafe { ManuallyDrop::take(&mut *entry) }; + + // make sure the preceding read doesn't get reordered past the following fifo write + compiler_fence(Ordering::SeqCst); + // Signal that it's safe for core 0 to get rid of the original value now. fifo_write(1); @@ -164,7 +169,7 @@ where // Push `entry`. stack_ptr = stack_ptr.sub(1); - stack_ptr.cast::<&mut ManuallyDrop>().write(&mut entry); + stack_ptr.cast::<*mut ManuallyDrop>().write(&mut entry); } // Make sure the compiler does not reorder the stack writes after to after the