Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions kernel/src/filesystem/vfs/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ pub(super) fn do_faccessat(

let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;

if path.len() == 0 {
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;

// 如果找不到文件,则返回错误码ENOENT
Expand All @@ -52,10 +48,6 @@ pub(super) fn do_faccessat(
pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError> {
let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;

if path.len() == 0 {
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;

// 如果找不到文件,则返回错误码ENOENT
Expand Down
69 changes: 26 additions & 43 deletions kernel/src/filesystem/vfs/syscall.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::ffi::CStr;

use alloc::{
string::{String, ToString},
sync::Arc,
Expand All @@ -10,12 +8,11 @@ use system_error::SystemError;
use crate::{
driver::base::{block::SeekFrom, device::device_number::DeviceNumber},
filesystem::vfs::file::FileDescriptorVec,
kerror,
libs::rwlock::RwLockWriteGuard,
mm::{verify_area, VirtAddr},
process::ProcessManager,
syscall::{
user_access::{check_and_clone_cstr, UserBufferReader, UserBufferWriter},
user_access::{check_and_clone_cstr, UserBufferWriter},
Syscall,
},
time::TimeSpec,
Expand Down Expand Up @@ -461,8 +458,7 @@ impl Syscall {
}
let inode =
match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) {
Err(e) => {
kerror!("Change Directory Failed, Error = {:?}", e);
Err(_) => {
return Err(SystemError::ENOENT);
}
Ok(i) => i,
Expand Down Expand Up @@ -554,7 +550,6 @@ impl Syscall {
// kdebug!("rmdir");
match do_remove_dir(dirfd, &pathname) {
Err(err) => {
kerror!("Failed to Remove Directory, Error Code = {:?}", err);
return Err(err);
}
Ok(_) => {
Expand All @@ -565,7 +560,6 @@ impl Syscall {

match do_unlink_at(dirfd, &pathname) {
Err(err) => {
kerror!("Failed to Remove Directory, Error Code = {:?}", err);
return Err(err);
}
Ok(_) => {
Expand All @@ -575,29 +569,14 @@ impl Syscall {
}

pub fn rmdir(pathname: *const u8) -> Result<usize, SystemError> {
let pathname: String = check_and_clone_cstr(pathname, Some(MAX_PATHLEN))?;
if pathname.len() >= MAX_PATHLEN {
return Err(SystemError::ENAMETOOLONG);
}
let pathname = Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;
let pathname = pathname.as_str().trim();
return do_remove_dir(AtFlags::AT_FDCWD.bits(), pathname).map(|v| v as usize);
}

pub fn unlink(pathname: *const u8) -> Result<usize, SystemError> {
if pathname.is_null() {
return Err(SystemError::EFAULT);
}
let ureader = UserBufferReader::new(pathname, MAX_PATHLEN, true)?;

let buf: &[u8] = ureader.buffer(0).unwrap();

let pathname: &CStr = CStr::from_bytes_until_nul(buf).map_err(|_| SystemError::EINVAL)?;

let pathname: &str = pathname.to_str().map_err(|_| SystemError::EINVAL)?;
if pathname.len() >= MAX_PATHLEN {
return Err(SystemError::ENAMETOOLONG);
}
let pathname = pathname.trim();
let pathname = Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;
let pathname = pathname.as_str().trim();

return do_unlink_at(AtFlags::AT_FDCWD.bits(), pathname).map(|v| v as usize);
}
Expand Down Expand Up @@ -872,29 +851,22 @@ impl Syscall {
}

pub fn mknod(
path_ptr: *const i8,
path_ptr: *const u8,
mode: ModeType,
dev_t: DeviceNumber,
) -> Result<usize, SystemError> {
// 安全检验
let len = unsafe { CStr::from_ptr(path_ptr).to_bytes().len() };
let user_buffer = UserBufferReader::new(path_ptr, len, true)?;
let buf = user_buffer.read_from_user::<u8>(0)?;
let path = core::str::from_utf8(buf).map_err(|_| SystemError::EINVAL)?;

// 文件名过长
if path.len() > MAX_PATHLEN as usize {
return Err(SystemError::ENAMETOOLONG);
}
let pathname = path_ptr;
let pathname = Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;
let pathname = pathname.as_str().trim();

let inode: Result<Arc<dyn IndexNode>, SystemError> =
ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
ROOT_INODE().lookup_follow_symlink(pathname, VFS_MAX_FOLLOW_SYMLINK_TIMES);

if inode.is_ok() {
return Err(SystemError::EEXIST);
}

let (filename, parent_path) = rsplit_path(path);
let (filename, parent_path) = rsplit_path(pathname);

// 查找父目录
let parent_inode: Arc<dyn IndexNode> = ROOT_INODE()
Expand Down Expand Up @@ -937,10 +909,6 @@ impl Syscall {
let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?;

if path.len() == 0 {
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;

let inode = inode.lookup(path.as_str())?;
Expand Down Expand Up @@ -1017,6 +985,21 @@ impl Syscall {
kwarn!("fchmod not fully implemented");
return Ok(0);
}

/// @brief 处理文件路径字符串,并将其从用户空间复制到内核空间
pub fn get_pathname(pathname: *const u8) -> Result<String, SystemError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个函数我觉得可以删掉,因为判断是否超过最大长度,check_and_clone_str已经做了。然后判断是否为空这个,不需要判断。因为lookup的时候本身就会去报出相应的错误。

let pathname: String = check_and_clone_cstr(pathname, Some(MAX_PATHLEN))?;

if pathname.len() >= MAX_PATHLEN {
return Err(SystemError::ENAMETOOLONG);
}

if pathname.is_empty() {
return Err(SystemError::ENOENT);
}

Ok(pathname)
}
}

#[repr(C)]
Expand Down
153 changes: 60 additions & 93 deletions kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::{
ffi::{c_char, c_int, c_void, CStr},
ffi::{c_char, c_int, c_void},
sync::atomic::{AtomicBool, Ordering},
};

Expand Down Expand Up @@ -90,41 +90,31 @@ impl Syscall {
}
#[cfg(target_arch = "x86_64")]
SYS_OPEN => {
let path: &CStr = unsafe { CStr::from_ptr(args[0] as *const c_char) };
let path: Result<&str, core::str::Utf8Error> = path.to_str();
let res = if path.is_err() {
Err(SystemError::EINVAL)
} else {
let path: &str = path.unwrap();

let flags = args[1];
let mode = args[2];
let pathname = args[0] as *const u8;
let pathname =
Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;
let pathname = pathname.trim();

let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
let mode = ModeType::from_bits(mode as u32).ok_or(SystemError::EINVAL)?;
Self::open(path, open_flags, mode, true)
};
res
let flags = args[1];
let mode = args[2];
let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
let mode = ModeType::from_bits(mode as u32).ok_or(SystemError::EINVAL)?;
Self::open(pathname, open_flags, mode, true)
}

SYS_OPENAT => {
let dirfd = args[0] as i32;
let path: &CStr = unsafe { CStr::from_ptr(args[1] as *const c_char) };
let pathname = args[1] as *const u8;
let pathname =
Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些操作不应该在这里执行。应当写到vfs里面的函数内。因为这样会造成vfs和通用的syscall入口的耦合。

let pathname = pathname.trim();
let flags = args[2];
let mode = args[3];

let path: Result<&str, core::str::Utf8Error> = path.to_str();
let res = if path.is_err() {
Err(SystemError::EINVAL)
} else {
let path: &str = path.unwrap();

let open_flags: FileMode =
FileMode::from_bits(flags as u32).ok_or(SystemError::EINVAL)?;
let mode = ModeType::from_bits(mode as u32).ok_or(SystemError::EINVAL)?;
Self::openat(dirfd, path, open_flags, mode, true)
};
res
let open_flags: FileMode =
FileMode::from_bits(flags as u32).ok_or(SystemError::EINVAL)?;
let mode = ModeType::from_bits(mode as u32).ok_or(SystemError::EINVAL)?;
Self::openat(dirfd, pathname, open_flags, mode, true)
}
SYS_CLOSE => {
let fd = args[0];
Expand Down Expand Up @@ -233,18 +223,16 @@ impl Syscall {
{
return Err(SystemError::EINVAL);
}
let dest_path: &CStr = unsafe { CStr::from_ptr(path_ptr) };
let dest_path: &str = dest_path.to_str().map_err(|_| SystemError::EINVAL)?;
if dest_path.len() == 0 {
return Err(SystemError::EINVAL);
} else if dest_path.len() > MAX_PATHLEN as usize {
return Err(SystemError::ENAMETOOLONG);
}

let dest_path = arg0 as *const u8;
let dest_path =
Self::get_pathname(dest_path).map_err(|_| SystemError::EINVAL.into())?;

return Ok(dest_path);
};

let r = chdir_check(args[0])?;
let r = r.as_str().trim();
Self::chdir(r)
}

Expand Down Expand Up @@ -321,21 +309,16 @@ impl Syscall {
{
return Err(SystemError::EINVAL);
}
let path: &CStr = unsafe { CStr::from_ptr(path_ptr) };
let path: &str = path.to_str().map_err(|_| SystemError::EINVAL)?.trim();
let pathname = args[0] as *const u8;
let pathname =
Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;

if path == "" {
return Err(SystemError::EINVAL);
}
return Ok(path);
return Ok(pathname);
};

let path = security_check();
if path.is_err() {
Err(path.unwrap_err())
} else {
Self::mkdir(path.unwrap(), mode)
}
let pathname = security_check()?;
let pathname = pathname.as_str().trim();
Self::mkdir(pathname, mode)
}

SYS_NANOSLEEP => {
Expand Down Expand Up @@ -378,30 +361,24 @@ impl Syscall {

SYS_UNLINKAT => {
let dirfd = args[0] as i32;
let pathname = args[1] as *const c_char;
let path_ptr = args[1] as *const c_char;
let flags = args[2] as u32;
let virt_pathname = VirtAddr::new(pathname as usize);
let virt_pathname = VirtAddr::new(path_ptr as usize);
if frame.from_user() && verify_area(virt_pathname, PAGE_4K_SIZE as usize).is_err() {
Err(SystemError::EFAULT)
} else if pathname.is_null() {
} else if path_ptr.is_null() {
Err(SystemError::EFAULT)
} else {
let get_path = || {
let pathname: &CStr = unsafe { CStr::from_ptr(pathname) };

let pathname: &str = pathname.to_str().map_err(|_| SystemError::EINVAL)?;
if pathname.len() >= MAX_PATHLEN {
return Err(SystemError::ENAMETOOLONG);
}
return Ok(pathname.trim());
let pathname = args[1] as *const u8;
let pathname =
Self::get_pathname(pathname).map_err(|_| SystemError::EINVAL.into())?;
return Ok(pathname);
};
let pathname = get_path();
if pathname.is_err() {
Err(pathname.unwrap_err())
} else {
// kdebug!("sys unlinkat: dirfd: {}, pathname: {}", dirfd, pathname.as_ref().unwrap());
Self::unlinkat(dirfd, pathname.unwrap(), flags)
}
let pathname = get_path()?;
let pathname = pathname.as_str().trim();
// kdebug!("sys unlinkat: dirfd: {}, pathname: {}", dirfd, pathname.as_ref().unwrap());
Self::unlinkat(dirfd, pathname, flags)
}
}

Expand Down Expand Up @@ -707,7 +684,7 @@ impl Syscall {
let flags = args[1];
let dev_t = args[2];
let flags: ModeType = ModeType::from_bits_truncate(flags as u32);
Self::mknod(path as *const i8, flags, DeviceNumber::from(dev_t as u32))
Self::mknod(path as *const u8, flags, DeviceNumber::from(dev_t as u32))
}

SYS_CLONE => {
Expand Down Expand Up @@ -759,40 +736,30 @@ impl Syscall {

#[cfg(target_arch = "x86_64")]
SYS_LSTAT => {
let path: &CStr = unsafe { CStr::from_ptr(args[0] as *const c_char) };
let path: Result<&str, core::str::Utf8Error> = path.to_str();
let res = if path.is_err() {
Err(SystemError::EINVAL)
} else {
let path: &str = path.unwrap();
let kstat = args[1] as *mut PosixKstat;
let vaddr = VirtAddr::new(kstat as usize);
match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
Ok(_) => Self::lstat(path, kstat),
Err(e) => Err(e),
}
};
let pathname = Self::get_pathname(args[0] as *const u8)
.map_err(|_| SystemError::EINVAL.into())?;
let pathname = pathname.as_str().trim();

res
let kstat = args[1] as *mut PosixKstat;
let vaddr = VirtAddr::new(kstat as usize);
match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
Ok(_) => Self::lstat(pathname, kstat),
Err(e) => Err(e),
}
}

#[cfg(target_arch = "x86_64")]
SYS_STAT => {
let path: &CStr = unsafe { CStr::from_ptr(args[0] as *const c_char) };
let path: Result<&str, core::str::Utf8Error> = path.to_str();
let res = if path.is_err() {
Err(SystemError::EINVAL)
} else {
let path: &str = path.unwrap();
let kstat = args[1] as *mut PosixKstat;
let vaddr = VirtAddr::new(kstat as usize);
match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
Ok(_) => Self::stat(path, kstat),
Err(e) => Err(e),
}
};
let pathname = Self::get_pathname(args[0] as *const u8)
.map_err(|_| SystemError::EINVAL.into())?;
let pathname = pathname.as_str().trim();

res
let kstat = args[1] as *mut PosixKstat;
let vaddr = VirtAddr::new(kstat as usize);
match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
Ok(_) => Self::stat(pathname, kstat),
Err(e) => Err(e),
}
}

SYS_EPOLL_CREATE => Self::epoll_create(args[0] as i32),
Expand Down