mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
@ -1,5 +1,23 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, c_void, CStr},
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::{
|
||||
arch::cpu::cpu_reset,
|
||||
filesystem::vfs::{
|
||||
file::FileMode,
|
||||
syscall::{SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
|
||||
MAX_PATHLEN,
|
||||
},
|
||||
include::bindings::bindings::{mm_stat_t, pid_t, verify_area, PAGE_2M_SIZE, PAGE_4K_SIZE},
|
||||
io::SeekFrom, kinfo,
|
||||
net::syscall::SockAddr,
|
||||
time::TimeSpec,
|
||||
};
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, Eq, Clone)]
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
@ -285,3 +303,585 @@ impl SystemError {
|
||||
return -<Self as ToPrimitive>::to_i32(self).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// 定义系统调用号
|
||||
pub const SYS_PUT_STRING: usize = 1;
|
||||
pub const SYS_OPEN: usize = 2;
|
||||
pub const SYS_CLOSE: usize = 3;
|
||||
pub const SYS_READ: usize = 4;
|
||||
pub const SYS_WRITE: usize = 5;
|
||||
pub const SYS_LSEEK: usize = 6;
|
||||
pub const SYS_FORK: usize = 7;
|
||||
pub const SYS_VFORK: usize = 8;
|
||||
pub const SYS_BRK: usize = 9;
|
||||
pub const SYS_SBRK: usize = 10;
|
||||
|
||||
pub const SYS_REBOOT: usize = 11;
|
||||
pub const SYS_CHDIR: usize = 12;
|
||||
pub const SYS_GET_DENTS: usize = 13;
|
||||
pub const SYS_EXECVE: usize = 14;
|
||||
pub const SYS_WAIT4: usize = 15;
|
||||
pub const SYS_EXIT: usize = 16;
|
||||
pub const SYS_MKDIR: usize = 17;
|
||||
pub const SYS_NANOSLEEP: usize = 18;
|
||||
/// todo: 该系统调用与Linux不一致,将来需要删除该系统调用!!! 删的时候记得改C版本的libc
|
||||
pub const SYS_CLOCK: usize = 19;
|
||||
pub const SYS_PIPE: usize = 20;
|
||||
|
||||
/// todo: 该系统调用不是符合POSIX标准的,在将来需要删除!!!
|
||||
pub const SYS_MSTAT: usize = 21;
|
||||
pub const SYS_UNLINK_AT: usize = 22;
|
||||
pub const SYS_KILL: usize = 23;
|
||||
pub const SYS_SIGACTION: usize = 24;
|
||||
pub const SYS_RT_SIGRETURN: usize = 25;
|
||||
pub const SYS_GETPID: usize = 26;
|
||||
pub const SYS_SCHED: usize = 27;
|
||||
pub const SYS_DUP: usize = 28;
|
||||
pub const SYS_DUP2: usize = 29;
|
||||
pub const SYS_SOCKET: usize = 30;
|
||||
|
||||
pub const SYS_SETSOCKOPT: usize = 31;
|
||||
pub const SYS_GETSOCKOPT: usize = 32;
|
||||
pub const SYS_CONNECT: usize = 33;
|
||||
pub const SYS_BIND: usize = 34;
|
||||
pub const SYS_SENDTO: usize = 35;
|
||||
pub const SYS_RECVFROM: usize = 36;
|
||||
pub const SYS_RECVMSG: usize = 37;
|
||||
pub const SYS_LISTEN: usize = 38;
|
||||
pub const SYS_SHUTDOWN: usize = 39;
|
||||
pub const SYS_ACCEPT: usize = 40;
|
||||
|
||||
pub const SYS_GETSOCKNAME: usize = 41;
|
||||
pub const SYS_GETPEERNAME: usize = 42;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Syscall;
|
||||
|
||||
extern "C" {
|
||||
fn do_put_string(s: *const u8, front_color: u32, back_color: u32) -> usize;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn syscall_init() -> i32 {
|
||||
kinfo!("Initializing syscall...");
|
||||
Syscall::init().expect("syscall init failed");
|
||||
kinfo!("Syscall init successfully!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
impl Syscall {
|
||||
/// 初始化系统调用
|
||||
pub fn init() -> Result<(), SystemError> {
|
||||
static INIT_FLAG: AtomicBool = AtomicBool::new(false);
|
||||
let prev = INIT_FLAG.swap(true, Ordering::SeqCst);
|
||||
if prev {
|
||||
panic!("Cannot initialize syscall more than once!");
|
||||
}
|
||||
return crate::arch::syscall::arch_syscall_init();
|
||||
}
|
||||
/// @brief 系统调用分发器,用于分发系统调用。
|
||||
///
|
||||
/// 这个函数内,需要根据系统调用号,调用对应的系统调用处理函数。
|
||||
/// 并且,对于用户态传入的指针参数,需要在本函数内进行越界检查,防止访问到内核空间。
|
||||
pub fn handle(syscall_num: usize, args: &[usize], from_user: bool) -> usize {
|
||||
let r = match syscall_num {
|
||||
SYS_PUT_STRING => {
|
||||
Self::put_string(args[0] as *const u8, args[1] as u32, args[2] as u32)
|
||||
}
|
||||
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 open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
|
||||
|
||||
Self::open(path, open_flags)
|
||||
};
|
||||
// kdebug!("open: {:?}, res: {:?}", path, res);
|
||||
res
|
||||
}
|
||||
SYS_CLOSE => {
|
||||
let fd = args[0];
|
||||
Self::close(fd)
|
||||
}
|
||||
SYS_READ => {
|
||||
let fd = args[0] as i32;
|
||||
let buf_vaddr = args[1];
|
||||
let len = args[2];
|
||||
|
||||
// 判断缓冲区是否来自用户态,进行权限校验
|
||||
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
|
||||
// 来自用户态,而buffer在内核态,这样的操作不被允许
|
||||
Err(SystemError::EPERM)
|
||||
} else {
|
||||
let buf: &mut [u8] = unsafe {
|
||||
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
|
||||
};
|
||||
Self::read(fd, buf)
|
||||
};
|
||||
|
||||
res
|
||||
}
|
||||
SYS_WRITE => {
|
||||
let fd = args[0] as i32;
|
||||
let buf_vaddr = args[1];
|
||||
let len = args[2];
|
||||
|
||||
// 判断缓冲区是否来自用户态,进行权限校验
|
||||
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
|
||||
// 来自用户态,而buffer在内核态,这样的操作不被允许
|
||||
Err(SystemError::EPERM)
|
||||
} else {
|
||||
let buf: &[u8] = unsafe {
|
||||
core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *const u8, len)
|
||||
};
|
||||
Self::write(fd, buf)
|
||||
};
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
SYS_LSEEK => {
|
||||
let fd = args[0] as i32;
|
||||
let offset = args[1] as i64;
|
||||
let whence = args[2] as u32;
|
||||
|
||||
let w = match whence {
|
||||
SEEK_SET => Ok(SeekFrom::SeekSet(offset)),
|
||||
SEEK_CUR => Ok(SeekFrom::SeekCurrent(offset)),
|
||||
SEEK_END => Ok(SeekFrom::SeekEnd(offset)),
|
||||
SEEK_MAX => Ok(SeekFrom::SeekEnd(0)),
|
||||
_ => Err(SystemError::EINVAL),
|
||||
};
|
||||
|
||||
let res = if w.is_err() {
|
||||
Err(w.unwrap_err())
|
||||
} else {
|
||||
let w = w.unwrap();
|
||||
Self::lseek(fd, w)
|
||||
};
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
SYS_BRK => {
|
||||
let new_brk = args[0];
|
||||
Self::brk(new_brk)
|
||||
}
|
||||
|
||||
SYS_SBRK => {
|
||||
let increment = args[0] as isize;
|
||||
Self::sbrk(increment)
|
||||
}
|
||||
|
||||
SYS_REBOOT => Self::reboot(),
|
||||
|
||||
SYS_CHDIR => {
|
||||
// Closure for checking arguments
|
||||
let chdir_check = |arg0: usize| {
|
||||
if arg0 == 0 {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
let path_ptr = arg0 as *const c_char;
|
||||
// 权限校验
|
||||
if path_ptr.is_null()
|
||||
|| (from_user
|
||||
&& unsafe { !verify_area(path_ptr as u64, PAGE_2M_SIZE as u64) })
|
||||
{
|
||||
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() > PAGE_4K_SIZE as usize {
|
||||
return Err(SystemError::ENAMETOOLONG);
|
||||
}
|
||||
|
||||
return Ok(dest_path);
|
||||
};
|
||||
|
||||
let r: Result<&str, SystemError> = chdir_check(args[0]);
|
||||
if r.is_err() {
|
||||
Err(r.unwrap_err())
|
||||
} else {
|
||||
Self::chdir(r.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
SYS_GET_DENTS => {
|
||||
let fd = args[0] as i32;
|
||||
let buf_vaddr = args[1];
|
||||
let len = args[2];
|
||||
|
||||
// 判断缓冲区是否来自用户态,进行权限校验
|
||||
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
|
||||
// 来自用户态,而buffer在内核态,这样的操作不被允许
|
||||
Err(SystemError::EPERM)
|
||||
} else if buf_vaddr == 0 {
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
let buf: &mut [u8] = unsafe {
|
||||
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
|
||||
};
|
||||
Self::getdents(fd, buf)
|
||||
};
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
SYS_EXECVE => {
|
||||
let path_ptr = args[0];
|
||||
let argv_ptr = args[1];
|
||||
let env_ptr = args[2];
|
||||
|
||||
// 权限校验
|
||||
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) }
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::execve(
|
||||
path_ptr as *const c_void,
|
||||
argv_ptr as *const *const c_void,
|
||||
env_ptr as *const *const c_void,
|
||||
)
|
||||
}
|
||||
}
|
||||
SYS_WAIT4 => {
|
||||
let pid = args[0] as pid_t;
|
||||
let wstatus = args[1] as *mut c_int;
|
||||
let options = args[2] as c_int;
|
||||
let rusage = args[3] as *mut c_void;
|
||||
|
||||
// 权限校验
|
||||
// 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) })
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::wait4(pid, wstatus, options, rusage)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_EXIT => {
|
||||
let exit_code = args[0];
|
||||
Self::exit(exit_code)
|
||||
}
|
||||
SYS_MKDIR => {
|
||||
let path_ptr = args[0] as *const c_char;
|
||||
let mode = args[1];
|
||||
|
||||
let security_check = || {
|
||||
if path_ptr.is_null()
|
||||
|| (from_user
|
||||
&& unsafe { !verify_area(path_ptr as u64, PAGE_2M_SIZE as u64) })
|
||||
{
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
let path: &CStr = unsafe { CStr::from_ptr(path_ptr) };
|
||||
let path: &str = path.to_str().map_err(|_| SystemError::EINVAL)?.trim();
|
||||
|
||||
if path == "" {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
return Ok(path);
|
||||
};
|
||||
|
||||
let path = security_check();
|
||||
if path.is_err() {
|
||||
Err(path.unwrap_err())
|
||||
} else {
|
||||
Self::mkdir(path.unwrap(), mode)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_NANOSLEEP => {
|
||||
let req = args[0] as *const TimeSpec;
|
||||
let rem = args[1] as *mut TimeSpec;
|
||||
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)
|
||||
})
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::nanosleep(req, rem)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_CLOCK => Self::clock(),
|
||||
SYS_PIPE => {
|
||||
let pipefd = args[0] as *mut c_int;
|
||||
if from_user
|
||||
&& unsafe {
|
||||
!verify_area(pipefd as u64, core::mem::size_of::<[c_int; 2]>() as u64)
|
||||
}
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else if pipefd.is_null() {
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
let pipefd = unsafe { core::slice::from_raw_parts_mut(pipefd, 2) };
|
||||
Self::pipe(pipefd)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_MSTAT => {
|
||||
let dst = args[0] as *mut mm_stat_t;
|
||||
if from_user
|
||||
&& unsafe { !verify_area(dst as u64, core::mem::size_of::<mm_stat_t>() as u64) }
|
||||
{
|
||||
Err(SystemError::EFAULT)
|
||||
} else if dst.is_null() {
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::mstat(dst, from_user)
|
||||
}
|
||||
}
|
||||
SYS_UNLINK_AT => {
|
||||
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) } {
|
||||
Err(SystemError::EFAULT)
|
||||
} else if pathname.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 = get_path();
|
||||
if pathname.is_err() {
|
||||
Err(pathname.unwrap_err())
|
||||
} else {
|
||||
Self::unlinkat(dirfd, pathname.unwrap(), flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
SYS_KILL => {
|
||||
let pid = args[0] as pid_t;
|
||||
let sig = args[1] as c_int;
|
||||
|
||||
Self::kill(pid, sig)
|
||||
}
|
||||
|
||||
SYS_SIGACTION => {
|
||||
let sig = args[0] as c_int;
|
||||
let act = args[1];
|
||||
let old_act = args[2];
|
||||
Self::sigaction(sig, act, old_act, from_user)
|
||||
}
|
||||
|
||||
SYS_RT_SIGRETURN => {
|
||||
// 由于目前signal机制的实现,与x86_64强关联,因此暂时在arch/x86_64/syscall.rs中调用
|
||||
// todo: 未来需要将signal机制与平台解耦
|
||||
todo!()
|
||||
}
|
||||
|
||||
SYS_GETPID => Self::getpid(),
|
||||
|
||||
SYS_SCHED => Self::sched(from_user),
|
||||
SYS_DUP => {
|
||||
let oldfd: i32 = args[0] as c_int;
|
||||
Self::dup(oldfd)
|
||||
}
|
||||
SYS_DUP2 => {
|
||||
let oldfd: i32 = args[0] as c_int;
|
||||
let newfd: i32 = args[1] as c_int;
|
||||
Self::dup2(oldfd, newfd)
|
||||
}
|
||||
|
||||
SYS_SOCKET => Self::socket(args[0], args[1], args[2]),
|
||||
SYS_SETSOCKOPT => {
|
||||
let optval = args[3] as *const u8;
|
||||
let optlen = args[4] as usize;
|
||||
// 验证optval的地址是否合法
|
||||
if unsafe { verify_area(optval as u64, optlen as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
let data: &[u8] = unsafe { core::slice::from_raw_parts(optval, optlen) };
|
||||
Self::setsockopt(args[0], args[1], args[2], data)
|
||||
}
|
||||
}
|
||||
SYS_GETSOCKOPT => {
|
||||
let optval = args[3] as *mut u8;
|
||||
let optlen = args[4] as *mut usize;
|
||||
|
||||
let security_check = || {
|
||||
// 验证optval的地址是否合法
|
||||
if unsafe { verify_area(optval as u64, PAGE_4K_SIZE as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
// 验证optlen的地址是否合法
|
||||
if unsafe { verify_area(optlen as u64, core::mem::size_of::<u32>() as u64) }
|
||||
== false
|
||||
{
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
return Ok(());
|
||||
};
|
||||
let r = security_check();
|
||||
if r.is_err() {
|
||||
Err(r.unwrap_err())
|
||||
} else {
|
||||
Self::getsockopt(args[0], args[1], args[2], optval, optlen as *mut u32)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_CONNECT => {
|
||||
let addr = args[1] as *const SockAddr;
|
||||
let addrlen = args[2] as usize;
|
||||
// 验证addr的地址是否合法
|
||||
if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::connect(args[0], addr, addrlen)
|
||||
}
|
||||
}
|
||||
SYS_BIND => {
|
||||
let addr = args[1] as *const SockAddr;
|
||||
let addrlen = args[2] as usize;
|
||||
// 验证addr的地址是否合法
|
||||
if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::bind(args[0], addr, addrlen)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_SENDTO => {
|
||||
let buf = args[1] as *const u8;
|
||||
let len = args[2] as usize;
|
||||
let flags = args[3] as u32;
|
||||
let addr = args[4] as *const SockAddr;
|
||||
let addrlen = args[5] as usize;
|
||||
// 验证buf的地址是否合法
|
||||
if unsafe { verify_area(buf as u64, len as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
Err(SystemError::EFAULT)
|
||||
} else if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
let data: &[u8] = unsafe { core::slice::from_raw_parts(buf, len) };
|
||||
Self::sendto(args[0], data, flags, addr, addrlen)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_RECVFROM => {
|
||||
let buf = args[1] as *mut u8;
|
||||
let len = args[2] as usize;
|
||||
let flags = args[3] as u32;
|
||||
let addr = args[4] as *mut SockAddr;
|
||||
let addrlen = args[5] as *mut usize;
|
||||
|
||||
let security_check = || {
|
||||
// 验证buf的地址是否合法
|
||||
if unsafe { verify_area(buf as u64, len as u64) } == false {
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
// 验证addrlen的地址是否合法
|
||||
if unsafe { verify_area(addrlen as u64, core::mem::size_of::<u32>() as u64) }
|
||||
== false
|
||||
{
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
if unsafe { verify_area(addr as u64, core::mem::size_of::<SockAddr>() as u64) }
|
||||
== false
|
||||
{
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
return Ok(());
|
||||
};
|
||||
let r = security_check();
|
||||
if r.is_err() {
|
||||
Err(r.unwrap_err())
|
||||
} else {
|
||||
let buf = unsafe { core::slice::from_raw_parts_mut(buf, len) };
|
||||
Self::recvfrom(args[0], buf, flags, addr, addrlen as *mut u32)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_RECVMSG => {
|
||||
let msg = args[1] as *mut crate::net::syscall::MsgHdr;
|
||||
let flags = args[2] as u32;
|
||||
let security_check = || {
|
||||
// 验证msg的地址是否合法
|
||||
if unsafe {
|
||||
verify_area(
|
||||
msg as u64,
|
||||
core::mem::size_of::<crate::net::syscall::MsgHdr>() as u64,
|
||||
)
|
||||
} == false
|
||||
{
|
||||
// 地址空间超出了用户空间的范围,不合法
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
let msg = unsafe { msg.as_mut() }.ok_or(SystemError::EFAULT)?;
|
||||
return Ok(msg);
|
||||
};
|
||||
let r = security_check();
|
||||
if r.is_err() {
|
||||
Err(r.unwrap_err())
|
||||
} else {
|
||||
let msg = r.unwrap();
|
||||
Self::recvmsg(args[0], msg, flags)
|
||||
}
|
||||
}
|
||||
|
||||
SYS_LISTEN => Self::listen(args[0], args[1]),
|
||||
SYS_SHUTDOWN => Self::shutdown(args[0], args[1]),
|
||||
SYS_ACCEPT => Self::accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
|
||||
SYS_GETSOCKNAME => {
|
||||
Self::getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32)
|
||||
}
|
||||
SYS_GETPEERNAME => {
|
||||
Self::getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32)
|
||||
}
|
||||
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||
};
|
||||
|
||||
let r = r.unwrap_or_else(|e| e.to_posix_errno() as usize);
|
||||
return r;
|
||||
}
|
||||
|
||||
pub fn put_string(
|
||||
s: *const u8,
|
||||
front_color: u32,
|
||||
back_color: u32,
|
||||
) -> Result<usize, SystemError> {
|
||||
return Ok(unsafe { do_put_string(s, front_color, back_color) });
|
||||
}
|
||||
|
||||
pub fn reboot() -> Result<usize, SystemError> {
|
||||
cpu_reset();
|
||||
}
|
||||
}
|
||||
|
@ -13,91 +13,6 @@
|
||||
// 导出系统调用入口函数,定义在entry.S中
|
||||
extern void syscall_int(void);
|
||||
|
||||
extern uint64_t sys_clock(struct pt_regs *regs);
|
||||
extern uint64_t sys_mstat(struct pt_regs *regs);
|
||||
extern uint64_t sys_open(struct pt_regs *regs);
|
||||
extern uint64_t sys_unlink_at(struct pt_regs *regs);
|
||||
extern uint64_t sys_kill(struct pt_regs *regs);
|
||||
extern uint64_t sys_sigaction(struct pt_regs *regs);
|
||||
extern uint64_t sys_rt_sigreturn(struct pt_regs *regs);
|
||||
extern uint64_t sys_getpid(struct pt_regs *regs);
|
||||
extern uint64_t sys_sched(struct pt_regs *regs);
|
||||
extern int sys_dup(int oldfd);
|
||||
extern int sys_dup2(int oldfd, int newfd);
|
||||
extern uint64_t sys_socket(struct pt_regs *regs);
|
||||
extern uint64_t sys_setsockopt(struct pt_regs *regs);
|
||||
extern uint64_t sys_getsockopt(struct pt_regs *regs);
|
||||
extern uint64_t sys_connect(struct pt_regs *regs);
|
||||
extern uint64_t sys_bind(struct pt_regs *regs);
|
||||
extern uint64_t sys_sendto(struct pt_regs *regs);
|
||||
extern uint64_t sys_recvfrom(struct pt_regs *regs);
|
||||
extern uint64_t sys_recvmsg(struct pt_regs *regs);
|
||||
extern uint64_t sys_listen(struct pt_regs *regs);
|
||||
extern uint64_t sys_shutdown(struct pt_regs *regs);
|
||||
extern uint64_t sys_accept(struct pt_regs *regs);
|
||||
extern uint64_t sys_getsockname(struct pt_regs *regs);
|
||||
extern uint64_t sys_getpeername(struct pt_regs *regs);
|
||||
extern uint64_t sys_pipe(struct pt_regs *regs);
|
||||
extern uint64_t sys_mkdir(struct pt_regs *regs);
|
||||
/**
|
||||
* @brief 关闭文件系统调用
|
||||
*
|
||||
* @param fd_num 文件描述符号
|
||||
*
|
||||
* @param regs
|
||||
* @return uint64_t
|
||||
*/
|
||||
extern uint64_t sys_close(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 从文件中读取数据
|
||||
*
|
||||
* @param fd_num regs->r8 文件描述符号
|
||||
* @param buf regs->r9 输出缓冲区
|
||||
* @param count regs->r10 要读取的字节数
|
||||
*
|
||||
* @return uint64_t
|
||||
*/
|
||||
extern uint64_t sys_read(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 向文件写入数据
|
||||
*
|
||||
* @param fd_num regs->r8 文件描述符号
|
||||
* @param buf regs->r9 输入缓冲区
|
||||
* @param count regs->r10 要写入的字节数
|
||||
*
|
||||
* @return uint64_t
|
||||
*/
|
||||
extern uint64_t sys_write(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 调整文件的访问位置
|
||||
*
|
||||
* @param fd_num 文件描述符号
|
||||
* @param offset 偏移量
|
||||
* @param whence 调整模式
|
||||
* @return uint64_t 调整结束后的文件访问位置
|
||||
*/
|
||||
extern uint64_t sys_lseek(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 导出系统调用处理函数的符号
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 系统调用不存在时的处理函数
|
||||
*
|
||||
* @param regs 进程3特权级下的寄存器
|
||||
* @return ul
|
||||
*/
|
||||
ul system_call_not_exists(struct pt_regs *regs)
|
||||
{
|
||||
kerror("System call [ ID #%d ] not exists.", regs->rax);
|
||||
return ESYSCALL_NOT_EXISTS;
|
||||
} // 取消前述宏定义
|
||||
|
||||
/**
|
||||
* @brief 重新定义为:把系统调用函数加入系统调用表
|
||||
* @param syscall_num 系统调用号
|
||||
@ -105,17 +20,6 @@ ul system_call_not_exists(struct pt_regs *regs)
|
||||
*/
|
||||
#define SYSCALL_COMMON(syscall_num, symbol) [syscall_num] = symbol,
|
||||
|
||||
/**
|
||||
* @brief 初始化系统调用模块
|
||||
*
|
||||
*/
|
||||
void syscall_init()
|
||||
{
|
||||
kinfo("Initializing syscall...");
|
||||
|
||||
set_system_trap_gate(0x80, 0, syscall_int); // 系统调用门
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过中断进入系统调用
|
||||
*
|
||||
@ -162,36 +66,23 @@ long enter_syscall_int(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg
|
||||
* @param arg2 背景色
|
||||
* @return ul 返回值
|
||||
*/
|
||||
ul sys_put_string(struct pt_regs *regs)
|
||||
ul do_put_string(char *s, uint32_t front_color, uint32_t background_color)
|
||||
{
|
||||
|
||||
printk_color(regs->r9, regs->r10, (char *)regs->r8);
|
||||
// printk_color(BLACK, WHITE, (char *)regs->r8);
|
||||
|
||||
printk_color(front_color, background_color, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t sys_fork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(regs, 0, regs->rsp, 0);
|
||||
}
|
||||
uint64_t sys_vfork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(regs, CLONE_VM | CLONE_FS | CLONE_SIGNAL, regs->rsp, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将堆内存调整为arg0
|
||||
*
|
||||
* @param arg0 新的堆区域的结束地址
|
||||
* arg0=-1 ===> 返回堆区域的起始地址
|
||||
* arg0=-2 ===> 返回堆区域的结束地址
|
||||
* @return uint64_t 错误码
|
||||
*
|
||||
*/
|
||||
uint64_t sys_brk(struct pt_regs *regs)
|
||||
uint64_t sys_do_brk(uint64_t newaddr)
|
||||
{
|
||||
uint64_t new_brk = PAGE_2M_ALIGN(regs->r8);
|
||||
uint64_t new_brk = PAGE_2M_ALIGN(newaddr);
|
||||
// kdebug("sys_brk input= %#010lx , new_brk= %#010lx bytes current_pcb->mm->brk_start=%#018lx
|
||||
// current->end_brk=%#018lx", regs->r8, new_brk, current_pcb->mm->brk_start, current_pcb->mm->brk_end);
|
||||
struct mm_struct *mm = current_pcb->mm;
|
||||
@ -216,16 +107,16 @@ uint64_t sys_brk(struct pt_regs *regs)
|
||||
/**
|
||||
* @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程)
|
||||
*
|
||||
* @param arg0 offset偏移量
|
||||
* @param incr offset偏移量
|
||||
* @return uint64_t the previous program break
|
||||
*/
|
||||
uint64_t sys_sbrk(struct pt_regs *regs)
|
||||
uint64_t sys_do_sbrk(int64_t incr)
|
||||
{
|
||||
uint64_t retval = current_pcb->mm->brk_end;
|
||||
if ((int64_t)regs->r8 > 0)
|
||||
if ((int64_t)incr > 0)
|
||||
{
|
||||
|
||||
uint64_t new_brk = PAGE_2M_ALIGN(retval + regs->r8);
|
||||
uint64_t new_brk = PAGE_2M_ALIGN(retval + incr);
|
||||
if (new_brk > current_pcb->addr_limit) // 堆地址空间超过限制
|
||||
{
|
||||
kdebug("exceed mem limit, new_brk = %#018lx", new_brk);
|
||||
@ -234,58 +125,16 @@ uint64_t sys_sbrk(struct pt_regs *regs)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((__int128_t)current_pcb->mm->brk_end + (__int128_t)regs->r8 < current_pcb->mm->brk_start)
|
||||
if ((__int128_t)current_pcb->mm->brk_end + (__int128_t)incr < current_pcb->mm->brk_start)
|
||||
return retval;
|
||||
}
|
||||
// kdebug("do brk");
|
||||
uint64_t new_brk = mm_do_brk(current_pcb->mm->brk_end, (int64_t)regs->r8); // 调整堆内存空间
|
||||
uint64_t new_brk = mm_do_brk(current_pcb->mm->brk_end, (int64_t)incr); // 调整堆内存空间
|
||||
// kdebug("do brk done, new_brk = %#018lx", new_brk);
|
||||
current_pcb->mm->brk_end = new_brk;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重启计算机
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
uint64_t sys_reboot(struct pt_regs *regs)
|
||||
{
|
||||
// 重启计算机
|
||||
io_out8(0x64, 0xfe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 切换工作目录
|
||||
*
|
||||
* @param dest_path 目标路径
|
||||
* @return
|
||||
+--------------+------------------------+
|
||||
| 返回码 | 描述 |
|
||||
+--------------+------------------------+
|
||||
| 0 | 成功 |
|
||||
| EACCESS | 权限不足 |
|
||||
| ELOOP | 解析path时遇到路径循环 |
|
||||
| ENAMETOOLONG | 路径名过长 |
|
||||
| ENOENT | 目标文件或目录不存在 |
|
||||
| ENODIR | 检索期间发现非目录项 |
|
||||
| ENOMEM | 系统内存不足 |
|
||||
| EFAULT | 错误的地址 |
|
||||
| ENAMETOOLONG | 路径过长 |
|
||||
+--------------+------------------------+
|
||||
*/
|
||||
extern uint64_t sys_chdir(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 获取目录中的数据
|
||||
*
|
||||
* @param fd 文件描述符号
|
||||
* @return uint64_t dirent的总大小
|
||||
*/
|
||||
extern uint64_t sys_getdents(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 执行新的程序
|
||||
*
|
||||
@ -293,12 +142,9 @@ extern uint64_t sys_getdents(struct pt_regs *regs);
|
||||
* @param argv(r9寄存器) 参数列表
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t sys_execve(struct pt_regs *regs)
|
||||
uint64_t c_sys_execve(char *user_path, char **argv, char **envp, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
char *user_path = (char *)regs->r8;
|
||||
char **argv = (char **)regs->r9;
|
||||
|
||||
int path_len = strnlen_user(user_path, PAGE_4K_SIZE);
|
||||
|
||||
if (path_len >= PAGE_4K_SIZE)
|
||||
@ -332,12 +178,8 @@ uint64_t sys_execve(struct pt_regs *regs)
|
||||
* @param rusage
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t sys_wait4(struct pt_regs *regs)
|
||||
uint64_t c_sys_wait4(pid_t pid, int *status, int options, void *rusage)
|
||||
{
|
||||
uint64_t pid = regs->r8;
|
||||
int *status = (int *)regs->r9;
|
||||
int options = regs->r10;
|
||||
void *rusage = (void *)regs->r11;
|
||||
|
||||
struct process_control_block *proc = NULL;
|
||||
struct process_control_block *child_proc = NULL;
|
||||
@ -369,82 +211,3 @@ uint64_t sys_wait4(struct pt_regs *regs)
|
||||
process_release_pcb(child_proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 进程退出
|
||||
*
|
||||
* @param exit_code 退出返回码
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t sys_exit(struct pt_regs *regs)
|
||||
{
|
||||
return process_do_exit(regs->r8);
|
||||
}
|
||||
|
||||
uint64_t sys_nanosleep(struct pt_regs *regs)
|
||||
{
|
||||
const struct timespec *rqtp = (const struct timespec *)regs->r8;
|
||||
struct timespec *rmtp = (struct timespec *)regs->r9;
|
||||
|
||||
return rs_nanosleep(rqtp, rmtp);
|
||||
}
|
||||
|
||||
ul sys_ahci_end_req(struct pt_regs *regs)
|
||||
{
|
||||
// ahci_end_request();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 系统调用的内核入口程序
|
||||
void do_syscall_int(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
ul ret = system_call_table[regs->rax](regs);
|
||||
regs->rax = ret; // 返回码
|
||||
}
|
||||
|
||||
system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
|
||||
[0] = system_call_not_exists,
|
||||
[1] = sys_put_string,
|
||||
[2] = sys_open,
|
||||
[3] = sys_close,
|
||||
[4] = sys_read,
|
||||
[5] = sys_write,
|
||||
[6] = sys_lseek,
|
||||
[7] = sys_fork,
|
||||
[8] = sys_vfork,
|
||||
[9] = sys_brk,
|
||||
[10] = sys_sbrk,
|
||||
[11] = sys_reboot,
|
||||
[12] = sys_chdir,
|
||||
[13] = sys_getdents,
|
||||
[14] = sys_execve,
|
||||
[15] = sys_wait4,
|
||||
[16] = sys_exit,
|
||||
[17] = sys_mkdir,
|
||||
[18] = sys_nanosleep,
|
||||
[19] = sys_clock,
|
||||
[20] = sys_pipe,
|
||||
[21] = sys_mstat,
|
||||
[22] = sys_unlink_at,
|
||||
[23] = sys_kill,
|
||||
[24] = sys_sigaction,
|
||||
[25] = sys_rt_sigreturn,
|
||||
[26] = sys_getpid,
|
||||
[27] = sys_sched,
|
||||
[28] = sys_dup,
|
||||
[29] = sys_dup2,
|
||||
[30] = sys_socket,
|
||||
[31] = sys_setsockopt,
|
||||
[32] = sys_getsockopt,
|
||||
[33] = sys_connect,
|
||||
[34] = sys_bind,
|
||||
[35] = sys_sendto,
|
||||
[36] = sys_recvfrom,
|
||||
[37] = sys_recvmsg,
|
||||
[38] = sys_listen,
|
||||
[39] = sys_shutdown,
|
||||
[40] = sys_accept,
|
||||
[41] = sys_getsockname,
|
||||
[42] = sys_getpeername,
|
||||
[43 ... 255] = system_call_not_exists,
|
||||
};
|
||||
|
@ -5,25 +5,11 @@
|
||||
#include <common/unistd.h>
|
||||
#include <process/ptrace.h>
|
||||
|
||||
// 定义最大系统调用数量
|
||||
#define MAX_SYSTEM_CALL_NUM 256
|
||||
|
||||
#define ESYSCALL_NOT_EXISTS 1
|
||||
|
||||
typedef unsigned long (*system_call_t)(struct pt_regs *regs);
|
||||
|
||||
extern system_call_t system_call_table[MAX_SYSTEM_CALL_NUM];
|
||||
|
||||
// 判断系统调用是否来自用户态
|
||||
#define SYSCALL_FROM_USER(regs) (user_mode(regs))
|
||||
// 判断系统调用是否来自内核态
|
||||
#define SYSCALL_FROM_KERNEL(regs) (!SYSCALL_FROM_USER(regs))
|
||||
|
||||
/**
|
||||
* @brief 初始化系统调用模块
|
||||
*
|
||||
*/
|
||||
void syscall_init();
|
||||
extern int syscall_init();
|
||||
|
||||
/**
|
||||
* @brief 用户态系统调用入口函数
|
||||
@ -33,57 +19,3 @@ void syscall_init();
|
||||
*/
|
||||
long enter_syscall_int(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg4, ul arg5, ul arg6, ul arg7);
|
||||
|
||||
/**
|
||||
* @brief 系统调用不存在时的处理函数
|
||||
*
|
||||
* @param regs 进程3特权级下的寄存器
|
||||
* @return ul
|
||||
*/
|
||||
ul system_call_not_exists(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 打印字符串的系统调用
|
||||
*
|
||||
* 当arg1和arg2均为0时,打印黑底白字,否则按照指定的前景色和背景色来打印
|
||||
*
|
||||
* @param regs 寄存器
|
||||
* @param arg0 要打印的字符串
|
||||
* @param arg1 前景色
|
||||
* @param arg2 背景色
|
||||
* @return ul 返回值
|
||||
*/
|
||||
ul sys_printf(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 将堆内存调整为arg0
|
||||
*
|
||||
* @param arg0 新的堆区域的结束地址
|
||||
* arg0=0 ===> 返回堆区域的起始地址
|
||||
* arg0=-1 ===> 返回堆区域的结束地址
|
||||
* @return uint64_t 错误码
|
||||
*
|
||||
*/
|
||||
uint64_t sys_brk(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程)
|
||||
*
|
||||
* @param arg0 offset偏移量
|
||||
* @return uint64_t the previous program break
|
||||
*/
|
||||
uint64_t sys_sbrk(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 创建文件夹
|
||||
* 在VFS.c中实现
|
||||
* @param path(r8) 路径
|
||||
* @param mode(r9) 模式
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t sys_mkdir(struct pt_regs *regs);
|
||||
|
||||
|
||||
ul sys_ahci_end_req(struct pt_regs *regs);
|
||||
|
||||
// 系统调用的内核入口程序
|
||||
void do_syscall_int(struct pt_regs *regs, unsigned long error_code);
|
||||
|
@ -1,11 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* 系统调用说明
|
||||
* 1 printf
|
||||
* 请注意!!!由于系统调用模块已经使用Rust重构,当修改系统调用号时,需要同时修改syscall_num.h和syscall/mod.rs中的系统调用号
|
||||
* 并且以syscall/mod.rs中的为准!!!
|
||||
*
|
||||
*
|
||||
* 255 AHCI end_request
|
||||
* TODO:在完成系统的重构后,删除syscall_num.h
|
||||
*
|
||||
*/
|
||||
|
||||
@ -43,17 +41,15 @@
|
||||
#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_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用
|
Reference in New Issue
Block a user