From b71a265aff1a4ef486cc654c488dc9c89a7e00fa Mon Sep 17 00:00:00 2001 From: LoGin Date: Tue, 23 Dec 2025 18:21:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(filesystem):=20=E5=AE=8C=E5=96=84=20rename?= =?UTF-8?q?=20=E7=B3=BB=E7=BB=9F=E8=B0=83=E7=94=A8=E5=AE=9E=E7=8E=B0=20(#1?= =?UTF-8?q?540)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 kernfs 中处理重命名到自身的特殊情况 - 在 renameat2 系统调用中添加权限检查 - 从测试黑名单中移除已实现的测试项 - 在测试白名单中添加 munmap_test Signed-off-by: longjin --- kernel/src/filesystem/kernfs/mod.rs | 25 ++++++++++++++++--- .../filesystem/vfs/syscall/rename_utils.rs | 18 +++++++++++++ .../syscall/gvisor/blocklists/rename_test | 9 ------- user/apps/tests/syscall/gvisor/whitelist.txt | 1 + 4 files changed, 40 insertions(+), 13 deletions(-) delete mode 100644 user/apps/tests/syscall/gvisor/blocklists/rename_test diff --git a/kernel/src/filesystem/kernfs/mod.rs b/kernel/src/filesystem/kernfs/mod.rs index 579311234..f6579c9ba 100644 --- a/kernel/src/filesystem/kernfs/mod.rs +++ b/kernel/src/filesystem/kernfs/mod.rs @@ -226,12 +226,29 @@ impl IndexNode for KernFSInode { fn move_to( &self, - _old_name: &str, - _target: &Arc, - _new_name: &str, + old_name: &str, + target: &Arc, + new_name: &str, _flags: RenameFlags, ) -> Result<(), SystemError> { - // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。 + // 处理重命名到自身的特殊情况 + // 如果源目录和目标目录是同一个 inode,且文件名相同,则直接返回成功 + // 这符合 Linux 的 rename 语义:重命名到自身是一个空操作 + if let Some(target_kernfs) = target.clone().downcast_arc::() { + // 使用 Arc::ptr_eq 比较两个 Arc 是否指向同一个对象 + // 通过 self_ref.upgrade() 获取 Arc + let self_arc = self.self_ref.upgrade().ok_or(SystemError::ENOENT)?; + let target_arc = target_kernfs + .self_ref + .upgrade() + .ok_or(SystemError::ENOENT)?; + + if Arc::ptr_eq(&self_arc, &target_arc) && old_name == new_name { + return Ok(()); + } + } + + // 其他情况返回 ENOSYS(sysfs/kernfs 不支持真正的重命名操作) return Err(SystemError::ENOSYS); } diff --git a/kernel/src/filesystem/vfs/syscall/rename_utils.rs b/kernel/src/filesystem/vfs/syscall/rename_utils.rs index 77efe56ad..a6132084f 100644 --- a/kernel/src/filesystem/vfs/syscall/rename_utils.rs +++ b/kernel/src/filesystem/vfs/syscall/rename_utils.rs @@ -1,3 +1,4 @@ +use crate::filesystem::vfs::permission::PermissionMask; use crate::filesystem::vfs::syscall::RenameFlags; use crate::filesystem::vfs::utils::is_ancestor; use crate::filesystem::vfs::utils::rsplit_path; @@ -83,6 +84,23 @@ pub fn do_renameat2( // 这会把同目录/向上移动的合法情况误判为 ENOTEMPTY。 // 非空目录覆盖应由具体文件系统在 move_to/rename 实现中返回 ENOTEMPTY。 + // 权限检查:根据 Linux 语义,rename 需要对源父目录和目标父目录都拥有写+搜索权限 + let cred = pcb.cred(); + + // 检查源父目录的写+搜索权限(需要删除旧目录项) + let old_parent_metadata = old_parent_inode.metadata()?; + cred.inode_permission( + &old_parent_metadata, + (PermissionMask::MAY_WRITE | PermissionMask::MAY_EXEC).bits(), + )?; + + // 检查目标父目录的写+搜索权限(需要创建新目录项) + let new_parent_metadata = new_parent_inode.metadata()?; + cred.inode_permission( + &new_parent_metadata, + (PermissionMask::MAY_WRITE | PermissionMask::MAY_EXEC).bits(), + )?; + old_parent_inode.move_to(old_filename, &new_parent_inode, new_filename, flags)?; return Ok(0); } diff --git a/user/apps/tests/syscall/gvisor/blocklists/rename_test b/user/apps/tests/syscall/gvisor/blocklists/rename_test deleted file mode 100644 index 65a75e1a2..000000000 --- a/user/apps/tests/syscall/gvisor/blocklists/rename_test +++ /dev/null @@ -1,9 +0,0 @@ -RenameTest.DirectoryOverwritesDirectoryLinkCount -# 权限相关未实现 -RenameTest.FailsWhenOldParentNotWritable -RenameTest.FailsWhenNewParentNotWritable -RenameTest.OverwriteFailsWhenNewParentNotWritable -RenameTest.FileDoesNotExistWhenNewParentNotExecutable -# 相关系统调用未实现 -RenameTest.SysfsFileToSelf -RenameTest.SysfsDirectoryToSelf diff --git a/user/apps/tests/syscall/gvisor/whitelist.txt b/user/apps/tests/syscall/gvisor/whitelist.txt index a5f9a40be..6a1cb1224 100644 --- a/user/apps/tests/syscall/gvisor/whitelist.txt +++ b/user/apps/tests/syscall/gvisor/whitelist.txt @@ -63,6 +63,7 @@ prctl_test # 内存管理测试 mmap_test +munmap_test brk_test mincore_test madvise_test