Fix mprotect and mremap potential failure
This commit is contained in:
		
							parent
							
								
									9e9c7c1644
								
							
						
					
					
						commit
						0bf4a5a7f7
					
				@ -390,14 +390,15 @@ impl ProcessVM {
 | 
				
			|||||||
        // Collect merged vmas which will be the output of this function
 | 
					        // Collect merged vmas which will be the output of this function
 | 
				
			||||||
        let mut merged_vmas = Vec::new();
 | 
					        let mut merged_vmas = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Insert the merged chunks or unchanged chunks back to mem_chunk list
 | 
					        // Insert unchanged chunks back to mem_chunks list and collect merged vmas for output
 | 
				
			||||||
        for chunk in single_vma_chunks.into_iter().filter_map(|chunk| {
 | 
					        for chunk in single_vma_chunks.into_iter().filter_map(|chunk| {
 | 
				
			||||||
            if !chunk.is_single_dummy_vma() {
 | 
					            if !chunk.is_single_dummy_vma() {
 | 
				
			||||||
                if chunk.is_single_vma_with_conflict_size() {
 | 
					                if chunk.is_single_vma_with_conflict_size() {
 | 
				
			||||||
                    let new_vma = chunk.get_vma_for_single_vma_chunk();
 | 
					                    let new_vma = chunk.get_vma_for_single_vma_chunk();
 | 
				
			||||||
                    merged_vmas.push(new_vma.clone());
 | 
					                    merged_vmas.push(new_vma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Some(Arc::new(Chunk::new_chunk_with_vma(new_vma)))
 | 
					                    // Don't insert the merged chunks to mem_chunk list here. It should be updated later.
 | 
				
			||||||
 | 
					                    None
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Some(chunk)
 | 
					                    Some(chunk)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -58,8 +58,6 @@ impl VMManager {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Allocate single VMA chunk for new process whose process VM is not ready yet
 | 
					    // Allocate single VMA chunk for new process whose process VM is not ready yet
 | 
				
			||||||
    pub fn alloc(&self, options: &VMMapOptions) -> Result<(VMRange, ChunkRef)> {
 | 
					    pub fn alloc(&self, options: &VMMapOptions) -> Result<(VMRange, ChunkRef)> {
 | 
				
			||||||
        let addr = *options.addr();
 | 
					 | 
				
			||||||
        let size = *options.size();
 | 
					 | 
				
			||||||
        if let Ok(new_chunk) = self.internal().mmap_chunk(options) {
 | 
					        if let Ok(new_chunk) = self.internal().mmap_chunk(options) {
 | 
				
			||||||
            return Ok((new_chunk.range().clone(), new_chunk));
 | 
					            return Ok((new_chunk.range().clone(), new_chunk));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -428,11 +426,11 @@ impl VMManager {
 | 
				
			|||||||
            // Must lock the internal manager first here in case the chunk's range and vma are conflict when other threads are operating the VM
 | 
					            // Must lock the internal manager first here in case the chunk's range and vma are conflict when other threads are operating the VM
 | 
				
			||||||
            let mut internal_manager = self.internal.lock().unwrap();
 | 
					            let mut internal_manager = self.internal.lock().unwrap();
 | 
				
			||||||
            let mut merged_vmas = current.vm().merge_all_single_vma_chunks()?;
 | 
					            let mut merged_vmas = current.vm().merge_all_single_vma_chunks()?;
 | 
				
			||||||
 | 
					            internal_manager.clean_single_vma_chunks();
 | 
				
			||||||
            while merged_vmas.len() != 0 {
 | 
					            while merged_vmas.len() != 0 {
 | 
				
			||||||
                let merged_vma = merged_vmas.pop().unwrap();
 | 
					                let merged_vma = merged_vmas.pop().unwrap();
 | 
				
			||||||
                internal_manager.add_new_chunk(¤t, merged_vma);
 | 
					                internal_manager.add_new_chunk(¤t, merged_vma);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            internal_manager.clean_single_vma_chunks();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Deternmine the chunk of the old range
 | 
					        // Deternmine the chunk of the old range
 | 
				
			||||||
@ -774,12 +772,14 @@ impl InternalVMManager {
 | 
				
			|||||||
        self.chunks.insert(new_chunk);
 | 
					        self.chunks.insert(new_chunk);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // protect_range should a sub-range of the chunk range
 | 
				
			||||||
    pub fn mprotect_single_vma_chunk(
 | 
					    pub fn mprotect_single_vma_chunk(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        chunk: &ChunkRef,
 | 
					        chunk: &ChunkRef,
 | 
				
			||||||
        protect_range: VMRange,
 | 
					        protect_range: VMRange,
 | 
				
			||||||
        new_perms: VMPerms,
 | 
					        new_perms: VMPerms,
 | 
				
			||||||
    ) -> Result<()> {
 | 
					    ) -> Result<()> {
 | 
				
			||||||
 | 
					        debug_assert!(chunk.range().is_superset_of(&protect_range));
 | 
				
			||||||
        let vma = match chunk.internal() {
 | 
					        let vma = match chunk.internal() {
 | 
				
			||||||
            ChunkType::MultiVMA(_) => {
 | 
					            ChunkType::MultiVMA(_) => {
 | 
				
			||||||
                unreachable!();
 | 
					                unreachable!();
 | 
				
			||||||
@ -838,7 +838,8 @@ impl InternalVMManager {
 | 
				
			|||||||
                        )
 | 
					                        )
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let updated_vmas = vec![containing_vma.clone(), new_vma, remaining_old_vma];
 | 
					                    // Put containing_vma at last to be updated first.
 | 
				
			||||||
 | 
					                    let updated_vmas = vec![new_vma, remaining_old_vma, containing_vma.clone()];
 | 
				
			||||||
                    updated_vmas
 | 
					                    updated_vmas
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
@ -858,28 +859,33 @@ impl InternalVMManager {
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    VMPerms::apply_perms(&new_vma, new_vma.perms());
 | 
					                    VMPerms::apply_perms(&new_vma, new_vma.perms());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let updated_vmas = vec![containing_vma.clone(), new_vma];
 | 
					                    // Put containing_vma at last to be updated first.
 | 
				
			||||||
 | 
					                    let updated_vmas = vec![new_vma, containing_vma.clone()];
 | 
				
			||||||
                    updated_vmas
 | 
					                    updated_vmas
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let current = current!();
 | 
					        let current = current!();
 | 
				
			||||||
        while updated_vmas.len() > 1 {
 | 
					        // First update current vma chunk
 | 
				
			||||||
            let vma = updated_vmas.pop().unwrap();
 | 
					        if updated_vmas.len() > 1 {
 | 
				
			||||||
            self.add_new_chunk(¤t, vma);
 | 
					            let update_vma = updated_vmas.pop().unwrap();
 | 
				
			||||||
 | 
					            self.update_single_vma_chunk(¤t, &chunk, update_vma);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        debug_assert!(updated_vmas.len() == 1);
 | 
					        // Then add new chunks if any
 | 
				
			||||||
        let vma = updated_vmas.pop().unwrap();
 | 
					        updated_vmas.into_iter().for_each(|vma| {
 | 
				
			||||||
        self.update_single_vma_chunk(¤t, &chunk, vma);
 | 
					            self.add_new_chunk(¤t, vma);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Must make sure that all the chunks are valid before adding new chunks
 | 
				
			||||||
    fn add_new_chunk(&mut self, current_thread: &ThreadRef, new_vma: VMArea) {
 | 
					    fn add_new_chunk(&mut self, current_thread: &ThreadRef, new_vma: VMArea) {
 | 
				
			||||||
        let new_vma_chunk = Arc::new(Chunk::new_chunk_with_vma(new_vma));
 | 
					        let new_vma_chunk = Arc::new(Chunk::new_chunk_with_vma(new_vma));
 | 
				
			||||||
        self.chunks.insert(new_vma_chunk.clone());
 | 
					        let success = self.chunks.insert(new_vma_chunk.clone());
 | 
				
			||||||
 | 
					        debug_assert!(success);
 | 
				
			||||||
        current_thread.vm().add_mem_chunk(new_vma_chunk);
 | 
					        current_thread.vm().add_mem_chunk(new_vma_chunk);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user