实现系统调用Fstat (#295)

* fstat

* 修改syscall.rs中的verify_area
This commit is contained in:
houmkh
2023-08-05 18:52:46 +08:00
committed by GitHub
parent 9550910ae1
commit be63f3b2b6
9 changed files with 601 additions and 76 deletions

View File

@ -5,3 +5,4 @@ pub mod procfs;
pub mod ramfs;
pub mod sysfs;
pub mod vfs;
pub mod syscall;

View File

@ -0,0 +1,167 @@
use crate::{
arch::asm::current::current_pcb,
filesystem::vfs::FileType,
kdebug,
syscall::{Syscall, SystemError},
time::TimeSpec,
};
bitflags! {
/// 文件类型和权限
pub struct ModeType: u32 {
/// 掩码
const S_IFMT = 0o0_170_000;
/// 文件类型
const S_IFSOCK = 0o140000;
const S_IFLNK = 0o120000;
const S_IFREG = 0o100000;
const S_IFBLK = 0o060000;
const S_IFDIR = 0o040000;
const S_IFCHR = 0o020000;
const S_IFIFO = 0o010000;
const S_ISUID = 0o004000;
const S_ISGID = 0o002000;
const S_ISVTX = 0o001000;
/// 文件用户权限
const S_IRWXU = 0o0700;
const S_IRUSR = 0o0400;
const S_IWUSR = 0o0200;
const S_IXUSR = 0o0100;
/// 文件组权限
const S_IRWXG = 0o0070;
const S_IRGRP = 0o0040;
const S_IWGRP = 0o0020;
const S_IXGRP = 0o0010;
/// 文件其他用户权限
const S_IRWXO = 0o0007;
const S_IROTH = 0o0004;
const S_IWOTH = 0o0002;
const S_IXOTH = 0o0001;
}
}
#[repr(C)]
/// # 文件信息结构体
pub struct PosixKstat {
/// 硬件设备ID
dev_id: u64,
/// inode号
inode: u64,
/// 硬链接数
nlink: u64,
/// 文件权限
mode: ModeType,
/// 所有者用户ID
uid: i32,
/// 所有者组ID
gid: i32,
/// 设备ID
rdev: i64,
/// 文件大小
size: i64,
/// 文件系统块大小
blcok_size: i64,
/// 分配的512B块数
blocks: u64,
/// 最后访问时间
atime: TimeSpec,
/// 最后修改时间
mtime: TimeSpec,
/// 最后状态变化时间
ctime: TimeSpec,
/// 用于填充结构体大小的空白数据
pub _pad: [i8; 24],
}
impl PosixKstat {
fn new() -> Self {
Self {
inode: 0,
dev_id: 0,
mode: ModeType { bits: 0 },
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
size: 0,
atime: TimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
mtime: TimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
ctime: TimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
blcok_size: 0,
blocks: 0,
_pad: Default::default(),
}
}
}
impl Syscall {
fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> {
let cur = current_pcb();
match cur.get_file_ref_by_fd(fd) {
Some(file) => {
let mut kstat = PosixKstat::new();
// 获取文件信息
match file.metadata() {
Ok(metadata) => {
kstat.size = metadata.size as i64;
kstat.dev_id = metadata.dev_id as u64;
kstat.inode = metadata.inode_id as u64;
kstat.blcok_size = metadata.blk_size as i64;
kstat.blocks = metadata.blocks as u64;
kstat.atime.tv_sec = metadata.atime.tv_sec;
kstat.atime.tv_nsec = metadata.atime.tv_nsec;
kstat.mtime.tv_sec = metadata.mtime.tv_sec;
kstat.mtime.tv_nsec = metadata.mtime.tv_nsec;
kstat.ctime.tv_sec = metadata.ctime.tv_sec;
kstat.ctime.tv_nsec = metadata.ctime.tv_nsec;
kstat.nlink = metadata.nlinks as u64;
kstat.uid = metadata.uid as i32;
kstat.gid = metadata.gid as i32;
kstat.rdev = metadata.raw_dev as i64;
kstat.mode.bits = metadata.mode;
match file.file_type() {
FileType::File => kstat.mode.insert(ModeType::S_IFMT),
FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK),
FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK),
FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO),
}
}
Err(e) => return Err(e),
}
return Ok(kstat);
}
None => {
kdebug!("file not be opened");
return Err(SystemError::EINVAL);
}
}
}
pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
match Self::do_fstat(fd) {
Ok(kstat) => {
if usr_kstat.is_null() {
return Err(SystemError::EFAULT);
}
unsafe {
*usr_kstat = kstat;
}
return Ok(0);
}
Err(e) => return Err(e),
}
}
}

