@@ -305,6 +305,34 @@ where
305305 }
306306}
307307
308+ // Split a memory region ptr..ptr + len into three parts:
309+ // +--------+
310+ // | small0 | Chunk smaller than 8 bytes
311+ // +--------+
312+ // | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
313+ // +--------+
314+ // | small1 | Chunk smaller than 8 bytes
315+ // +--------+
316+ fn region_as_aligned_chunks ( ptr : * const u8 , len : usize ) -> ( u8 , usize , u8 ) {
317+ let small0_size = ( 8 - ptr as usize % 8 ) as u8 ;
318+ let small1_size = ( ( len - small0_size as usize ) % 8 ) as u8 ;
319+ let big_size = len - small0_size as usize - small1_size as usize ;
320+
321+ ( small0_size, big_size, small1_size)
322+ }
323+
324+ unsafe fn copy_quadwords ( src : * const u8 , dst : * mut u8 , len : usize ) {
325+ unsafe {
326+ asm ! (
327+ "rep movsq (%rsi), (%rdi)" ,
328+ inout( "rcx" ) len / 8 => _,
329+ inout( "rdi" ) dst => _,
330+ inout( "rsi" ) src => _,
331+ options( att_syntax, nostack, preserves_flags)
332+ ) ;
333+ }
334+ }
335+
308336/// Copies `len` bytes of data from enclave pointer `src` to userspace `dst`
309337///
310338/// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either:
@@ -343,17 +371,6 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
343371 }
344372 }
345373
346- unsafe fn copy_aligned_quadwords_to_userspace ( src : * const u8 , dst : * mut u8 , len : usize ) {
347- unsafe {
348- asm ! (
349- "rep movsq (%rsi), (%rdi)" ,
350- inout( "rcx" ) len / 8 => _,
351- inout( "rdi" ) dst => _,
352- inout( "rsi" ) src => _,
353- options( att_syntax, nostack, preserves_flags)
354- ) ;
355- }
356- }
357374 assert ! ( !src. is_null( ) ) ;
358375 assert ! ( !dst. is_null( ) ) ;
359376 assert ! ( is_enclave_range( src, len) ) ;
@@ -370,7 +387,7 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
370387 } else if len % 8 == 0 && dst as usize % 8 == 0 {
371388 // Copying 8-byte aligned quadwords: copy quad word per quad word
372389 unsafe {
373- copy_aligned_quadwords_to_userspace ( src, dst, len) ;
390+ copy_quadwords ( src, dst, len) ;
374391 }
375392 } else {
376393 // Split copies into three parts:
@@ -381,20 +398,16 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
381398 // +--------+
382399 // | small1 | Chunk smaller than 8 bytes
383400 // +--------+
401+ let ( small0_size, big_size, small1_size) = region_as_aligned_chunks ( dst, len) ;
384402
385403 unsafe {
386404 // Copy small0
387- let small0_size = ( 8 - dst as usize % 8 ) as u8 ;
388- let small0_src = src;
389- let small0_dst = dst;
390- copy_bytewise_to_userspace ( small0_src as _ , small0_dst, small0_size as _ ) ;
405+ copy_bytewise_to_userspace ( src, dst, small0_size as _ ) ;
391406
392407 // Copy big
393- let small1_size = ( ( len - small0_size as usize ) % 8 ) as u8 ;
394- let big_size = len - small0_size as usize - small1_size as usize ;
395408 let big_src = src. offset ( small0_size as _ ) ;
396409 let big_dst = dst. offset ( small0_size as _ ) ;
397- copy_aligned_quadwords_to_userspace ( big_src as _ , big_dst, big_size) ;
410+ copy_quadwords ( big_src as _ , big_dst, big_size) ;
398411
399412 // Copy small1
400413 let small1_src = src. offset ( big_size as isize + small0_size as isize ) ;
0 commit comments