From c588d6f77f4b38939701b946228218ea81a7c8dc Mon Sep 17 00:00:00 2001 From: login Date: Mon, 19 Dec 2022 15:03:44 +0800 Subject: [PATCH] Patch add abort func (#120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 对于除了sigkill以外的信号,也加入队列 * bugfix:libc中,注册信号处理函数时,总是注册sigkill的问题 * 增加getpid系统调用 * 增加了raise、kill、abort --- kernel/src/ipc/signal.rs | 78 +++++++++++++++++++---------- kernel/src/ipc/signal_types.rs | 13 +++-- kernel/src/process/pid.rs | 10 ++++ kernel/src/syscall/syscall.c | 4 +- kernel/src/syscall/syscall_num.h | 1 + user/apps/shell/cmd.c | 2 +- user/libs/libc/src/include/signal.h | 9 +++- user/libs/libc/src/signal.c | 35 ++++++++++--- user/libs/libc/src/stdlib.c | 16 +++++- user/libs/libc/src/stdlib.h | 8 ++- user/libs/libc/src/unistd.c | 26 +++++++--- user/libs/libc/src/unistd.h | 4 +- user/libs/libsystem/syscall.h | 1 + 13 files changed, 155 insertions(+), 52 deletions(-) diff --git a/kernel/src/ipc/signal.rs b/kernel/src/ipc/signal.rs index f61f454c..b50d291b 100644 --- a/kernel/src/ipc/signal.rs +++ b/kernel/src/ipc/signal.rs @@ -64,6 +64,7 @@ pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction { pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 { let pid: pid_t = regs.r8 as pid_t; let sig: SignalNumber = SignalNumber::from(regs.r9 as i32); + if sig == SignalNumber::INVALID { // 传入的signal数值不合法 kwarn!("Not a valid signal number"); @@ -86,29 +87,43 @@ pub extern "C" fn sys_kill(regs: &pt_regs) -> u64 { }; compiler_fence(core::sync::atomic::Ordering::SeqCst); - let retval = signal_kill_something_info(sig, Some(&mut info), pid) as u64; - + let retval = signal_kill_something_info(sig, Some(&mut info), pid); + let x; + if retval.is_ok() { + x = retval.unwrap(); + } else { + x = retval.unwrap_err(); + } compiler_fence(core::sync::atomic::Ordering::SeqCst); - return retval; + + return x as u64; } /// 通过kill的方式向目标进程发送信号 /// @param sig 要发送的信号 /// @param info 要发送的信息 /// @param pid 进程id(目前只支持pid>0) -fn signal_kill_something_info(sig: SignalNumber, info: Option<&mut siginfo>, pid: pid_t) -> i32 { +fn signal_kill_something_info( + sig: SignalNumber, + info: Option<&mut siginfo>, + pid: pid_t, +) -> Result { // 暂时不支持特殊的kill操作 if pid <= 0 { kwarn!("Kill operation not support: pid={}", pid); - return -(ENOTSUP as i32); + return Err(-(ENOTSUP as i32)); } // kill单个进程 return signal_kill_proc_info(sig, info, pid); } -fn signal_kill_proc_info(sig: SignalNumber, info: Option<&mut siginfo>, pid: pid_t) -> i32 { - let mut retval: i32 = -(ESRCH as i32); +fn signal_kill_proc_info( + sig: SignalNumber, + info: Option<&mut siginfo>, + pid: pid_t, +) -> Result { + let mut retval = Err(-(ESRCH as i32)); // step1: 当进程管理模块拥有pcblist_lock之后,对其加锁 @@ -147,16 +162,16 @@ fn signal_send_sig_info( sig: SignalNumber, info: Option<&mut siginfo>, target_pcb: &mut process_control_block, -) -> i32 { +) -> Result { // kdebug!("signal_send_sig_info"); // 检查sig是否符合要求,如果不符合要求,则退出。 if !verify_signal(sig) { - return -(EINVAL as i32); + return Err(-(EINVAL as i32)); } // 信号符合要求,可以发送 - let mut retval = -(ESRCH as i32); + let mut retval = Err(-(ESRCH as i32)); let mut flags: u64 = 0; // 如果上锁成功,则发送信号 if !lock_process_sighand(target_pcb, &mut flags).is_none() { @@ -214,7 +229,7 @@ fn send_signal_locked( info: Option<&mut siginfo>, pcb: &mut process_control_block, pt: PidType, -) -> i32 { +) -> Result { // 是否强制发送信号 let mut force_send = false; // signal的信息为空 @@ -240,13 +255,12 @@ fn send_signal_locked( /// @return i32 错误码 fn __send_signal_locked( sig: SignalNumber, - _info: Option<&mut siginfo>, + info: Option<&mut siginfo>, pcb: &mut process_control_block, pt: PidType, _force_send: bool, -) -> i32 { +) -> Result { // kdebug!("__send_signal_locked"); - let mut retval = 0; // 判断该进入该函数时,是否已经持有了锁 assert!(spin_is_locked(unsafe { &(*pcb.sighand).siglock })); @@ -257,11 +271,26 @@ fn __send_signal_locked( if sig == SignalNumber::SIGKILL || (pcb.flags & (PF_KTHREAD as u64)) != 0 { complete_signal(sig, pcb, pt); } else { - // todo: 如果是其他信号,则加入到sigqueue内,然后complete_signal - retval = -(ENOTSUP as i32); + // 如果是其他信号,则加入到sigqueue内,然后complete_signal + let mut q: siginfo; + match info { + Some(x) => { + // 已经显式指定了siginfo,则直接使用它。 + q = x.clone(); + } + None => { + // 不需要显示指定siginfo,因此设置为默认值 + q = siginfo::new(sig, 0, si_code_val::SI_USER); + q._sinfo.data._sifields._kill._pid = current_pcb().pid; + } + } + + let sq: &mut SigQueue = SigQueue::from_c_void(current_pcb().sig_pending.sigqueue); + sq.q.push(q); + complete_signal(sig, pcb, pt); } compiler_fence(core::sync::atomic::Ordering::SeqCst); - return retval; + return Ok(0); } /// @brief 将信号添加到目标进程的sig_pending。在引入进程组后,本函数还将负责把信号传递给整个进程组。 @@ -407,8 +436,7 @@ pub extern "C" fn do_signal(regs: &mut pt_regs) { // 做完上面的检查后,开中断 sti(); - // return; - // kdebug!("do_signal"); + let oldset = current_pcb().sig_blocked; loop { let (sig_number, info, ka) = get_signal_to_deliver(regs.clone()); @@ -790,7 +818,7 @@ pub extern "C" fn sys_sigaction(regs: &mut pt_regs) -> u64 { } let mask: sigset_t = unsafe { (*act).sa_mask }; let _input_sah = unsafe { (*act).sa_handler as u64 }; - + // kdebug!("_input_sah={}", _input_sah); match _input_sah { USER_SIG_DFL | USER_SIG_IGN => { if _input_sah == USER_SIG_DFL { @@ -818,6 +846,7 @@ pub extern "C" fn sys_sigaction(regs: &mut pt_regs) -> u64 { }; } } + // kdebug!("new_ka={:?}", new_ka); // 如果用户手动给了sa_restorer,那么就置位SA_FLAG_RESTORER,否则报错。(用户必须手动指定restorer) if new_ka.sa_restorer != NULL as u64 { new_ka.sa_flags |= SA_FLAG_RESTORER; @@ -875,6 +904,7 @@ pub extern "C" fn sys_sigaction(regs: &mut pt_regs) -> u64 { (*old_act).sa_restorer = old_ka.sa_restorer as *mut c_void; } } + return retval as u64; } @@ -946,8 +976,7 @@ fn do_sigaction( let mut mask: sigset_t = 0; sigset_clear(&mut mask); sigset_add(&mut mask, sig); - let sq = pcb.sig_pending.sigqueue as *mut SigQueue; - let sq = unsafe { sq.as_mut::<'static>() }.unwrap(); + let sq: &mut SigQueue = SigQueue::from_c_void(pcb.sig_pending.sigqueue); sq.flush_by_mask(&mask); // todo: 当有了多个线程后,在这里进行操作,把每个线程的sigqueue都进行刷新 @@ -966,11 +995,6 @@ pub fn sigmask(sig: SignalNumber) -> u64 { #[no_mangle] pub extern "C" fn sys_rt_sigreturn(regs: &mut pt_regs) -> u64 { - // kdebug!( - // "sigreturn, pid={}, regs.rsp=0x{:018x}", - // current_pcb().pid, - // regs.rsp - // ); let frame = regs.rsp as usize as *mut sigframe; // 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击) diff --git a/kernel/src/ipc/signal_types.rs b/kernel/src/ipc/signal_types.rs index fc24b338..2c1d0490 100644 --- a/kernel/src/ipc/signal_types.rs +++ b/kernel/src/ipc/signal_types.rs @@ -93,9 +93,9 @@ pub const SA_ALL_FLAGS: u64 = SA_FLAG_IGN | SA_FLAG_DFL | SA_FLAG_RESTORER | SA_ // ============ sigaction结构体中的的sa_flags的可选值 end =========== /// 用户态程序传入的SIG_DFL的值 -pub const USER_SIG_DFL: u64 = 1u64 << 0; +pub const USER_SIG_DFL: u64 = 0; /// 用户态程序传入的SIG_IGN的值 -pub const USER_SIG_IGN: u64 = 1u64 << 1; +pub const USER_SIG_IGN: u64 = 1; /** * @brief 信号处理结构体 @@ -544,6 +544,13 @@ impl SigQueue { drop(x) } } + + /// @brief 从C的void*指针转换为static生命周期的可变引用 + pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue{ + let sq = p as *mut SigQueue; + let sq = unsafe { sq.as_mut::<'static>() }.unwrap(); + return sq; + } } impl Default for SigQueue { @@ -587,7 +594,7 @@ pub fn sigset_delmask(set: &mut sigset_t, mask: u64) { /// @brief 判断两个sigset是否相等 #[inline] pub fn sigset_equal(a: &sigset_t, b: &sigset_t) -> bool { - if _NSIG_U64_CNT == 1{ + if _NSIG_U64_CNT == 1 { return *a == *b; } return false; diff --git a/kernel/src/process/pid.rs b/kernel/src/process/pid.rs index db8e20e6..5e0c3312 100644 --- a/kernel/src/process/pid.rs +++ b/kernel/src/process/pid.rs @@ -1,3 +1,5 @@ +use crate::{include::bindings::bindings::pt_regs, arch::x86_64::asm::current::current_pcb}; + #[allow(dead_code)] #[derive(Debug, Clone, Copy)] #[repr(u8)] @@ -15,4 +17,12 @@ impl PartialEq for PidType { fn eq(&self, other: &PidType) -> bool { *self as u8 == *other as u8 } +} + +/** + * @brief 获取当前进程的pid + */ +#[no_mangle] +pub extern "C" fn sys_getpid(_regs: &pt_regs)->u64{ + return current_pcb().pid as u64; } \ No newline at end of file diff --git a/kernel/src/syscall/syscall.c b/kernel/src/syscall/syscall.c index f2fe0700..e8c30d94 100644 --- a/kernel/src/syscall/syscall.c +++ b/kernel/src/syscall/syscall.c @@ -22,6 +22,7 @@ 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); /** * @brief 导出系统调用处理函数的符号 @@ -590,6 +591,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = { [23] = sys_kill, [24] = sys_sigaction, [25] = sys_rt_sigreturn, - [26 ... 254] = system_call_not_exists, + [26] = sys_getpid, + [27 ... 254] = system_call_not_exists, [255] = sys_ahci_end_req, }; diff --git a/kernel/src/syscall/syscall_num.h b/kernel/src/syscall/syscall_num.h index 853d95e4..a212fae0 100644 --- a/kernel/src/syscall/syscall_num.h +++ b/kernel/src/syscall/syscall_num.h @@ -37,5 +37,6 @@ #define SYS_KILL 23 // kill一个进程(向这个进程发出信号) #define SYS_SIGACTION 24 // 设置进程的信号处理动作 #define SYS_RT_SIGRETURN 25 // 从信号处理函数返回 +#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符) #define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用 \ No newline at end of file diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 77545757..2485a8d2 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -529,7 +529,7 @@ int shell_cmd_kill(int argc, char **argv) retval = -EINVAL; goto out; } - retval = syscall_invoke(SYS_KILL, atoi(argv[1]), SIGKILL, 0, 0, 0, 0, 0, 0); + retval = kill(atoi(argv[1]), SIGKILL); out:; free(argv); return retval; diff --git a/user/libs/libc/src/include/signal.h b/user/libs/libc/src/include/signal.h index 004d98a6..d6ea1e8d 100644 --- a/user/libs/libc/src/include/signal.h +++ b/user/libs/libc/src/include/signal.h @@ -40,7 +40,10 @@ #define SIGRTMIN 32 #define SIGRTMAX MAX_SIG_NUM -typedef void (*__sighandler_t) (int); +typedef void (*__sighandler_t)(int); + +#define SIG_DFL ((__sighandler_t)0) /* Default action. */ +#define SIG_IGN ((__sighandler_t)1) /* Ignore signal. */ // 注意,该结构体最大16字节 union __sifields { @@ -86,4 +89,6 @@ struct sigaction }; int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); -int signal(int signum, __sighandler_t handler); \ No newline at end of file +int signal(int signum, __sighandler_t handler); +int raise(int sig); +int kill(pid_t, int sig); \ No newline at end of file diff --git a/user/libs/libc/src/signal.c b/user/libs/libc/src/signal.c index a000475d..379e4655 100644 --- a/user/libs/libc/src/signal.c +++ b/user/libs/libc/src/signal.c @@ -14,10 +14,10 @@ void __libc_sa_restorer() /** * @brief 设置信号处理动作(简单版本) - * - * @param signum - * @param handler - * @return int + * + * @param signum + * @param handler + * @return int */ int signal(int signum, __sighandler_t handler) { @@ -27,12 +27,12 @@ int signal(int signum, __sighandler_t handler) sa.sa_restorer = &__libc_sa_restorer; // printf("handler address: %#018lx\n", handler); // printf("restorer address: %#018lx\n", &__libc_sa_restorer); - sigaction(SIGKILL, &sa, NULL); + sigaction(signum, &sa, NULL); } /** * @brief 设置信号处理动作 - * + * * @param signum 信号 * @param act 处理动作(不可为NULL) * @param oldact 返回的旧的处理动作(若为NULL,则不返回) @@ -41,4 +41,27 @@ int signal(int signum, __sighandler_t handler) int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { return syscall_invoke(SYS_SIGACTION, (uint64_t)signum, (uint64_t)act, (uint64_t)oldact, 0, 0, 0, 0, 0); +} + +/** + * @brief 向当前进程发送一个信号 + * + * @param sig signal number + * @return int 错误码 + */ +int raise(int sig) +{ + return kill(getpid(), sig); +} + +/** + * @brief + * + * @param pid 进程的标识符 + * @param sig signal number + * @return int 错误码 + */ +int kill(pid_t pid, int sig) +{ + syscall_invoke(SYS_KILL, pid, sig, 0, 0, 0, 0, 0, 0); } \ No newline at end of file diff --git a/user/libs/libc/src/stdlib.c b/user/libs/libc/src/stdlib.c index c6b4d3a4..44b5a732 100644 --- a/user/libs/libc/src/stdlib.c +++ b/user/libs/libc/src/stdlib.c @@ -1,7 +1,8 @@ -#include -#include #include +#include +#include #include +#include int abs(int i) { @@ -54,4 +55,15 @@ int atoi(const char *str) void exit(int status) { syscall_invoke(SYS_EXIT, status, 0, 0, 0, 0, 0, 0, 0); +} + +/** + * @brief 通过发送SIGABRT,从而退出当前进程 + * + */ +void abort() +{ + // step1:设置SIGABRT的处理函数为SIG_DFL + signal(SIGABRT, SIG_DFL); + raise(SIGABRT); } \ No newline at end of file diff --git a/user/libs/libc/src/stdlib.h b/user/libs/libc/src/stdlib.h index 0cdc6132..18df39e3 100644 --- a/user/libs/libc/src/stdlib.h +++ b/user/libs/libc/src/stdlib.h @@ -39,4 +39,10 @@ int atoi(const char * str); * * @param status */ -void exit(int status); \ No newline at end of file +void exit(int status); + +/** + * @brief 通过发送SIGABRT,从而退出当前进程 + * + */ +void abort(); \ No newline at end of file diff --git a/user/libs/libc/src/unistd.c b/user/libs/libc/src/unistd.c index a5a98484..58d98b68 100644 --- a/user/libs/libc/src/unistd.c +++ b/user/libs/libc/src/unistd.c @@ -1,10 +1,10 @@ +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include /** * @brief 关闭文件接口 @@ -163,11 +163,11 @@ int rmdir(const char *path) /** * @brief 删除文件 - * + * * @param path 绝对路径 - * @return int + * @return int */ -int rm(const char * path) +int rm(const char *path) { return syscall_invoke(SYS_UNLINK_AT, 0, (uint64_t)path, 0, 0, 0, 0, 0, 0); } @@ -193,4 +193,14 @@ void swab(void *restrict src, void *restrict dest, ssize_t nbytes) _src += transfer; _dest += transfer; } +} + +/** + * @brief 获取当前进程的pid(进程标识符) + * + * @return pid_t 当前进程的pid + */ +pid_t getpid(void) +{ + syscall_invoke(SYS_GETPID, 0, 0, 0, 0, 0, 0, 0, 0); } \ No newline at end of file diff --git a/user/libs/libc/src/unistd.h b/user/libs/libc/src/unistd.h index 15ca09c2..cdf530ca 100644 --- a/user/libs/libc/src/unistd.h +++ b/user/libs/libc/src/unistd.h @@ -114,4 +114,6 @@ int rm(const char * path); * @param dest 目的地址 * @param nbytes 交换字节数 */ -void swab(void *restrict src, void *restrict dest, ssize_t nbytes); \ No newline at end of file +void swab(void *restrict src, void *restrict dest, ssize_t nbytes); + +pid_t getpid(void); \ No newline at end of file diff --git a/user/libs/libsystem/syscall.h b/user/libs/libsystem/syscall.h index f2289813..e553d23f 100644 --- a/user/libs/libsystem/syscall.h +++ b/user/libs/libsystem/syscall.h @@ -31,6 +31,7 @@ #define SYS_KILL 23 // kill一个进程(向这个进程发出信号) #define SYS_SIGACTION 24 // 设置进程的信号处理动作 #define SYS_RT_SIGRETURN 25 // 从信号处理函数返回 +#define SYS_GETPID 26 // 获取当前进程的pid(进程标识符) /** * @brief 用户态系统调用函数