-
-
Notifications
You must be signed in to change notification settings - Fork 168
feat(vfs):增加sys_chroot #1379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat(vfs):增加sys_chroot #1379
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,91 @@ | ||||||||||||
| //! System call handler for changing the root directory (chroot). | ||||||||||||
|
|
||||||||||||
| use system_error::SystemError; | ||||||||||||
|
|
||||||||||||
| use alloc::{string::String, vec::Vec}; | ||||||||||||
|
|
||||||||||||
| use crate::arch::interrupt::TrapFrame; | ||||||||||||
| use crate::arch::syscall::nr::SYS_CHROOT; | ||||||||||||
| use crate::filesystem::vfs::{FileType, MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES}; | ||||||||||||
| use crate::process::cred::CAPFlags; | ||||||||||||
| use crate::process::ProcessManager; | ||||||||||||
| use crate::syscall::table::FormattedSyscallParam; | ||||||||||||
| use crate::syscall::table::Syscall; | ||||||||||||
| use crate::syscall::user_access::check_and_clone_cstr; | ||||||||||||
|
|
||||||||||||
| /// System call handler for the `chroot` syscall | ||||||||||||
| /// | ||||||||||||
| /// Changes the root directory of the calling process. | ||||||||||||
| pub struct SysChrootHandle; | ||||||||||||
|
|
||||||||||||
| impl Syscall for SysChrootHandle { | ||||||||||||
| /// Returns the number of arguments expected by the `chroot` syscall | ||||||||||||
| fn num_args(&self) -> usize { | ||||||||||||
| 1 | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /// 切换根目录(chroot) | ||||||||||||
| /// | ||||||||||||
| /// 权限要求:CAP_SYS_CHROOT | ||||||||||||
| /// | ||||||||||||
| /// 可能错误: | ||||||||||||
| /// - EFAULT: 用户指针无效 | ||||||||||||
| /// - EINVAL: 路径编码非法 | ||||||||||||
| /// - ENOENT: 目标不存在 | ||||||||||||
| /// - ENOTDIR: 目标不是目录 | ||||||||||||
| /// - EPERM: 缺少 CAP_SYS_CHROOT 权限 | ||||||||||||
| fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> { | ||||||||||||
| let path_ptr = Self::path(args); | ||||||||||||
|
|
||||||||||||
| if path_ptr.is_null() { | ||||||||||||
| return Err(SystemError::EFAULT); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // 权限检查:需要 CAP_SYS_CHROOT | ||||||||||||
| let pcb = ProcessManager::current_pcb(); | ||||||||||||
| if !pcb.cred().has_capability(CAPFlags::CAP_SYS_CHROOT) { | ||||||||||||
| return Err(SystemError::EPERM); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| let path = check_and_clone_cstr(path_ptr, Some(MAX_PATHLEN))? | ||||||||||||
| .into_string() | ||||||||||||
| .map_err(|_| SystemError::EINVAL)?; | ||||||||||||
|
|
||||||||||||
| // 查找并跟随符号链接 | ||||||||||||
| let root_inode = pcb.fs_struct().root(); | ||||||||||||
| let inode = match root_inode.lookup_follow_symlink(&path, VFS_MAX_FOLLOW_SYMLINK_TIMES) | ||||||||||||
| { | ||||||||||||
| Err(_) => return Err(SystemError::ENOENT), | ||||||||||||
| Ok(i) => i, | ||||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| // 必须是目录 | ||||||||||||
| let metadata = inode.metadata()?; | ||||||||||||
| if metadata.file_type != FileType::Dir { | ||||||||||||
| return Err(SystemError::ENOTDIR); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // 更新进程的 fs 视图:设置新的 root。 | ||||||||||||
| // 同时将工作目录移动到新根,保证位于 chroot 内部。 | ||||||||||||
| pcb.fs_struct_mut().set_root(inode); | ||||||||||||
|
||||||||||||
| pcb.fs_struct_mut().set_root(inode); | |
| let fs_struct = pcb.fs_struct_mut(); | |
| fs_struct.set_root(inode.clone()); | |
| fs_struct.set_pwd(inode); | |
| pcb.basic_mut().set_cwd(String::from("/")); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| ChrootTest.PermissionDenied | ||
| ChrootTest.CreatesNewRoot | ||
| ChrootTest.ProcMemSelfMapsNoEscapeProcOpen | ||
| ChrootTest.ProcMountsMountinfoNoEscape |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ mknod_test | |
| unlink_test | ||
| lseek_test | ||
| sync_test | ||
| chroot_test | ||
| #stat_test | ||
| #chmod_test | ||
| #chown_test | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error from
lookup_follow_symlinkis being discarded and always converted toENOENT. This could hide other important errors such asEACCES(permission denied),ELOOP(too many symbolic links), or other filesystem errors. While this pattern is consistent with other syscalls in the codebase (likesys_chdir), it makes debugging more difficult and could confuse users who encounter permission issues but receive "file not found" errors instead.Consider propagating the actual error or at least handling common cases explicitly: