@@ -1318,6 +1318,9 @@ impl<C: 'static + Chip> ProcessStandard<'_, C> {
13181318 // Make room for grant pointers.
13191319 let grant_ptr_size = mem:: size_of :: < GrantPointerEntry > ( ) ;
13201320 let grant_ptrs_num = kernel. get_grant_count_and_finalize ( ) ;
1321+ if grant_ptr_size == 0 || usize:: MAX / grant_ptr_size < grant_ptrs_num {
1322+ return Err ( ( ProcessLoadError :: NotEnoughMemory , remaining_memory) ) ;
1323+ }
13211324 let grant_ptrs_offset = grant_ptrs_num * grant_ptr_size;
13221325
13231326 // Initial size of the kernel-owned part of process memory can be
@@ -1332,7 +1335,12 @@ impl<C: 'static + Chip> ProcessStandard<'_, C> {
13321335 // `sizeof(usize)` bytes.
13331336 let upper_bound = ( u32:: MAX / 4 ) as usize ;
13341337 let usize_size = core:: mem:: size_of :: < usize > ( ) ;
1335- let callbacks_offset = Self :: CALLBACKS_OFFSET ;
1338+ let callbacks_len = Self :: CALLBACK_LEN ;
1339+ let task_size = core:: mem:: size_of :: < Task > ( ) ;
1340+ if task_size == 0 || usize:: MAX / task_size < callbacks_len {
1341+ return Err ( ( ProcessLoadError :: NotEnoughMemory , remaining_memory) ) ;
1342+ }
1343+ let callbacks_offset = task_size * callbacks_len;
13361344 let process_struct_offset = Self :: PROCESS_STRUCT_OFFSET ;
13371345
13381346 if !( process_struct_offset < isize_into_usize ( isize:: MAX )
@@ -1342,7 +1350,9 @@ impl<C: 'static + Chip> ProcessStandard<'_, C> {
13421350 && callbacks_offset < upper_bound
13431351 && 0 < usize_size
13441352 && usize_size <= 8
1345- && grant_ptrs_offset < upper_bound)
1353+ && grant_ptrs_offset < upper_bound
1354+ && callbacks_offset % usize_size == 0
1355+ && grant_ptrs_offset % usize_size == 0 )
13461356 {
13471357 return Err ( ( ProcessLoadError :: NotEnoughMemory , remaining_memory) ) ;
13481358 }
@@ -1582,52 +1592,68 @@ impl<C: 'static + Chip> ProcessStandard<'_, C> {
15821592 // Calling `wrapping_sub` is safe here, as we've factored in an optional
15831593 // padding of at most `sizeof(usize)` bytes in the calculation of
15841594 // `initial_kernel_memory_size` above.
1585- let mut kernel_memory_break = app_memory_alloc. memory_end ( ) ;
1595+ let memory_end = app_memory_alloc. memory_end ( ) ;
1596+ let actual_kernel_break = app_memory_alloc. kernel_break ( ) ;
1597+ let mut kernel_memory_break = memory_end;
15861598
1599+ // aligned to 4 bytes
15871600 kernel_memory_break =
15881601 kernel_memory_break. wrapping_sub ( kernel_memory_break. as_usize ( ) % usize_size) ;
15891602
15901603 // Now that we know we have the space we can setup the grant pointers.
1591- // kernel_memory_break = kernel_memory_break.offset(-(grant_ptrs_offset as isize)); // VTOCK TODO: Something about usize cast to isize here?
1604+ let grant_ptrs_offset = usize_into_isize ( grant_ptrs_offset) ;
1605+ kernel_memory_break = kernel_memory_break. offset ( -grant_ptrs_offset) ;
15921606
15931607 // This is safe, `kernel_memory_break` is aligned to a word-boundary,
15941608 // and `grant_ptrs_offset` is a multiple of the word size.
1595- #[ allow( clippy:: cast_ptr_alignment) ]
15961609 // Set all grant pointers to null.
1597- let grant_pointers = core:: slice:: from_raw_parts_mut (
1598- kernel_memory_break. unsafe_as_ptr ( ) as * mut GrantPointerEntry ,
1610+ let grant_pointers: & mut [ GrantPointerEntry ] = flux_support:: from_raw_parts_mut (
1611+ kernel_memory_break,
1612+ grant_ptr_size,
15991613 grant_ptrs_num,
1614+ usize_size,
16001615 ) ;
16011616 for grant_entry in grant_pointers. iter_mut ( ) {
16021617 grant_entry. driver_num = 0 ;
16031618 grant_entry. grant_ptr = FluxPtr :: null_mut ( ) ;
16041619 }
1620+ // would be nice to have a start addr for grant_pointers but we'll trust its kernel_memory_break
1621+ // assert we aren't overflowing the end of memory
1622+ flux_support:: assert (
1623+ kernel_memory_break. as_usize ( ) + grant_pointers. len ( ) <= memory_end. as_usize ( ) ,
1624+ ) ;
1625+ let grant_entry_checkpoint = kernel_memory_break;
16051626
16061627 // Now that we know we have the space we can setup the memory for the
16071628 // upcalls.
16081629 let callbacks_isize = usize_into_isize ( callbacks_offset) ;
16091630 kernel_memory_break = kernel_memory_break. offset ( -callbacks_isize) ;
16101631
1611- // This is safe today, as MPU constraints ensure that `memory_start`
1612- // will always be aligned on at least a word boundary, and that
1613- // memory_size will be aligned on at least a word boundary, and
1614- // `grant_ptrs_offset` is a multiple of the word size. Thus,
1615- // `kernel_memory_break` must be word aligned. While this is unlikely to
1616- // change, it should be more proactively enforced.
1617- //
1618- // TODO: https://github.com/tock/tock/issues/1739
1619- #[ allow( clippy:: cast_ptr_alignment) ]
16201632 // Set up ring buffer for upcalls to the process.
16211633 let upcall_buf = flux_support:: from_raw_parts_mut (
1622- kernel_memory_break. unsafe_as_ptr ( ) as * mut Task ,
1623- Self :: CALLBACK_LEN ,
1634+ kernel_memory_break,
1635+ task_size,
1636+ callbacks_len,
1637+ usize_size,
16241638 ) ;
1639+ // assert we aren't overflowing the start of the grant entries
1640+ flux_support:: assert (
1641+ kernel_memory_break. as_usize ( ) + upcall_buf. len ( ) <= grant_entry_checkpoint. as_usize ( ) ,
1642+ ) ;
1643+ let upcall_buf_checkpoint = kernel_memory_break;
16251644 let tasks = RingBuffer :: new ( upcall_buf) ;
16261645
16271646 // Last thing in the kernel region of process RAM is the process struct.
16281647 let process_struct_offset = usize_into_isize ( process_struct_offset) ;
16291648 kernel_memory_break = kernel_memory_break. offset ( -process_struct_offset) ;
16301649 let process_struct_memory_location = kernel_memory_break;
1650+ flux_support:: assert (
1651+ process_struct_memory_location. as_usize ( ) + isize_into_usize ( process_struct_offset)
1652+ <= upcall_buf_checkpoint. as_usize ( ) ,
1653+ ) ;
1654+
1655+ // assert we don't allocate past the kernel memory break the allocator set up
1656+ flux_support:: assert ( kernel_memory_break >= actual_kernel_break) ;
16311657
16321658 // Create the Process struct in the app grant region.
16331659 // Note that this requires every field be explicitly initialized
@@ -1683,13 +1709,6 @@ impl<C: 'static + Chip> ProcessStandard<'_, C> {
16831709 } ) ;
16841710
16851711 // Handle any architecture-specific requirements for a new process.
1686- //
1687- // NOTE! We have to ensure that the start of process-accessible memory
1688- // (`app_memory_start`) is word-aligned. Since we currently start
1689- // process-accessible memory at the beginning of the allocated memory
1690- // region, we trust the MPU to give us a word-aligned starting address.
1691- //
1692- // TODO: https://github.com/tock/tock/issues/1739
16931712 match process. stored_state . map ( |stored_state| {
16941713 chip. userspace_kernel_boundary ( ) . initialize_process (
16951714 memory_start,
0 commit comments