diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 6353c4075..7aa51b035 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -524,7 +524,7 @@ impl File { pub fn readable(&self) -> Result<(), SystemError> { let mode = *self.mode.read(); // 暂时认为只要不是write only, 就可读 - if mode == FileMode::O_WRONLY || mode.contains(FileMode::O_PATH) { + if mode.accmode() == FileMode::O_WRONLY.bits || mode.contains(FileMode::O_PATH) { return Err(SystemError::EBADF); } diff --git a/kernel/src/filesystem/vfs/syscall/sys_pread64.rs b/kernel/src/filesystem/vfs/syscall/sys_pread64.rs index 4470fe984..91ef4c319 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_pread64.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_pread64.rs @@ -4,6 +4,7 @@ use system_error::SystemError; use crate::arch::interrupt::TrapFrame; use crate::arch::syscall::nr::SYS_PREAD64; +use crate::filesystem::vfs::FileType; use crate::process::ProcessManager; use crate::syscall::table::FormattedSyscallParam; use crate::syscall::table::Syscall; @@ -35,7 +36,15 @@ impl Syscall for SysPread64Handle { let len = Self::len(args); let offset = Self::offset(args); - let mut user_buffer_writer = UserBufferWriter::new(buf_vaddr, len, frame.is_from_user())?; + // 检查offset + len是否溢出 同时检查offset是否为负数 + + let end_pos = offset.checked_add(len).ok_or(SystemError::EINVAL)?; + if offset > i64::MAX as usize || end_pos > i64::MAX as usize { + return Err(SystemError::EINVAL); + } + + let mut user_buffer_writer = + UserBufferWriter::new_checked(buf_vaddr, len, frame.is_from_user())?; let user_buf = user_buffer_writer.buffer(0)?; let binding = ProcessManager::current_pcb().fd_table(); @@ -48,6 +57,15 @@ impl Syscall for SysPread64Handle { // Drop guard to avoid scheduling issues drop(fd_table_guard); + // 检查是否是管道/Socket (ESPIPE) + let md = file.metadata()?; + if md.file_type == FileType::Pipe + || md.file_type == FileType::Socket + || md.file_type == FileType::CharDevice + { + return Err(SystemError::ESPIPE); + } + return file.pread(offset, len, user_buf); } diff --git a/kernel/src/syscall/user_access.rs b/kernel/src/syscall/user_access.rs index b6a933eb8..282fe8b04 100644 --- a/kernel/src/syscall/user_access.rs +++ b/kernel/src/syscall/user_access.rs @@ -215,7 +215,8 @@ impl UserBufferReader<'_> { len: usize, from_user: bool, ) -> Result { - if !check_user_access_by_page_table(VirtAddr::new(addr as usize), len, false) { + let accessible_len = user_accessible_len(VirtAddr::new(addr as usize), len, false); + if accessible_len < len { return Err(SystemError::EFAULT); } @@ -442,14 +443,12 @@ impl UserBufferReader<'_> { offset: usize, ) -> Result<&[T], SystemError> { let size = src.len().saturating_sub(offset); - if size > 0 - && !check_user_access_by_page_table( - VirtAddr::new(src.as_ptr() as usize + offset), - size, - false, - ) - { - return Err(SystemError::EFAULT); + if size > 0 { + let accessible_len = + user_accessible_len(VirtAddr::new(src.as_ptr() as usize + offset), size, false); + if accessible_len < size { + return Err(SystemError::EFAULT); + } } self.convert_with_offset(src, offset) } @@ -542,7 +541,8 @@ impl<'a> UserBufferWriter<'a> { } pub fn new_checked(addr: *mut U, len: usize, from_user: bool) -> Result { - if !check_user_access_by_page_table(VirtAddr::new(addr as usize), len, true) { + let accessible_len = user_accessible_len(VirtAddr::new(addr as usize), len, true); + if accessible_len < len { return Err(SystemError::EFAULT); } @@ -714,14 +714,12 @@ impl<'a> UserBufferWriter<'a> { offset: usize, ) -> Result<&mut [T], SystemError> { let size = src.len().saturating_sub(offset); - if size > 0 - && !check_user_access_by_page_table( - VirtAddr::new(src.as_ptr() as usize + offset), - size, - true, - ) - { - return Err(SystemError::EFAULT); + if size > 0 { + let accessible_len = + user_accessible_len(VirtAddr::new(src.as_ptr() as usize + offset), size, true); + if accessible_len < size { + return Err(SystemError::EFAULT); + } } Self::convert_with_offset(src, offset) } diff --git a/user/apps/tests/syscall/gvisor/blocklists/pread64_test b/user/apps/tests/syscall/gvisor/blocklists/pread64_test new file mode 100644 index 000000000..22b4bb75a --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/pread64_test @@ -0,0 +1,2 @@ +# SYS_MEMFD_CREATE未实现 +Pread64Test.Overflow diff --git a/user/apps/tests/syscall/gvisor/blocklists/preadv_test b/user/apps/tests/syscall/gvisor/blocklists/preadv_test new file mode 100644 index 000000000..c20c26f3f --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/preadv_test @@ -0,0 +1 @@ +PreadvTest.MMConcurrencyStress diff --git a/user/apps/tests/syscall/gvisor/whitelist.txt b/user/apps/tests/syscall/gvisor/whitelist.txt index cfd4fee10..1edafd23c 100644 --- a/user/apps/tests/syscall/gvisor/whitelist.txt +++ b/user/apps/tests/syscall/gvisor/whitelist.txt @@ -24,6 +24,7 @@ sync_test #chown_test chdir_test fchdir_test +pread64_test rename_test getdents_test preadv_test