Skip to content

Commit 97e27f9

Browse files
fix(iov): 更新注释以更清晰地描述可访问内存的检查逻辑
fix(user_access): 增强用户空间访问长度检查,确保正确处理文件后备长度
1 parent 61f60d3 commit 97e27f9

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

kernel/src/filesystem/vfs/iov.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl IoVecs {
8989
let mut buf = Vec::with_capacity(self.total_len());
9090

9191
for iov in self.0.iter() {
92-
// 检查从 iov_base 开始有多少连续可访问的空间
92+
// 检查从 iov_base 开始有多少 bytes 在 vma 内部且实际可以访问
9393
let accessible =
9494
user_accessible_len(VirtAddr::new(iov.iov_base as usize), iov.iov_len, false);
9595

kernel/src/syscall/user_access.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -954,11 +954,31 @@ pub fn user_accessible_len(addr: VirtAddr, size: usize, check_write: bool) -> us
954954
break;
955955
};
956956

957-
let (region_end, vm_flags) = {
957+
// 获取地址所在内存页的起始地址 和结束地址,以及访问权限标志 和文件后备长度
958+
let (region_start, region_end, vm_flags, file_backed_len) = {
958959
let guard = vma.lock_irqsave();
960+
let region_start = guard.region().start().data();
959961
let region_end = guard.region().end().data();
960962
let vm_flags = *guard.vm_flags();
961-
(region_end, vm_flags)
963+
let vma_size = region_end.saturating_sub(region_start);
964+
965+
let file_backed_len = guard.vm_file().and_then(|file| {
966+
let file_offset_pages = guard.file_page_offset().unwrap_or(0);
967+
let file_offset_bytes = file_offset_pages.saturating_mul(MMArch::PAGE_SIZE);
968+
let file_size = match file.metadata() {
969+
Ok(md) if md.size > 0 => {
970+
let capped = core::cmp::min(md.size as u128, usize::MAX as u128);
971+
capped as usize
972+
}
973+
Ok(_) => 0,
974+
Err(_) => return None,
975+
};
976+
977+
let backed = file_size.saturating_sub(file_offset_bytes);
978+
Some(core::cmp::min(backed, vma_size))
979+
});
980+
981+
(region_start, region_end, vm_flags, file_backed_len)
962982
};
963983

964984
// 根据 vm_flags 判断是否具备访问权限
@@ -973,7 +993,14 @@ pub fn user_accessible_len(addr: VirtAddr, size: usize, check_write: bool) -> us
973993
}
974994

975995
let current_addr = current.data();
976-
let available = region_end.saturating_sub(current_addr);
996+
let mut available = region_end.saturating_sub(current_addr);
997+
998+
if let Some(backed_len) = file_backed_len {
999+
let offset_in_vma = current_addr.saturating_sub(region_start);
1000+
let backed_available = backed_len.saturating_sub(offset_in_vma);
1001+
// Clamp to the range actually backed by the file to avoid walking into holes.
1002+
available = min(available, backed_available);
1003+
}
9771004
if available == 0 {
9781005
break;
9791006
}

0 commit comments

Comments
 (0)