mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
@ -6,30 +6,27 @@ use core::{
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::{
|
||||
arch::{cpu::cpu_reset, MMArch},
|
||||
arch::cpu::cpu_reset,
|
||||
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::{mm_stat_t, pid_t, verify_area, PAGE_2M_SIZE, PAGE_4K_SIZE},
|
||||
io::SeekFrom,
|
||||
kinfo,
|
||||
libs::align::page_align_up,
|
||||
mm::{MemoryManagementArch, VirtAddr},
|
||||
net::syscall::SockAddr,
|
||||
time::{
|
||||
syscall::{PosixTimeZone, PosixTimeval},
|
||||
syscall::{PosixTimeZone, PosixTimeval, SYS_TIMEZONE},
|
||||
TimeSpec,
|
||||
},
|
||||
};
|
||||
|
||||
pub mod user_access;
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, Eq, Clone)]
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
pub enum SystemError {
|
||||
/// 操作不被允许 Operation not permitted.
|
||||
EPERM = 1,
|
||||
/// 没有指定的文件或目录 No such file or directory.
|
||||
ENOENT = 2,
|
||||
@ -334,8 +331,9 @@ pub const SYS_NANOSLEEP: usize = 18;
|
||||
/// todo: 该系统调用与Linux不一致,将来需要删除该系统调用!!! 删的时候记得改C版本的libc
|
||||
pub const SYS_CLOCK: usize = 19;
|
||||
pub const SYS_PIPE: usize = 20;
|
||||
/// 系统调用21曾经是SYS_MSTAT,但是现在已经废弃
|
||||
pub const __NOT_USED: usize = 21;
|
||||
|
||||
/// 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;
|
||||
@ -360,9 +358,6 @@ pub const SYS_ACCEPT: usize = 40;
|
||||
pub const SYS_GETSOCKNAME: usize = 41;
|
||||
pub const SYS_GETPEERNAME: usize = 42;
|
||||
pub const SYS_GETTIMEOFDAY: usize = 43;
|
||||
pub const SYS_MMAP: usize = 44;
|
||||
pub const SYS_MUNMAP: usize = 45;
|
||||
pub const SYS_MPROTECT: usize = 46;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Syscall;
|
||||
@ -478,13 +473,13 @@ impl Syscall {
|
||||
}
|
||||
|
||||
SYS_BRK => {
|
||||
let new_brk = VirtAddr::new(args[0]);
|
||||
Self::brk(new_brk).map(|vaddr| vaddr.data())
|
||||
let new_brk = args[0];
|
||||
Self::brk(new_brk)
|
||||
}
|
||||
|
||||
SYS_SBRK => {
|
||||
let increment = args[0] as isize;
|
||||
Self::sbrk(increment).map(|vaddr| vaddr.data())
|
||||
Self::sbrk(increment)
|
||||
}
|
||||
|
||||
SYS_REBOOT => Self::reboot(),
|
||||
@ -647,6 +642,18 @@ impl Syscall {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -866,7 +873,7 @@ impl Syscall {
|
||||
}
|
||||
SYS_GETTIMEOFDAY => {
|
||||
let timeval = args[0] as *mut PosixTimeval;
|
||||
let timezone_ptr = args[1] as *mut PosixTimeZone;
|
||||
let timezone_ptr = args[1] as *const PosixTimeZone;
|
||||
let security_check = || {
|
||||
if unsafe {
|
||||
verify_area(timeval as u64, core::mem::size_of::<PosixTimeval>() as u64)
|
||||
@ -889,49 +896,18 @@ impl Syscall {
|
||||
if r.is_err() {
|
||||
Err(r.unwrap_err())
|
||||
} else {
|
||||
let timezone = if !timezone_ptr.is_null() {
|
||||
&SYS_TIMEZONE
|
||||
} else {
|
||||
unsafe { timezone_ptr.as_ref().unwrap() }
|
||||
};
|
||||
if !timeval.is_null() {
|
||||
Self::gettimeofday(timeval, timezone_ptr)
|
||||
Self::gettimeofday(timeval, timezone)
|
||||
} else {
|
||||
Err(SystemError::EFAULT)
|
||||
}
|
||||
}
|
||||
}
|
||||
SYS_MMAP => {
|
||||
let len = page_align_up(args[1]);
|
||||
if unsafe { !verify_area(args[0] as u64, len as u64) } {
|
||||
Err(SystemError::EFAULT)
|
||||
} else {
|
||||
Self::mmap(
|
||||
VirtAddr::new(args[0]),
|
||||
len,
|
||||
args[2],
|
||||
args[3],
|
||||
args[4] as i32,
|
||||
args[5],
|
||||
)
|
||||
}
|
||||
}
|
||||
SYS_MUNMAP => {
|
||||
let addr = args[0];
|
||||
let len = page_align_up(args[1]);
|
||||
if addr & MMArch::PAGE_SIZE != 0 {
|
||||
// The addr argument is not a multiple of the page size
|
||||
Err(SystemError::EINVAL)
|
||||
} else {
|
||||
Self::munmap(VirtAddr::new(addr), len)
|
||||
}
|
||||
}
|
||||
SYS_MPROTECT => {
|
||||
let addr = args[0];
|
||||
let len = page_align_up(args[1]);
|
||||
if addr & MMArch::PAGE_SIZE != 0 {
|
||||
// The addr argument is not a multiple of the page size
|
||||
Err(SystemError::EINVAL)
|
||||
} else {
|
||||
Self::mprotect(VirtAddr::new(addr), len, args[2])
|
||||
}
|
||||
}
|
||||
|
||||
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||
};
|
||||
|
||||
|
@ -73,6 +73,102 @@ ul do_put_string(char *s, uint32_t front_color, uint32_t background_color)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将堆内存调整为arg0
|
||||
*
|
||||
* @param arg0 新的堆区域的结束地址
|
||||
* @return uint64_t 错误码
|
||||
*
|
||||
*/
|
||||
uint64_t sys_do_brk(uint64_t newaddr)
|
||||
{
|
||||
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;
|
||||
if (new_brk < mm->brk_start || new_brk > new_brk >= current_pcb->addr_limit)
|
||||
return mm->brk_end;
|
||||
|
||||
if (mm->brk_end == new_brk)
|
||||
return new_brk;
|
||||
|
||||
int64_t offset;
|
||||
if (new_brk >= current_pcb->mm->brk_end)
|
||||
offset = (int64_t)(new_brk - current_pcb->mm->brk_end);
|
||||
else
|
||||
offset = -(int64_t)(current_pcb->mm->brk_end - new_brk);
|
||||
|
||||
new_brk = mm_do_brk(current_pcb->mm->brk_end, offset); // 扩展堆内存空间
|
||||
|
||||
current_pcb->mm->brk_end = new_brk;
|
||||
return mm->brk_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程)
|
||||
*
|
||||
* @param incr offset偏移量
|
||||
* @return uint64_t the previous program break
|
||||
*/
|
||||
uint64_t sys_do_sbrk(int64_t incr)
|
||||
{
|
||||
uint64_t retval = current_pcb->mm->brk_end;
|
||||
if ((int64_t)incr > 0)
|
||||
{
|
||||
|
||||
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);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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)incr); // 调整堆内存空间
|
||||
// kdebug("do brk done, new_brk = %#018lx", new_brk);
|
||||
current_pcb->mm->brk_end = new_brk;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行新的程序
|
||||
*
|
||||
* @param user_path(r8寄存器) 文件路径
|
||||
* @param argv(r9寄存器) 参数列表
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t c_sys_execve(char *user_path, char **argv, char **envp, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
int path_len = strnlen_user(user_path, PAGE_4K_SIZE);
|
||||
|
||||
if (path_len >= PAGE_4K_SIZE)
|
||||
return -ENAMETOOLONG;
|
||||
else if (path_len <= 0)
|
||||
return -EFAULT;
|
||||
|
||||
char *path = (char *)kmalloc(path_len + 1, 0);
|
||||
if (path == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(path, 0, path_len + 1);
|
||||
|
||||
// 拷贝文件路径
|
||||
strncpy_from_user(path, user_path, path_len);
|
||||
path[path_len] = '\0';
|
||||
|
||||
// 执行新的程序
|
||||
uint64_t retval = do_execve(regs, path, argv, NULL);
|
||||
|
||||
kfree(path);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 等待进程退出
|
||||
*
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define SYS_CLOCK 19 // 获取当前cpu时间
|
||||
#define SYS_PIPE 20 // 创建管道
|
||||
|
||||
#define SYS_MSTAT 21 // 获取系统的内存状态信息
|
||||
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
|
||||
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
|
||||
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
|
||||
@ -40,20 +41,18 @@
|
||||
#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_GETSOCKNAME 41 // 获取socket的名字
|
||||
#define SYS_GETPEERNAME 42 // 获取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_GETTIMEOFDAY 43 // 获取当前时间
|
||||
#define SYS_MMAP 44 // 内存映射
|
||||
#define SYS_MUNMAP 45 // 内存解除映射
|
||||
#define SYS_MPROTECT 46 // 内存保护
|
||||
|
||||
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用
|
@ -1,141 +0,0 @@
|
||||
//! 这个文件用于放置一些内核态访问用户态数据的函数
|
||||
use core::mem::size_of;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
|
||||
use crate::mm::{verify_area, VirtAddr};
|
||||
|
||||
use super::SystemError;
|
||||
|
||||
/// 清空用户空间指定范围内的数据
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `dest`:用户空间的目标地址
|
||||
/// - `len`:要清空的数据长度
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 返回清空的数据长度
|
||||
///
|
||||
/// ## 错误
|
||||
///
|
||||
/// - `EFAULT`:目标地址不合法
|
||||
pub unsafe fn clear_user(dest: VirtAddr, len: usize) -> Result<usize, SystemError> {
|
||||
verify_area(dest, len).map_err(|_| SystemError::EFAULT)?;
|
||||
|
||||
let p = dest.data() as *mut u8;
|
||||
// 清空用户空间的数据
|
||||
p.write_bytes(0, len);
|
||||
return Ok(len);
|
||||
}
|
||||
|
||||
pub unsafe fn copy_to_user(dest: VirtAddr, src: &[u8]) -> Result<usize, SystemError> {
|
||||
verify_area(dest, src.len()).map_err(|_| SystemError::EFAULT)?;
|
||||
|
||||
let p = dest.data() as *mut u8;
|
||||
// 拷贝数据
|
||||
p.copy_from_nonoverlapping(src.as_ptr(), src.len());
|
||||
return Ok(src.len());
|
||||
}
|
||||
|
||||
/// 从用户空间拷贝数据到内核空间
|
||||
pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result<usize, SystemError> {
|
||||
verify_area(src, dst.len()).map_err(|_| SystemError::EFAULT)?;
|
||||
|
||||
let src: &[u8] = core::slice::from_raw_parts(src.data() as *const u8, dst.len());
|
||||
// 拷贝数据
|
||||
dst.copy_from_slice(&src);
|
||||
|
||||
return Ok(dst.len());
|
||||
}
|
||||
|
||||
/// 检查并从用户态拷贝一个 C 字符串。
|
||||
///
|
||||
/// 一旦遇到非法地址,就会返回错误
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `user`:用户态的 C 字符串指针
|
||||
/// - `max_length`:最大拷贝长度
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 返回拷贝的 C 字符串
|
||||
///
|
||||
/// ## 错误
|
||||
///
|
||||
/// - `EFAULT`:用户态地址不合法
|
||||
pub fn check_and_clone_cstr(
|
||||
user: *const u8,
|
||||
max_length: Option<usize>,
|
||||
) -> Result<String, SystemError> {
|
||||
if user.is_null() {
|
||||
return Ok(String::new());
|
||||
}
|
||||
|
||||
// 从用户态读取,直到遇到空字符 '\0' 或者达到最大长度
|
||||
let mut buffer = Vec::new();
|
||||
for i in 0.. {
|
||||
if max_length.is_some() && max_length.as_ref().unwrap() <= &i {
|
||||
break;
|
||||
}
|
||||
|
||||
let addr = unsafe { user.add(i) };
|
||||
let mut c = [0u8; 1];
|
||||
unsafe {
|
||||
copy_from_user(&mut c, VirtAddr::new(addr as usize))?;
|
||||
}
|
||||
if c[0] == 0 {
|
||||
break;
|
||||
}
|
||||
buffer.push(c[0]);
|
||||
}
|
||||
return Ok(String::from_utf8(buffer).map_err(|_| SystemError::EFAULT)?);
|
||||
}
|
||||
|
||||
/// 检查并从用户态拷贝一个 C 字符串数组
|
||||
///
|
||||
/// 一旦遇到空指针,就会停止拷贝. 一旦遇到非法地址,就会返回错误
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `user`:用户态的 C 字符串指针数组
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 返回拷贝的 C 字符串数组
|
||||
///
|
||||
/// ## 错误
|
||||
///
|
||||
/// - `EFAULT`:用户态地址不合法
|
||||
pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>, SystemError> {
|
||||
if user.is_null() {
|
||||
Ok(Vec::new())
|
||||
} else {
|
||||
// kdebug!("check_and_clone_cstr_array: {:p}\n", user);
|
||||
let mut buffer = Vec::new();
|
||||
for i in 0.. {
|
||||
let addr = unsafe { user.add(i) };
|
||||
let str_ptr: *const u8;
|
||||
// 读取这个地址的值(这个值也是一个指针)
|
||||
unsafe {
|
||||
let dst = [0usize; 1];
|
||||
let mut dst = core::mem::transmute::<[usize; 1], [u8; size_of::<usize>()]>(dst);
|
||||
copy_from_user(&mut dst, VirtAddr::new(addr as usize))?;
|
||||
let dst = core::mem::transmute::<[u8; size_of::<usize>()], [usize; 1]>(dst);
|
||||
str_ptr = dst[0] as *const u8;
|
||||
|
||||
// kdebug!("str_ptr: {:p}, addr:{addr:?}\n", str_ptr);
|
||||
}
|
||||
|
||||
if str_ptr.is_null() {
|
||||
break;
|
||||
}
|
||||
// 读取这个指针指向的字符串
|
||||
let string = check_and_clone_cstr(str_ptr, None)?;
|
||||
// 将字符串放入 buffer 中
|
||||
buffer.push(string);
|
||||
}
|
||||
return Ok(buffer);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user