View File

@ -7,16 +7,17 @@ use num_traits::{FromPrimitive, ToPrimitive};
use crate::{
arch::{cpu::cpu_reset, MMArch},
filesystem::syscall::PosixKstat,
filesystem::vfs::{
file::FileMode,
syscall::{SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
MAX_PATHLEN,
},
include::bindings::bindings::{pid_t, verify_area, PAGE_2M_SIZE, PAGE_4K_SIZE},
include::bindings::bindings::{pid_t, PAGE_2M_SIZE, PAGE_4K_SIZE},
io::SeekFrom,
kinfo,
libs::align::page_align_up,
mm::{MemoryManagementArch, VirtAddr},
mm::{verify_area, MemoryManagementArch, VirtAddr},
net::syscall::SockAddr,
time::{
syscall::{PosixTimeZone, PosixTimeval},
@ -364,6 +365,8 @@ pub const SYS_MMAP: usize = 44;
pub const SYS_MUNMAP: usize = 45;
pub const SYS_MPROTECT: usize = 46;
pub const SYS_FSTAT: usize = 47;
#[derive(Debug)]
pub struct Syscall;
@ -421,9 +424,9 @@ impl Syscall {
let fd = args[0] as i32;
let buf_vaddr = args[1];
let len = args[2];
let virt_addr = VirtAddr::new(buf_vaddr);
// 判断缓冲区是否来自用户态,进行权限校验
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
let res = if from_user && verify_area(virt_addr, len as usize).is_err() {
// 来自用户态而buffer在内核态这样的操作不被允许
Err(SystemError::EPERM)
} else {
@ -439,9 +442,9 @@ impl Syscall {
let fd = args[0] as i32;
let buf_vaddr = args[1];
let len = args[2];
let virt_addr = VirtAddr::new(buf_vaddr);
// 判断缓冲区是否来自用户态,进行权限校验
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
let res = if from_user && verify_area(virt_addr, len as usize).is_err() {
// 来自用户态而buffer在内核态这样的操作不被允许
Err(SystemError::EPERM)
} else {
@ -496,10 +499,10 @@ impl Syscall {
return Err(SystemError::EFAULT);
}
let path_ptr = arg0 as *const c_char;
let virt_addr = VirtAddr::new(path_ptr as usize);
// 权限校验
if path_ptr.is_null()
|| (from_user
&& unsafe { !verify_area(path_ptr as u64, PAGE_2M_SIZE as u64) })
|| (from_user && verify_area(virt_addr, PAGE_2M_SIZE as usize).is_err())
{
return Err(SystemError::EINVAL);
}
@ -526,9 +529,9 @@ impl Syscall {
let fd = args[0] as i32;
let buf_vaddr = args[1];
let len = args[2];
let virt_addr = VirtAddr::new(buf_vaddr);
// 判断缓冲区是否来自用户态,进行权限校验
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
let res = if from_user && verify_area(virt_addr, len as usize).is_err() {
// 来自用户态而buffer在内核态这样的操作不被允许
Err(SystemError::EPERM)
} else if buf_vaddr == 0 {
@ -547,12 +550,14 @@ impl Syscall {
let path_ptr = args[0];
let argv_ptr = args[1];
let env_ptr = args[2];
let virt_path_ptr = VirtAddr::new(path_ptr);
let virt_argv_ptr = VirtAddr::new(argv_ptr);
let virt_env_ptr = VirtAddr::new(env_ptr);
// 权限校验
if from_user
&& (unsafe { !verify_area(path_ptr as u64, PAGE_4K_SIZE as u64) }
|| unsafe { !verify_area(argv_ptr as u64, PAGE_4K_SIZE as u64) })
|| unsafe { !verify_area(env_ptr as u64, PAGE_4K_SIZE as u64) }
&& (verify_area(virt_path_ptr, PAGE_4K_SIZE as usize).is_err()
|| verify_area(virt_argv_ptr, PAGE_4K_SIZE as usize).is_err())
|| verify_area(virt_env_ptr, PAGE_4K_SIZE as usize).is_err()
{
Err(SystemError::EFAULT)
} else {
@ -568,13 +573,13 @@ impl Syscall {
let wstatus = args[1] as *mut c_int;
let options = args[2] as c_int;
let rusage = args[3] as *mut c_void;
let virt_wstatus = VirtAddr::new(wstatus as usize);
let virt_rusage = VirtAddr::new(rusage as usize);
// 权限校验
// todo: 引入rusage之后更正以下权限校验代码中rusage的大小
if from_user
&& (unsafe {
!verify_area(wstatus as u64, core::mem::size_of::<c_int>() as u64)
} || unsafe { !verify_area(rusage as u64, PAGE_4K_SIZE as u64) })
&& (verify_area(virt_wstatus, core::mem::size_of::<c_int>() as usize).is_err()
|| verify_area(virt_rusage, PAGE_4K_SIZE as usize).is_err())
{
Err(SystemError::EFAULT)
} else {
@ -589,11 +594,10 @@ impl Syscall {
SYS_MKDIR => {
let path_ptr = args[0] as *const c_char;
let mode = args[1];
let virt_path_ptr = VirtAddr::new(path_ptr as usize);
let security_check = || {
if path_ptr.is_null()
|| (from_user
&& unsafe { !verify_area(path_ptr as u64, PAGE_2M_SIZE as u64) })
|| (from_user && verify_area(virt_path_ptr, PAGE_2M_SIZE as usize).is_err())
{
return Err(SystemError::EINVAL);
}
@ -617,12 +621,12 @@ impl Syscall {
SYS_NANOSLEEP => {
let req = args[0] as *const TimeSpec;
let rem = args[1] as *mut TimeSpec;
let virt_req = VirtAddr::new(req as usize);
let virt_rem = VirtAddr::new(rem as usize);
if from_user
&& (unsafe {
!verify_area(req as u64, core::mem::size_of::<TimeSpec>() as u64)
} || unsafe {
!verify_area(rem as u64, core::mem::size_of::<TimeSpec>() as u64)
})
&& (verify_area(virt_req, core::mem::size_of::<TimeSpec>() as usize).is_err()
|| verify_area(virt_rem, core::mem::size_of::<TimeSpec>() as usize)
.is_err())
{
Err(SystemError::EFAULT)
} else {
@ -633,10 +637,10 @@ impl Syscall {
SYS_CLOCK => Self::clock(),
SYS_PIPE => {
let pipefd = args[0] as *mut c_int;
let virt_pipefd = VirtAddr::new(pipefd as usize);
if from_user
&& unsafe {
!verify_area(pipefd as u64, core::mem::size_of::<[c_int; 2]>() as u64)
}
&& verify_area(virt_pipefd, core::mem::size_of::<[c_int; 2]>() as usize)
.is_err()
{
Err(SystemError::EFAULT)
} else if pipefd.is_null() {
@ -651,7 +655,8 @@ impl Syscall {
let dirfd = args[0] as i32;
let pathname = args[1] as *const c_char;
let flags = args[2] as u32;
if from_user && unsafe { !verify_area(pathname as u64, PAGE_4K_SIZE as u64) } {
let virt_pathname = VirtAddr::new(pathname as usize);
if from_user && verify_area(virt_pathname, PAGE_4K_SIZE as usize).is_err() {
Err(SystemError::EFAULT)
} else if pathname.is_null() {
Err(SystemError::EFAULT)
@ -710,8 +715,9 @@ impl Syscall {
SYS_SETSOCKOPT => {
let optval = args[3] as *const u8;
let optlen = args[4] as usize;
let virt_optval = VirtAddr::new(optval as usize);
// 验证optval的地址是否合法
if unsafe { verify_area(optval as u64, optlen as u64) } == false {
if verify_area(virt_optval, optlen as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
@ -722,18 +728,17 @@ impl Syscall {
SYS_GETSOCKOPT => {
let optval = args[3] as *mut u8;
let optlen = args[4] as *mut usize;
let virt_optval = VirtAddr::new(optval as usize);
let virt_optlen = VirtAddr::new(optlen as usize);
let security_check = || {
// 验证optval的地址是否合法
if unsafe { verify_area(optval as u64, PAGE_4K_SIZE as u64) } == false {
if verify_area(virt_optval, PAGE_4K_SIZE as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
// 验证optlen的地址是否合法
if unsafe { verify_area(optlen as u64, core::mem::size_of::<u32>() as u64) }
== false
{
if verify_area(virt_optlen, core::mem::size_of::<u32>() as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
@ -750,8 +755,9 @@ impl Syscall {
SYS_CONNECT => {
let addr = args[1] as *const SockAddr;
let addrlen = args[2] as usize;
let virt_addr = VirtAddr::new(addr as usize);
// 验证addr的地址是否合法
if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
if verify_area(virt_addr, addrlen as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
@ -761,8 +767,9 @@ impl Syscall {
SYS_BIND => {
let addr = args[1] as *const SockAddr;
let addrlen = args[2] as usize;
let virt_addr = VirtAddr::new(addr as usize);
// 验证addr的地址是否合法
if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
if verify_area(virt_addr, addrlen as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
@ -776,11 +783,13 @@ impl Syscall {
let flags = args[3] as u32;
let addr = args[4] as *const SockAddr;
let addrlen = args[5] as usize;
let virt_buf = VirtAddr::new(buf as usize);
let virt_addr = VirtAddr::new(addr as usize);
// 验证buf的地址是否合法
if unsafe { verify_area(buf as u64, len as u64) } == false {
if verify_area(virt_buf, len as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
} else if verify_area(virt_addr, addrlen as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
@ -795,25 +804,23 @@ impl Syscall {
let flags = args[3] as u32;
let addr = args[4] as *mut SockAddr;
let addrlen = args[5] as *mut usize;
let virt_buf = VirtAddr::new(buf as usize);
let virt_addrlen = VirtAddr::new(addrlen as usize);
let virt_addr = VirtAddr::new(addr as usize);
let security_check = || {
// 验证buf的地址是否合法
if unsafe { verify_area(buf as u64, len as u64) } == false {
if verify_area(virt_buf, len as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
// 验证addrlen的地址是否合法
if unsafe { verify_area(addrlen as u64, core::mem::size_of::<u32>() as u64) }
== false
{
if verify_area(virt_addrlen, core::mem::size_of::<u32>() as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
if unsafe { verify_area(addr as u64, core::mem::size_of::<SockAddr>() as u64) }
== false
{
if verify_area(virt_addr, core::mem::size_of::<SockAddr>() as usize).is_err() {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
@ -831,14 +838,14 @@ impl Syscall {
SYS_RECVMSG => {
let msg = args[1] as *mut crate::net::syscall::MsgHdr;
let flags = args[2] as u32;
let virt_msg = VirtAddr::new(msg as usize);
let security_check = || {
// 验证msg的地址是否合法
if unsafe {
verify_area(
msg as u64,
core::mem::size_of::<crate::net::syscall::MsgHdr>() as u64,
)
} == false
if verify_area(
virt_msg,
core::mem::size_of::<crate::net::syscall::MsgHdr>() as usize,
)
.is_err()
{
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
@ -867,19 +874,19 @@ impl Syscall {
SYS_GETTIMEOFDAY => {
let timeval = args[0] as *mut PosixTimeval;
let timezone_ptr = args[1] as *mut PosixTimeZone;
let virt_timeval = VirtAddr::new(timeval as usize);
let virt_timezone_ptr = VirtAddr::new(timezone_ptr as usize);
let security_check = || {
if unsafe {
verify_area(timeval as u64, core::mem::size_of::<PosixTimeval>() as u64)
} == false
if verify_area(virt_timeval, core::mem::size_of::<PosixTimeval>() as usize)
.is_err()
{
return Err(SystemError::EFAULT);
}
if unsafe {
verify_area(
timezone_ptr as u64,
core::mem::size_of::<PosixTimeZone>() as u64,
)
} == false
if verify_area(
virt_timezone_ptr,
core::mem::size_of::<PosixTimeZone>() as usize,
)
.is_err()
{
return Err(SystemError::EFAULT);
}
@ -898,7 +905,8 @@ impl Syscall {
}
SYS_MMAP => {
let len = page_align_up(args[1]);
if unsafe { !verify_area(args[0] as u64, len as u64) } {
let virt_addr = VirtAddr::new(args[0] as usize);
if verify_area(virt_addr, len as usize).is_err() {
Err(SystemError::EFAULT)
} else {
Self::mmap(
@ -932,6 +940,18 @@ impl Syscall {
}
}
SYS_FSTAT => {
let fd = args[0] as i32;
let kstat = args[1] as *mut PosixKstat;
let vaddr = VirtAddr::new(kstat as usize);
// FIXME 由于c中的verify_area与rust中的verify_area重名所以在引入时加了前缀区分
// TODO 应该将用了c版本的verify_area都改为rust的verify_area
match verify_area(vaddr, core::mem::size_of::<PosixKstat>()) {
Ok(_) => Self::fstat(fd, kstat),
Err(e) => Err(e),
}
}
_ => panic!("Unsupported syscall ID: {}", syscall_num),
};

View File

@ -40,20 +40,23 @@
#define SYS_DUP2 29
#define SYS_SOCKET 30 // 创建一个socket
#define SYS_SETSOCKOPT 31 // 设置socket的选项
#define SYS_GETSOCKOPT 32 // 获取socket的选项
#define SYS_CONNECT 33 // 连接到一个socket
#define SYS_BIND 34 // 绑定一个socket
#define SYS_SENDTO 35 // 向一个socket发送数据
#define SYS_RECVFROM 36 // 从一个socket接收数据
#define SYS_RECVMSG 37 // 从一个socket接收消息
#define SYS_LISTEN 38 // 监听一个socket
#define SYS_SHUTDOWN 39 // 关闭socket
#define SYS_ACCEPT 40 // 接受一个socket连接
#define SYS_SETSOCKOPT 31 // 设置socket的选项
#define SYS_GETSOCKOPT 32 // 获取socket的选项
#define SYS_CONNECT 33 // 连接到一个socket
#define SYS_BIND 34 // 绑定一个socket
#define SYS_SENDTO 35 // 向一个socket发送数据
#define SYS_RECVFROM 36 // 从一个socket接收数据
#define SYS_RECVMSG 37 // 从一个socket接收消息
#define SYS_LISTEN 38 // 监听一个socket
#define SYS_SHUTDOWN 39 // 关闭socket
#define SYS_ACCEPT 40 // 接受一个socket连接
#define SYS_GETSOCKNAME 41 // 获取socket的名字
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
#define SYS_GETSOCKNAME 41 // 获取socket的名字
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
#define SYS_GETTIMEOFDAY 43 // 获取当前时间
#define SYS_MMAP 44 // 内存映射
#define SYS_MUNMAP 45 // 内存解除映射
#define SYS_MPROTECT 46 // 内存保护
#define SYS_FSTAT 47 // 根据文件描述符获取文件信息