From 7c356ff53cc4dd853cd056237e527462abcd684b Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Sun, 7 Dec 2025 20:44:49 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E9=99=90=E5=88=B6=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E5=8C=BA=E5=A4=A7=E5=B0=8F=E4=B8=BA=20512KB=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E5=88=86=E9=85=8D=E8=BF=87=E5=A4=A7=E5=86=85=E5=AD=98?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=AE=B9=E9=87=8F=E6=BA=A2=E5=87=BA=EF=BC=9B?= =?UTF-8?q?=E4=B8=BAresize=E5=8A=A0=E4=B8=8A=E9=A1=B5=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E6=88=AA=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/fat/entry.rs | 21 +++++++++++++++++-- kernel/src/filesystem/fat/fs.rs | 14 ++++++++----- .../filesystem/vfs/syscall/sys_truncate.rs | 3 +++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/kernel/src/filesystem/fat/entry.rs b/kernel/src/filesystem/fat/entry.rs index b5ee37869..14ad00a00 100644 --- a/kernel/src/filesystem/fat/entry.rs +++ b/kernel/src/filesystem/fat/entry.rs @@ -202,6 +202,12 @@ impl FATFile { .gendisk .write_at_bytes(&buf[start..start + end_len], offset as usize)?; + // 如果写入了 0 字节,可能是磁盘错误,避免死循环 + if w == 0 { + warn!("FAT write returned 0 bytes, breaking to avoid infinite loop"); + break; + } + // 更新偏移量数据 write_ok += w; start += w; @@ -322,8 +328,19 @@ impl FATFile { return Ok(()); } - let zeroes: Vec = vec![0u8; (range_end - range_start) as usize]; - fs.gendisk.write_at_bytes(&zeroes, range_start as usize)?; + // 限制每次写入的缓冲区大小,避免大文件扩展时分配过大内存 + const ZERO_BUF_SIZE: usize = 512 * 1024; // 512KB + let zeroes: Vec = vec![0u8; ZERO_BUF_SIZE]; + let mut offset = range_start; + let mut remain = (range_end - range_start) as usize; + + while remain > 0 { + let write_size = core::cmp::min(remain, ZERO_BUF_SIZE); + fs.gendisk + .write_at_bytes(&zeroes[..write_size], offset as usize)?; + offset += write_size as u64; + remain -= write_size; + } return Ok(()); } diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 109ffe3b8..b978b570e 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1,4 +1,7 @@ use crate::filesystem::vfs::syscall::RenameFlags; +use crate::arch::MMArch; +use crate::mm::truncate::truncate_inode_pages; +use crate::mm::MemoryManagementArch; use alloc::string::ToString; use alloc::{ string::String, @@ -1737,8 +1740,10 @@ impl IndexNode for LockedFATInode { Ok(()) } fn resize(&self, len: usize) -> Result<(), SystemError> { - // 先调整页缓存大小,但不要提前返回;后续仍需同步到底层文件并更新元数据 + // 先调整页缓存:清除被截断区间的缓存页,再缩容缓存大小 if let Some(page_cache) = self.page_cache() { + let start_page = (len + MMArch::PAGE_SIZE - 1) >> MMArch::PAGE_SHIFT; + truncate_inode_pages(page_cache.clone(), start_page); page_cache.lock_irqsave().resize(len)?; } @@ -1755,11 +1760,10 @@ impl IndexNode for LockedFATInode { } Ordering::Greater => { // 如果新的长度比旧的长度大,那么就在文件末尾添加空白 - let mut buf: Vec = Vec::new(); + // 限制缓冲区大小为 512KB,避免分配过大内存导致容量溢出 let mut remain_size = len - old_size; - let buf_size = remain_size; - // let buf_size = core::cmp::min(remain_size, 512 * 1024); - buf.resize(buf_size, 0); + let buf_size = core::cmp::min(remain_size, 512 * 1024); + let buf: Vec = vec![0u8; buf_size]; let mut offset = old_size; while remain_size > 0 { diff --git a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs index 0e503a17e..d524c0feb 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs @@ -35,6 +35,9 @@ impl Syscall for SysTruncateHandle { let path_ptr = args[0] as *const u8; let length = args[1]; + if length > 1024 * 1024 { + return Err(SystemError::EFBIG); + } // 复制并校验用户态路径 let path = check_and_clone_cstr(path_ptr, Some(MAX_PATHLEN))?; let path = path.to_str().map_err(|_| SystemError::EINVAL)?; From 26a5619231c62e94995a50489e06761f6147fcb1 Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Sun, 7 Dec 2025 21:31:17 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9len=E7=9A=84?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=EF=BC=8C=E6=A3=80=E6=9F=A5=E6=88=AA=E6=96=AD?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E9=95=BF=E5=BA=A6=E6=98=AF=E5=90=A6=E8=B6=85?= =?UTF-8?q?=E8=BF=87=E9=99=90=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/vfs/file.rs | 15 ++++++- .../filesystem/vfs/syscall/sys_ftruncate.rs | 12 ++++-- .../filesystem/vfs/syscall/sys_truncate.rs | 41 +++++++++++++++---- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index 96c6a7287..a72fcca7f 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -37,7 +37,7 @@ use crate::{ ProcessControlBlock, ProcessManager, RawPid, }, }; -use crate::{filesystem::vfs::InodeFlags, process::pid::PidPrivateData}; +use crate::{arch::ipc::signal::Signal, filesystem::vfs::InodeFlags, process::pid::PidPrivateData}; const MAX_LFS_FILESIZE: i64 = i64::MAX; /// Namespace fd backing data, typically created from /proc/thread-self/ns/* files. @@ -980,6 +980,19 @@ impl File { // 如果文件不可写,返回错误 self.writeable()?; + // RLIMIT_FSIZE 对常规文件生效 + let md = self.inode.metadata()?; + if md.file_type != FileType::File { + return Err(SystemError::EINVAL); + } + + let current_pcb = ProcessManager::current_pcb(); + let fsize_limit = current_pcb.get_rlimit(RLimitID::Fsize); + if fsize_limit.rlim_cur != u64::MAX && len as u64 > fsize_limit.rlim_cur { + let _ = send_signal_to_pid(current_pcb.raw_pid(), Signal::SIGXFSZ); + return Err(SystemError::EFBIG); + } + // 统一通过 VFS 封装,复用类型/只读检查 crate::filesystem::vfs::vcore::vfs_truncate(self.inode(), len)?; return Ok(()); diff --git a/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs b/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs index 7d8f73acb..0699162af 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs @@ -31,7 +31,7 @@ impl Syscall for SysFtruncateHandle { } fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { let fd = Self::fd(args); - let len = Self::len(args); + let len = Self::len(args)?; let binding = ProcessManager::current_pcb().fd_table(); let fd_table_guard = binding.read(); @@ -49,7 +49,7 @@ impl Syscall for SysFtruncateHandle { fn entry_format(&self, args: &[usize]) -> Vec { vec![ FormattedSyscallParam::new("fd", format!("{:#x}", Self::fd(args))), - FormattedSyscallParam::new("len", format!("{:#x}", Self::len(args))), + FormattedSyscallParam::new("len", format!("{:#x}", Self::len(args).unwrap_or(0))), ] } } @@ -59,8 +59,12 @@ impl SysFtruncateHandle { args[0] as i32 } - fn len(args: &[usize]) -> usize { - args[1] + fn len(args: &[usize]) -> Result { + let len = args[1] as isize; + if len < 0 { + return Err(SystemError::EINVAL); + } + Ok(len as usize) } } diff --git a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs index d524c0feb..3c38bb8e2 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs @@ -1,10 +1,12 @@ -use crate::arch::syscall::nr::SYS_TRUNCATE; +use crate::arch::{ipc::signal::Signal, syscall::nr::SYS_TRUNCATE}; use crate::{ arch::interrupt::TrapFrame, filesystem::vfs::{ - fcntl::AtFlags, utils::user_path_at, IndexNode, MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES, + fcntl::AtFlags, permission::PermissionMask, utils::user_path_at, FileType, IndexNode, + MAX_PATHLEN, VFS_MAX_FOLLOW_SYMLINK_TIMES, }, - process::ProcessManager, + ipc::kill::send_signal_to_pid, + process::{resource::RLimitID, ProcessManager}, syscall::{ table::{FormattedSyscallParam, Syscall}, user_access::check_and_clone_cstr, @@ -33,11 +35,7 @@ impl Syscall for SysTruncateHandle { fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { let path_ptr = args[0] as *const u8; - let length = args[1]; - - if length > 1024 * 1024 { - return Err(SystemError::EFBIG); - } + let length = Self::len(args)?; // 复制并校验用户态路径 let path = check_and_clone_cstr(path_ptr, Some(MAX_PATHLEN))?; let path = path.to_str().map_err(|_| SystemError::EINVAL)?; @@ -53,6 +51,23 @@ impl Syscall for SysTruncateHandle { let target: Arc = begin_inode .lookup_follow_symlink(remain_path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; + let md = target.metadata()?; + // DAC write permission check + let cred = ProcessManager::current_pcb().cred(); + cred.inode_permission(&md, PermissionMask::MAY_WRITE.bits())?; + + // RLIMIT_FSIZE enforcement for regular files + if md.file_type == FileType::File { + let fsize_limit = ProcessManager::current_pcb().get_rlimit(RLimitID::Fsize); + if fsize_limit.rlim_cur != u64::MAX && length as u64 > fsize_limit.rlim_cur { + let _ = send_signal_to_pid( + ProcessManager::current_pcb().raw_pid(), + Signal::SIGXFSZ, + ); + return Err(SystemError::EFBIG); + } + } + vfs_truncate(target, length)?; Ok(0) } @@ -65,4 +80,14 @@ impl Syscall for SysTruncateHandle { } } +impl SysTruncateHandle { + fn len(args: &[usize]) -> Result { + let len = args[1] as isize; + if len < 0 { + return Err(SystemError::EINVAL); + } + Ok(len as usize) + } +} + syscall_table_macros::declare_syscall!(SYS_TRUNCATE, SysTruncateHandle); From c77598e8cdf232c5edee51aec242989a721e47ea Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Sun, 7 Dec 2025 21:34:15 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E6=A3=80=E6=9F=A5filemode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/vfs/file.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index a72fcca7f..c298dbf20 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -977,15 +977,24 @@ impl File { /// @return 成功:Ok() /// 失败:Err(错误码) pub fn ftruncate(&self, len: usize) -> Result<(), SystemError> { - // 如果文件不可写,返回错误 - self.writeable()?; - - // RLIMIT_FSIZE 对常规文件生效 + // 类型必须是普通文件,否则 EINVAL let md = self.inode.metadata()?; if md.file_type != FileType::File { return Err(SystemError::EINVAL); } + // O_PATH 直接返回 EBADF,保持与 open 时的行为一致 + let mode = *self.mode.read(); + if mode.contains(FileMode::FMODE_PATH) { + return Err(SystemError::EBADF); + } + + // 非可写打开返回 EINVAL(对齐 gVisor 预期) + if !mode.contains(FileMode::FMODE_WRITE) || !mode.can_write() { + return Err(SystemError::EINVAL); + } + + // RLIMIT_FSIZE 检查 let current_pcb = ProcessManager::current_pcb(); let fsize_limit = current_pcb.get_rlimit(RLimitID::Fsize); if fsize_limit.rlim_cur != u64::MAX && len as u64 > fsize_limit.rlim_cur { From f12f38afe5cb4e4e87facd40583160975442e305 Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Sun, 7 Dec 2025 21:44:05 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E5=9B=9E=E9=80=80=E5=9C=A8resize?= =?UTF-8?q?=E9=87=8C=E9=99=90=E5=88=B6=E6=96=87=E4=BB=B6=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/fat/entry.rs | 6 ------ kernel/src/filesystem/fat/fs.rs | 7 ++++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/kernel/src/filesystem/fat/entry.rs b/kernel/src/filesystem/fat/entry.rs index 14ad00a00..e13e9caaa 100644 --- a/kernel/src/filesystem/fat/entry.rs +++ b/kernel/src/filesystem/fat/entry.rs @@ -202,12 +202,6 @@ impl FATFile { .gendisk .write_at_bytes(&buf[start..start + end_len], offset as usize)?; - // 如果写入了 0 字节,可能是磁盘错误,避免死循环 - if w == 0 { - warn!("FAT write returned 0 bytes, breaking to avoid infinite loop"); - break; - } - // 更新偏移量数据 write_ok += w; start += w; diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index b978b570e..85419eefa 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1760,10 +1760,11 @@ impl IndexNode for LockedFATInode { } Ordering::Greater => { // 如果新的长度比旧的长度大,那么就在文件末尾添加空白 - // 限制缓冲区大小为 512KB,避免分配过大内存导致容量溢出 + let mut buf: Vec = Vec::new(); let mut remain_size = len - old_size; - let buf_size = core::cmp::min(remain_size, 512 * 1024); - let buf: Vec = vec![0u8; buf_size]; + let buf_size = remain_size; + // let buf_size = core::cmp::min(remain_size, 512 * 1024); + buf.resize(buf_size, 0); let mut offset = old_size; while remain_size > 0 { From 9a757c1be695d7bd884b70baa9ea9fdf885fe8ae Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Sun, 7 Dec 2025 21:58:37 +0800 Subject: [PATCH 05/10] fmt --- kernel/src/filesystem/fat/fs.rs | 2 +- kernel/src/filesystem/vfs/file.rs | 2 +- kernel/src/filesystem/vfs/syscall/sys_truncate.rs | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index 85419eefa..d399d180f 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1,5 +1,5 @@ -use crate::filesystem::vfs::syscall::RenameFlags; use crate::arch::MMArch; +use crate::filesystem::vfs::syscall::RenameFlags; use crate::mm::truncate::truncate_inode_pages; use crate::mm::MemoryManagementArch; use alloc::string::ToString; diff --git a/kernel/src/filesystem/vfs/file.rs b/kernel/src/filesystem/vfs/file.rs index c298dbf20..fc2b74176 100644 --- a/kernel/src/filesystem/vfs/file.rs +++ b/kernel/src/filesystem/vfs/file.rs @@ -8,6 +8,7 @@ use log::error; use system_error::SystemError; use super::{FileType, IndexNode, InodeId, Metadata, SpecialNodeData}; +use crate::{arch::ipc::signal::Signal, filesystem::vfs::InodeFlags, process::pid::PidPrivateData}; use crate::{ arch::MMArch, driver::{ @@ -37,7 +38,6 @@ use crate::{ ProcessControlBlock, ProcessManager, RawPid, }, }; -use crate::{arch::ipc::signal::Signal, filesystem::vfs::InodeFlags, process::pid::PidPrivateData}; const MAX_LFS_FILESIZE: i64 = i64::MAX; /// Namespace fd backing data, typically created from /proc/thread-self/ns/* files. diff --git a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs index 3c38bb8e2..311c3f4fb 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs @@ -60,10 +60,8 @@ impl Syscall for SysTruncateHandle { if md.file_type == FileType::File { let fsize_limit = ProcessManager::current_pcb().get_rlimit(RLimitID::Fsize); if fsize_limit.rlim_cur != u64::MAX && length as u64 > fsize_limit.rlim_cur { - let _ = send_signal_to_pid( - ProcessManager::current_pcb().raw_pid(), - Signal::SIGXFSZ, - ); + let _ = + send_signal_to_pid(ProcessManager::current_pcb().raw_pid(), Signal::SIGXFSZ); return Err(SystemError::EFBIG); } } From 0f4303c6c1db58d07709310b2d6afe3f3998e3fa Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Sun, 7 Dec 2025 21:59:48 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user/apps/tests/syscall/gvisor/blocklists/truncate_test | 1 + user/apps/tests/syscall/gvisor/whitelist.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 user/apps/tests/syscall/gvisor/blocklists/truncate_test diff --git a/user/apps/tests/syscall/gvisor/blocklists/truncate_test b/user/apps/tests/syscall/gvisor/blocklists/truncate_test new file mode 100644 index 000000000..36f093ed0 --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/truncate_test @@ -0,0 +1 @@ +TruncateTest.FtruncateVirtualTmp diff --git a/user/apps/tests/syscall/gvisor/whitelist.txt b/user/apps/tests/syscall/gvisor/whitelist.txt index ccf09ce6e..75711cc36 100644 --- a/user/apps/tests/syscall/gvisor/whitelist.txt +++ b/user/apps/tests/syscall/gvisor/whitelist.txt @@ -30,6 +30,7 @@ rename_test getdents_test preadv_test utimes_test +truncate_test # 进程相关测试 fork_test From da98a8322ad94630631c002e51de7253ac58df16 Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Thu, 11 Dec 2025 23:31:00 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E7=9A=84=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=9B=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=99=90=E5=88=B6=E5=A4=A7=E5=B0=8F=E7=9A=84=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E5=8C=BA=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/fat/fs.rs | 12 +++++------- kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs | 6 +++--- kernel/src/filesystem/vfs/syscall/sys_truncate.rs | 6 +++--- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index d399d180f..c495a8ecb 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1760,16 +1760,14 @@ impl IndexNode for LockedFATInode { } Ordering::Greater => { // 如果新的长度比旧的长度大,那么就在文件末尾添加空白 - let mut buf: Vec = Vec::new(); - let mut remain_size = len - old_size; - let buf_size = remain_size; - // let buf_size = core::cmp::min(remain_size, 512 * 1024); - buf.resize(buf_size, 0); + const ZERO_BUF_SIZE: usize = 512 * 1024; // 与 zero_range 保持一致的上限 + let buf: Vec = vec![0u8; ZERO_BUF_SIZE]; + let mut remain_size = len - old_size; let mut offset = old_size; while remain_size > 0 { - let write_size = core::cmp::min(remain_size, buf_size); - file.write(fs, &buf[0..write_size], offset as u64)?; + let write_size = core::cmp::min(remain_size, ZERO_BUF_SIZE); + file.write(fs, &buf[..write_size], offset as u64)?; remain_size -= write_size; offset += write_size; } diff --git a/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs b/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs index 0699162af..5f6d84c1c 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_ftruncate.rs @@ -60,11 +60,11 @@ impl SysFtruncateHandle { } fn len(args: &[usize]) -> Result { - let len = args[1] as isize; - if len < 0 { + let len = args[1]; + if len > isize::MAX as usize { return Err(SystemError::EINVAL); } - Ok(len as usize) + Ok(len) } } diff --git a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs index 311c3f4fb..f632af118 100644 --- a/kernel/src/filesystem/vfs/syscall/sys_truncate.rs +++ b/kernel/src/filesystem/vfs/syscall/sys_truncate.rs @@ -80,11 +80,11 @@ impl Syscall for SysTruncateHandle { impl SysTruncateHandle { fn len(args: &[usize]) -> Result { - let len = args[1] as isize; - if len < 0 { + let len = args[1]; + if len > isize::MAX as usize { return Err(SystemError::EINVAL); } - Ok(len as usize) + Ok(len) } } From 45d5e088dd478b7262873fc02f06ec94bf78d728 Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Thu, 11 Dec 2025 23:47:23 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E5=9C=A8fat=E7=9A=84resize=E4=B8=AD?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E6=9C=80=E5=A4=A7=E5=AE=B9=E9=87=8F=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/fat/fs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index c495a8ecb..837faaa33 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -1740,6 +1740,10 @@ impl IndexNode for LockedFATInode { Ok(()) } fn resize(&self, len: usize) -> Result<(), SystemError> { + //检查是否超过fat支持的最大容量 + if (len as u64) > MAX_FILE_SIZE { + return Err(SystemError::EFBIG); + } // 先调整页缓存:清除被截断区间的缓存页,再缩容缓存大小 if let Some(page_cache) = self.page_cache() { let start_page = (len + MMArch::PAGE_SIZE - 1) >> MMArch::PAGE_SHIFT; From a8e4073c68a679dd16e43ccc0edabb7667df85a2 Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Mon, 15 Dec 2025 19:53:20 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=AE=9A=E4=B9=89ZERO?= =?UTF-8?q?=5FBUF=5FSIZE=EF=BC=9B=E5=A2=9E=E5=8A=A0=E5=AF=B9=E9=9B=B6?= =?UTF-8?q?=E5=86=99=E5=85=A5=E7=9A=84=E6=A3=80=E6=9F=A5=EF=BC=9B=E5=9C=A8?= =?UTF-8?q?vfs=E5=B1=82=E7=BB=9F=E4=B8=80=E6=8B=92=E7=BB=9D=E8=B6=85?= =?UTF-8?q?=E5=87=BA=20isize::MAX=20=E7=9A=84=E9=95=BF=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/filesystem/fat/entry.rs | 14 +++++++++----- kernel/src/filesystem/fat/fs.rs | 4 +++- kernel/src/filesystem/vfs/vcore.rs | 5 +++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/kernel/src/filesystem/fat/entry.rs b/kernel/src/filesystem/fat/entry.rs index e13e9caaa..0685e8ab6 100644 --- a/kernel/src/filesystem/fat/entry.rs +++ b/kernel/src/filesystem/fat/entry.rs @@ -16,7 +16,7 @@ use log::{debug, warn}; use system_error::SystemError; use super::{ - fs::{Cluster, FATFileSystem, MAX_FILE_SIZE}, + fs::{Cluster, FATFileSystem, MAX_FILE_SIZE, ZERO_BUF_SIZE}, utils::decode_u8_ascii, }; @@ -197,10 +197,13 @@ impl FATFile { // 计算本次写入位置在分区上的偏移量 let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_bytes_offset; - // 写入磁盘 + // 写入磁盘(防御性检查:若设备返回0字节写入视为IO错误) let w = fs .gendisk .write_at_bytes(&buf[start..start + end_len], offset as usize)?; + if w == 0 { + return Err(SystemError::EIO); + } // 更新偏移量数据 write_ok += w; @@ -323,15 +326,16 @@ impl FATFile { } // 限制每次写入的缓冲区大小,避免大文件扩展时分配过大内存 - const ZERO_BUF_SIZE: usize = 512 * 1024; // 512KB let zeroes: Vec = vec![0u8; ZERO_BUF_SIZE]; let mut offset = range_start; let mut remain = (range_end - range_start) as usize; while remain > 0 { let write_size = core::cmp::min(remain, ZERO_BUF_SIZE); - fs.gendisk - .write_at_bytes(&zeroes[..write_size], offset as usize)?; + let w = fs.gendisk.write_at_bytes(&zeroes[..write_size], offset as usize)?; + if w == 0 { + return Err(SystemError::EIO); + } offset += write_size as u64; remain -= write_size; } diff --git a/kernel/src/filesystem/fat/fs.rs b/kernel/src/filesystem/fat/fs.rs index f975a8829..c180ada1b 100644 --- a/kernel/src/filesystem/fat/fs.rs +++ b/kernel/src/filesystem/fat/fs.rs @@ -51,6 +51,9 @@ const FAT_MAX_NAMELEN: u64 = 255; /// FAT32文件系统的最大的文件大小 pub const MAX_FILE_SIZE: u64 = 0xffff_ffff; +/// 每次清零写入时的缓冲区上限(避免分配过大内存) +pub const ZERO_BUF_SIZE: usize = 512 * 1024; // 512KB + /// @brief 表示当前簇和上一个簇的关系的结构体 /// 定义这样一个结构体的原因是,FAT文件系统的文件中,前后两个簇具有关联关系。 #[allow(dead_code)] @@ -1776,7 +1779,6 @@ impl IndexNode for LockedFATInode { } Ordering::Greater => { // 如果新的长度比旧的长度大,那么就在文件末尾添加空白 - const ZERO_BUF_SIZE: usize = 512 * 1024; // 与 zero_range 保持一致的上限 let buf: Vec = vec![0u8; ZERO_BUF_SIZE]; let mut remain_size = len - old_size; diff --git a/kernel/src/filesystem/vfs/vcore.rs b/kernel/src/filesystem/vfs/vcore.rs index b5842fbef..d64af2de8 100644 --- a/kernel/src/filesystem/vfs/vcore.rs +++ b/kernel/src/filesystem/vfs/vcore.rs @@ -372,6 +372,11 @@ pub(super) fn do_file_lookup_at( pub fn vfs_truncate(inode: Arc, len: usize) -> Result<(), SystemError> { let md = inode.metadata()?; + // 防御性检查:统一拒绝超出 isize::MAX 的长度,避免后续类型转换溢出 + if len > isize::MAX as usize { + return Err(SystemError::EINVAL); + } + if md.file_type == FileType::Dir { return Err(SystemError::EISDIR); } From 456e821d8cbb59af14d453044fb2f692c72811f2 Mon Sep 17 00:00:00 2001 From: kaleidoscope416 <2448956191@qq.com> Date: Mon, 15 Dec 2025 22:56:24 +0800 Subject: [PATCH 10/10] fmt --- kernel/src/filesystem/fat/entry.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/src/filesystem/fat/entry.rs b/kernel/src/filesystem/fat/entry.rs index 0685e8ab6..2860c2064 100644 --- a/kernel/src/filesystem/fat/entry.rs +++ b/kernel/src/filesystem/fat/entry.rs @@ -332,7 +332,9 @@ impl FATFile { while remain > 0 { let write_size = core::cmp::min(remain, ZERO_BUF_SIZE); - let w = fs.gendisk.write_at_bytes(&zeroes[..write_size], offset as usize)?; + let w = fs + .gendisk + .write_at_bytes(&zeroes[..write_size], offset as usize)?; if w == 0 { return Err(SystemError::EIO); }