mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
parent
9550910ae1
commit
be63f3b2b6
1
.vscode/c_cpp_properties.json
vendored
1
.vscode/c_cpp_properties.json
vendored
@ -4,6 +4,7 @@
|
||||
"name": "DragonOS",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/bin/sysroot/usr/include",
|
||||
"${workspaceFolder}/user/libs/libc/src/include",
|
||||
"${workspaceFolder}/user/libs/libc/src/include/export"
|
||||
],
|
||||
|
@ -5,3 +5,4 @@ pub mod procfs;
|
||||
pub mod ramfs;
|
||||
pub mod sysfs;
|
||||
pub mod vfs;
|
||||
pub mod syscall;
|
167
kernel/src/filesystem/syscall.rs
Normal file
167
kernel/src/filesystem/syscall.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
if verify_area(
|
||||
virt_msg,
|
||||
core::mem::size_of::<crate::net::syscall::MsgHdr>() as usize,
|
||||
)
|
||||
} == false
|
||||
.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,
|
||||
if verify_area(
|
||||
virt_timezone_ptr,
|
||||
core::mem::size_of::<PosixTimeZone>() as usize,
|
||||
)
|
||||
} == false
|
||||
.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),
|
||||
};
|
||||
|
||||
|
@ -57,3 +57,6 @@
|
||||
#define SYS_MMAP 44 // 内存映射
|
||||
#define SYS_MUNMAP 45 // 内存解除映射
|
||||
#define SYS_MPROTECT 46 // 内存保护
|
||||
|
||||
#define SYS_FSTAT 47 // 根据文件描述符获取文件信息
|
||||
|
||||
|
26
user/apps/test_fstat/Makefile
Normal file
26
user/apps/test_fstat/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
CC=$(DragonOS_GCC)/x86_64-elf-gcc
|
||||
LD=ld
|
||||
OBJCOPY=objcopy
|
||||
# 修改这里,把它改为你的relibc的sysroot路径
|
||||
RELIBC_OPT=$(DADK_BUILD_CACHE_DIR_RELIBC_0_1_0)
|
||||
CFLAGS=-I $(RELIBC_OPT)/include -D__dragonos__
|
||||
|
||||
tmp_output_dir=$(ROOT_PATH)/bin/tmp/user
|
||||
output_dir=$(DADK_BUILD_CACHE_DIR_TEST_FSTAT_0_1_0)
|
||||
|
||||
LIBC_OBJS:=$(shell find $(RELIBC_OPT)/lib -name "*.o" | sort )
|
||||
LIBC_OBJS+=$(RELIBC_OPT)/lib/libc.a
|
||||
|
||||
all: main.o
|
||||
mkdir -p $(tmp_output_dir)
|
||||
|
||||
$(LD) -b elf64-x86-64 -z muldefs -o $(tmp_output_dir)/test_fstat $(shell find . -name "*.o") $(LIBC_OBJS) -T link.lds
|
||||
|
||||
$(OBJCOPY) -I elf64-x86-64 -R ".eh_frame" -R ".comment" -O elf64-x86-64 $(tmp_output_dir)/test_fstat $(output_dir)/test_fstat.elf
|
||||
|
||||
mv $(output_dir)/test_fstat.elf $(output_dir)/test_fstat
|
||||
main.o: main.c
|
||||
$(CC) $(CFLAGS) -c main.c -o main.o
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
239
user/apps/test_fstat/link.lds
Normal file
239
user/apps/test_fstat/link.lds
Normal file
@ -0,0 +1,239 @@
|
||||
/* Script for -z combreloc */
|
||||
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||
Copying and distribution of this script, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. */
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
|
||||
"elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.dyn :
|
||||
{
|
||||
*(.rela.init)
|
||||
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||
*(.rela.fini)
|
||||
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||
*(.rela.ctors)
|
||||
*(.rela.dtors)
|
||||
*(.rela.got)
|
||||
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||
*(.rela.ifunc)
|
||||
}
|
||||
.rela.plt :
|
||||
{
|
||||
*(.rela.plt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||
*(.rela.iplt)
|
||||
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||
}
|
||||
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}
|
||||
.plt : { *(.plt) *(.iplt) }
|
||||
.plt.got : { *(.plt.got) }
|
||||
.plt.sec : { *(.plt.sec) }
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf.em. */
|
||||
*(.gnu.warning)
|
||||
}
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
}
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||
/* Exception handling */
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.tdata :
|
||||
{
|
||||
PROVIDE_HIDDEN (__tdata_start = .);
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
}
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.got : { *(.got) *(.igot) }
|
||||
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||
.data :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
_edata = .; PROVIDE (edata = .);
|
||||
. = .;
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections.
|
||||
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||
pad the .data section. */
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
.lbss :
|
||||
{
|
||||
*(.dynlbss)
|
||||
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||
*(LARGE_COMMON)
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||
}
|
||||
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||
{
|
||||
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
_end = .; PROVIDE (end = .);
|
||||
. = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* DWARF 3 */
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
/* DWARF Extension. */
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
|
||||
}
|
35
user/apps/test_fstat/main.c
Normal file
35
user/apps/test_fstat/main.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
int main()
|
||||
{
|
||||
|
||||
int fd = open("/bin/about.elf", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
printf("fd = %d\n", fd);
|
||||
struct stat *st = (struct stat *)malloc(sizeof(struct stat));
|
||||
fstat(fd, st);
|
||||
printf("stat size = %d\n", sizeof(struct stat));
|
||||
// FIXME 打印数据时内存出错
|
||||
printf("====================\n");
|
||||
printf("st address: %#018lx\n", st);
|
||||
printf("st_dev = %d\n", (*st).st_dev);
|
||||
printf("st_ino = %d\n", (*st).st_ino);
|
||||
printf("st_mode = %d\n", (*st).st_mode);
|
||||
printf("st_nlink = %d\n", (*st).st_nlink);
|
||||
printf("st_uid = %d\n", (*st).st_uid);
|
||||
printf("st_gid = %d\n", (*st).st_gid);
|
||||
printf("st_rdev = %d\n", (*st).st_rdev);
|
||||
printf("st_size = %d\n", (*st).st_size);
|
||||
printf("st_blksize = %d\n", (*st).st_blksize);
|
||||
printf("st_blocks = %d\n", (*st).st_blocks);
|
||||
printf("st_atim.sec= %d\tst_atim.nsec= %d\n", (*st).st_atim.tv_sec, (*st).st_atim.tv_nsec);
|
||||
printf("st_mtim.sec= %d\tst_mtim.nsec= %d\n", (*st).st_mtim.tv_sec, (*st).st_mtim.tv_nsec);
|
||||
printf("st_ctim.sec= %d\tst_ctim.nsec= %d\n", (*st).st_ctim.tv_sec, (*st).st_ctim.tv_nsec);
|
||||
|
||||
return 0;
|
||||
}
|
33
user/dadk/config/test_fstat-0.1.0.dadk
Normal file
33
user/dadk/config/test_fstat-0.1.0.dadk
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "test_fstat",
|
||||
"version": "0.1.0",
|
||||
"description": "一个用来测试fstat能够正常运行的app",
|
||||
"task_type": {
|
||||
"BuildFromSource": {
|
||||
"Local": {
|
||||
"path": "apps/test_fstat"
|
||||
}
|
||||
}
|
||||
},
|
||||
"depends": [
|
||||
{
|
||||
"name": "relibc",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"build_command": "make"
|
||||
},
|
||||
"install": {
|
||||
"in_dragonos_path": "/bin"
|
||||
},
|
||||
"clean": {
|
||||
"clean_command": "make clean"
|
||||
},
|
||||
"envs": [
|
||||
{
|
||||
"key": "__dragonos__",
|
||||
"value": "__dragonos__"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user