feat(vfs): 增加sys_preadv 增加对readable中对 O_PATH的检查 (#1404)
* 实现preadv系统调用, 增加对对 O_PATH 的可读检查 Signed-off-by: 2448956191@qq.com <2448956191@qq.com>
This commit is contained in:
parent
cb6237403a
commit
94c1f4cd20
|
|
@ -407,9 +407,10 @@ impl File {
|
|||
/// @brief 判断当前文件是否可读
|
||||
#[inline]
|
||||
pub fn readable(&self) -> Result<(), SystemError> {
|
||||
let mode = *self.mode.read();
|
||||
// 暂时认为只要不是write only, 就可读
|
||||
if *self.mode.read() == FileMode::O_WRONLY {
|
||||
return Err(SystemError::EPERM);
|
||||
if mode == FileMode::O_WRONLY || mode.contains(FileMode::O_PATH) {
|
||||
return Err(SystemError::EBADF);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ mod sys_mkdirat;
|
|||
pub mod sys_mknodat;
|
||||
mod sys_openat;
|
||||
mod sys_pread64;
|
||||
mod sys_preadv;
|
||||
mod sys_pselect6;
|
||||
mod sys_pwrite64;
|
||||
mod sys_pwritev;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
use alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::arch::syscall::nr::SYS_PREADV;
|
||||
use crate::filesystem::vfs::iov::{IoVec, IoVecs};
|
||||
use crate::process::ProcessManager;
|
||||
use crate::syscall::table::{FormattedSyscallParam, Syscall};
|
||||
|
||||
pub struct SysPreadVHandle;
|
||||
|
||||
impl Syscall for SysPreadVHandle {
|
||||
fn num_args(&self) -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn handle(
|
||||
&self,
|
||||
args: &[usize],
|
||||
_frame: &mut crate::arch::interrupt::TrapFrame,
|
||||
) -> Result<usize, SystemError> {
|
||||
let fd = Self::fd(args);
|
||||
let iov = Self::iov(args);
|
||||
let iov_count = Self::iov_count(args);
|
||||
let offset = Self::offset(args);
|
||||
|
||||
// Construct IoVecs from user pointer.
|
||||
// For preadv, we are writing to user buffers, so we need to verify they are writable.
|
||||
// IoVecs::from_user internally uses UserBufferWriter::new which verifies the area.
|
||||
let iovecs = unsafe { IoVecs::from_user(iov, iov_count, true) }?;
|
||||
|
||||
do_preadv(fd, &iovecs, offset)
|
||||
}
|
||||
|
||||
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||
vec![
|
||||
FormattedSyscallParam::new("fd:", Self::fd(args).to_string()),
|
||||
FormattedSyscallParam::new("iov:", format!("{:#x}", Self::iov(args) as usize)),
|
||||
FormattedSyscallParam::new("iov_count:", Self::iov_count(args).to_string()),
|
||||
FormattedSyscallParam::new("offset:", Self::offset(args).to_string()),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl SysPreadVHandle {
|
||||
fn fd(args: &[usize]) -> i32 {
|
||||
args[0] as i32
|
||||
}
|
||||
|
||||
fn iov(args: &[usize]) -> *const IoVec {
|
||||
args[1] as *const IoVec
|
||||
}
|
||||
|
||||
fn iov_count(args: &[usize]) -> usize {
|
||||
args[2]
|
||||
}
|
||||
|
||||
fn offset(args: &[usize]) -> usize {
|
||||
args[3]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_preadv(fd: i32, iovecs: &IoVecs, offset: usize) -> Result<usize, SystemError> {
|
||||
let binding = ProcessManager::current_pcb().fd_table();
|
||||
let fd_table_guard = binding.read();
|
||||
|
||||
let file = fd_table_guard
|
||||
.get_file_by_fd(fd)
|
||||
.ok_or(SystemError::EBADF)?;
|
||||
|
||||
drop(fd_table_guard);
|
||||
|
||||
// Create a kernel buffer to read data into.
|
||||
// TODO: Support scatter-gather I/O directly in FS to avoid this copy.
|
||||
let mut data = vec![0; iovecs.total_len()];
|
||||
|
||||
// Read from file at offset into kernel buffer.
|
||||
let read_len = file.pread(offset, data.len(), &mut data)?;
|
||||
|
||||
// Scatter the read data back to user buffers.
|
||||
iovecs.scatter(&data[..read_len]);
|
||||
|
||||
Ok(read_len)
|
||||
}
|
||||
|
||||
syscall_table_macros::declare_syscall!(SYS_PREADV, SysPreadVHandle);
|
||||
|
|
@ -25,6 +25,7 @@ chdir_test
|
|||
fchdir_test
|
||||
rename_test
|
||||
getdents_test
|
||||
preadv_test
|
||||
|
||||
# 进程相关测试
|
||||
fork_test
|
||||
|
|
|
|||
Loading…
Reference in New Issue