Selaa lähdekoodia

new:在fork时拷贝signal和sighand (#91)

* refcount初始化

* new: 实现copy_sighand
del: 删除sighand_struct的wqh, 待将来有需要时,替换成rust版本的

* new: 拷贝signal
bugfix: 解决拷贝sighand时的uaf问题
login 2 vuotta sitten
vanhempi
commit
c8025a8879

+ 1 - 2
kernel/src/include/DragonOS/signal.h

@@ -108,13 +108,12 @@ struct signal_struct
 
 /**
  * @brief 信号处理结构体,位于pcb之中。
- *
+ * 请注意,该结构体需要与rust的版本一致,且以rust的为准
  */
 struct sighand_struct
 {
     spinlock_t siglock;
     refcount_t count;
-    wait_queue_head_t signal_fd_wqh;
     // 为每个信号注册的处理函数的结构体
     struct sigaction action[MAX_SIG_NUM];
 };

+ 40 - 2
kernel/src/include/DragonOS/signal.rs

@@ -4,7 +4,6 @@
 // todo: 将这里更换为手动编写的ffi绑定
 use crate::include::bindings::bindings::atomic_t;
 use crate::include::bindings::bindings::spinlock_t;
-use crate::include::bindings::bindings::wait_queue_head_t;
 use crate::libs::ffi_convert::FFIBind2Rust;
 use crate::libs::ffi_convert::__convert_mut;
 use crate::libs::ffi_convert::__convert_ref;
@@ -27,6 +26,12 @@ pub struct signal_struct {
     pub sig_cnt: atomic_t,
 }
 
+impl Default for signal_struct{
+    fn default() -> Self {
+        Self { sig_cnt: Default::default() }
+    }
+}
+
 /**
  * sigaction中的信号处理函数结构体
  * 分为两种处理函数
@@ -50,6 +55,13 @@ impl core::fmt::Debug for sigaction__union_u{
     }
 }
 
+
+impl Default for sigaction__union_u {
+    fn default() -> Self {
+        Self{_sa_handler:None}
+    }
+}
+
 /**
  * @brief 信号处理结构体
  */
@@ -62,6 +74,13 @@ pub struct sigaction {
     pub sa_restorer: ::core::option::Option<unsafe extern "C" fn()>, // 暂时未实现该函数
 }
 
+impl Default for sigaction{
+    fn default() -> Self {
+        Self { _u: Default::default(), sa_flags: Default::default(), sa_mask: Default::default(), sa_restorer: Default::default() }
+    }
+}
+
+
 
 /**
  * 信号消息的结构体,作为参数传入sigaction结构体中指向的处理函数
@@ -115,10 +134,15 @@ pub struct __sifields__kill {
 pub struct sighand_struct {
     pub siglock: spinlock_t,
     pub count: RefCount,
-    pub signal_fd_wqh: wait_queue_head_t,
     pub action: [sigaction; MAX_SIG_NUM as usize],
 }
 
+impl Default for sighand_struct{
+    fn default() -> Self {
+        Self { siglock: Default::default(), count: Default::default(), action: [Default::default();MAX_SIG_NUM as usize] }
+    }
+}
+
 /**
  * @brief 正在等待的信号的标志位
  */
@@ -319,4 +343,18 @@ impl FFIBind2Rust<crate::include::bindings::bindings::sighand_struct> for sighan
     ) -> Option<&'a Self> {
         return __convert_ref(src)
     }
+}
+
+/// @brief 将给定的来自bindgen的sigaction解析为Rust的signal.rs中定义的sigaction的引用
+impl FFIBind2Rust<crate::include::bindings::bindings::sigaction> for sigaction{
+    fn convert_mut<'a>(
+        src: *mut crate::include::bindings::bindings::sigaction,
+    ) -> Option<&'a mut Self> {
+        return __convert_mut(src);
+    }
+    fn convert_ref<'a>(
+        src: *const crate::include::bindings::bindings::sigaction,
+    ) -> Option<&'a Self> {
+        return __convert_ref(src)
+    }
 }

+ 18 - 20
kernel/src/ipc/signal.rs

@@ -7,8 +7,8 @@ use crate::{
             ENOTSUP, ESRCH, PF_EXITING, PF_KTHREAD, PF_WAKEKILL, PROC_INTERRUPTIBLE,
         },
         DragonOS::signal::{
-            si_code_val, sighand_struct, siginfo, signal_struct, sigpending, sigset_t,
-            SignalNumber, MAX_SIG_NUM, sigaction, sigaction__union_u,
+            si_code_val, sigaction, sigaction__union_u, sighand_struct, siginfo, signal_struct,
+            sigpending, sigset_t, SignalNumber, MAX_SIG_NUM,
         },
     },
     kBUG, kdebug, kwarn,
@@ -26,13 +26,11 @@ use crate::{
 use crate::include::DragonOS::signal::{__siginfo_union, __siginfo_union_data};
 
 /// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
-pub static DEFAULT_SIGACTION: sigaction = sigaction{
-    _u: sigaction__union_u{
-        _sa_handler: None,
-    },
-    sa_flags:0,
-    sa_mask:0,
-    sa_restorer:None
+pub static DEFAULT_SIGACTION: sigaction = sigaction {
+    _u: sigaction__union_u { _sa_handler: None },
+    sa_flags: 0,
+    sa_mask: 0,
+    sa_restorer: None,
 };
 
 /// @brief kill系统调用,向指定的进程发送信号
@@ -142,7 +140,7 @@ fn signal_send_sig_info(
     if !lock_process_sighand(target_pcb, &mut flags).is_none() {
         // 发送信号
         retval = send_signal_locked(sig, info, target_pcb, PidType::PID);
-        
+
         kdebug!("flags=0x{:016x}", flags);
         // 对sighand放锁
         unlock_process_sighand(target_pcb, &flags);
@@ -159,22 +157,20 @@ fn lock_process_sighand<'a>(
     flags: &mut u64,
 ) -> Option<&'a mut sighand_struct> {
     kdebug!("lock_process_sighand");
-    let x = unsafe { &mut *pcb.sighand };
 
     let sighand_ptr = sighand_struct::convert_mut(unsafe { &mut *pcb.sighand });
     // kdebug!("sighand_ptr={:?}", &sighand_ptr);
     if !sighand_ptr.is_some() {
         kBUG!("Sighand ptr of process {pid} is NULL!", pid = pcb.pid);
         return None;
-    }else{
-
+    } else {
         kdebug!("7777");
     }
-    let lock =  {&mut sighand_ptr.unwrap().siglock};
+    let lock = { &mut sighand_ptr.unwrap().siglock };
     kdebug!("123");
-    kdebug!("lock={}", unsafe{*(lock as *mut spinlock_t as *mut i8)});
+    kdebug!("lock={}", unsafe { *(lock as *mut spinlock_t as *mut i8) });
     spin_lock_irqsave(lock, flags);
-    kdebug!("lock={}", unsafe{*(lock as *mut spinlock_t as *mut i8)});
+    kdebug!("lock={}", unsafe { *(lock as *mut spinlock_t as *mut i8) });
     kdebug!("locked");
     let ret = unsafe { ((*pcb).sighand as *mut sighand_struct).as_mut() };
 
@@ -186,10 +182,10 @@ fn lock_process_sighand<'a>(
 /// @param flags 用来保存rflags的变量,将这个值恢复到rflags寄存器中
 fn unlock_process_sighand(pcb: &mut process_control_block, flags: &u64) {
     kdebug!("unlock_process_sighand");
-    let lock = unsafe{&mut (*pcb.sighand).siglock};
+    let lock = unsafe { &mut (*pcb.sighand).siglock };
     kdebug!("lock={:?}", lock);
     spin_unlock_irqrestore(lock, flags);
-    kdebug!("lock={}", unsafe{*(lock as *mut spinlock_t as *mut i8)});
+    kdebug!("lock={}", unsafe { *(lock as *mut spinlock_t as *mut i8) });
     kdebug!("123443");
 }
 
@@ -238,7 +234,10 @@ fn __send_signal_locked(
     let mut retval = 0;
 
     // 判断该进入该函数时,是否已经持有了锁
-    println!("locked={}",spin_is_locked(unsafe { &(*pcb.sighand).siglock }));
+    println!(
+        "locked={}",
+        spin_is_locked(unsafe { &(*pcb.sighand).siglock })
+    );
     kdebug!("1234");
     let _pending: Option<&mut sigpending> = sigpending::convert_mut(&mut pcb.sig_pending);
     kdebug!("567");
@@ -399,4 +398,3 @@ fn signal_wake_up_state(pcb: &mut process_control_block, state: u64) {
         process_kick(pcb);
     }
 }
-

+ 19 - 4
kernel/src/libs/atomic.rs

@@ -1,11 +1,26 @@
-use core::ptr::read_volatile;
+#![allow(dead_code)]
+use core::ptr::{read_volatile, write_volatile};
 
 use crate::include::bindings::bindings::atomic_t;
 
 /// @brief 原子的读取指定的原子变量的值
 #[inline]
-pub fn atomic_read(ato:*const atomic_t)-> i64{
-    unsafe{
+pub fn atomic_read(ato: *const atomic_t) -> i64 {
+    unsafe {
         return read_volatile(&(*ato).value);
     }
-}
+}
+
+/// @brief 原子的设置原子变量的值
+#[inline]
+pub fn atomic_set(ato: *mut atomic_t, value:i64) {
+    unsafe{
+        write_volatile(&mut (*ato).value, value);
+    }
+}
+
+impl Default for atomic_t {
+    fn default() -> Self {
+        Self { value: 0 }
+    }
+}

+ 15 - 0
kernel/src/libs/list.rs

@@ -0,0 +1,15 @@
+use crate::include::bindings::bindings::List;
+
+/// @brief 初始化链表
+#[inline]
+pub fn list_init(list: *mut List) {
+    unsafe{*list}.prev = list;
+    unsafe{*list}.next = list;
+}
+
+impl Default for List{
+    fn default() -> Self {
+       let x= Self { prev: 0 as *mut List, next: 0 as *mut List };
+       return x;
+    }
+}

+ 3 - 1
kernel/src/libs/mod.rs

@@ -3,4 +3,6 @@ pub mod spinlock;
 pub mod ffi_convert;
 #[macro_use]
 pub mod refcount;
-pub mod atomic;
+pub mod atomic;
+pub mod wait_queue;
+pub mod list;

+ 8 - 1
kernel/src/libs/refcount.rs

@@ -7,6 +7,12 @@ pub struct RefCount {
     pub refs: atomic_t,
 }
 
+impl Default for RefCount{
+    fn default() -> Self {
+        Self { refs:  atomic_t { value: 1 }}
+    }
+}
+
 /// @brief 将给定的来自bindgen的refcount_t解析为Rust的RefCount的引用
 impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCount{
     fn convert_mut<'a>(
@@ -21,10 +27,11 @@ impl FFIBind2Rust<crate::include::bindings::bindings::refcount_struct> for RefCo
     }
 }
 
+/// @brief 以指定的值初始化refcount
 macro_rules! REFCOUNT_INIT {
     ($x:expr) => {
         $crate::libs::refcount::RefCount {
-            refs: atomic_t { value: 0 },
+            refs: $crate::include::bindings::bindings::atomic_t { value: $x },
         }
     };
 }

+ 6 - 0
kernel/src/libs/spinlock.rs

@@ -28,3 +28,9 @@ pub fn spin_is_locked(lock: &spinlock_t) -> bool {
 
     return if val == 0 { true } else { false };
 }
+
+impl Default for spinlock_t {
+    fn default() -> Self {
+        Self { lock: 1 }
+    }
+}

+ 12 - 0
kernel/src/libs/wait_queue.rs

@@ -0,0 +1,12 @@
+use crate::include::bindings::bindings::{wait_queue_head_t};
+
+use super::{list::list_init};
+
+
+impl Default for wait_queue_head_t{
+    fn default() -> Self {
+        let mut x = Self { wait_list: Default::default(), lock: Default::default() };
+        list_init(&mut x.wait_list);
+        return x;
+    }
+}

+ 10 - 9
kernel/src/process/fork.c

@@ -12,11 +12,12 @@ int process_copy_files(uint64_t clone_flags, struct process_control_block *pcb);
 int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb);
 int process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb);
 int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start,
-                             uint64_t stack_size, struct pt_regs *current_regs);
-
-extern int process_copy_sighand(uint64_t clone_flags, struct process_control_block * pcb);
-extern int process_copy_signal(uint64_t clone_flags, struct process_control_block * pcb);
+                        uint64_t stack_size, struct pt_regs *current_regs);
 
+extern int process_copy_sighand(uint64_t clone_flags, struct process_control_block *pcb);
+extern int process_copy_signal(uint64_t clone_flags, struct process_control_block *pcb);
+extern void process_exit_sighand(struct process_control_block *pcb);
+extern void process_exit_signal(struct process_control_block *pcb);
 
 /**
  * @brief fork当前进程
@@ -111,14 +112,14 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
     retval = process_copy_files(clone_flags, tsk);
     if (retval)
         goto copy_files_failed;
-    
+
     // 拷贝信号处理函数
     retval = process_copy_sighand(clone_flags, tsk);
-    if(retval)
+    if (retval)
         goto copy_sighand_failed;
-    
+
     retval = process_copy_signal(clone_flags, tsk);
-    if(retval)
+    if (retval)
         goto copy_signal_failed;
 
     // 拷贝线程结构体
@@ -338,7 +339,7 @@ static int process_rewrite_rbp(struct pt_regs *new_regs, struct process_control_
  * @return uint64_t
  */
 int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start,
-                             uint64_t stack_size, struct pt_regs *current_regs)
+                        uint64_t stack_size, struct pt_regs *current_regs)
 {
     // 将线程结构体放置在pcb后方
     struct thread_struct *thd = (struct thread_struct *)(pcb + 1);

+ 84 - 9
kernel/src/process/fork.rs

@@ -1,27 +1,102 @@
-use crate::{include::bindings::bindings::{process_control_block, CLONE_SIGHAND}, kdebug, libs::{refcount::{refcount_inc, RefCount}, ffi_convert::FFIBind2Rust}, arch::x86_64::asm::current::current_pcb};
+use core::ptr::null_mut;
+
+use alloc::boxed::Box;
+
+use crate::{
+    arch::x86_64::asm::current::current_pcb,
+    include::{
+        bindings::bindings::{
+            process_control_block, CLONE_CLEAR_SIGHAND, CLONE_SIGHAND, CLONE_THREAD, ENOMEM,
+        },
+        DragonOS::signal::{sigaction, sighand_struct, signal_struct},
+    },
+    ipc::signal::DEFAULT_SIGACTION,
+    kdebug,
+    libs::{
+        ffi_convert::FFIBind2Rust,
+        refcount::{refcount_inc, RefCount},
+        spinlock::{spin_lock_irqsave, spin_unlock_irqrestore}, atomic::atomic_set,
+    },
+};
 
 #[no_mangle]
 pub extern "C" fn process_copy_sighand(clone_flags: u64, pcb: *mut process_control_block) -> i32 {
     kdebug!("process_copy_sighand");
-    if(clone_flags & (CLONE_SIGHAND as u64)) != 0{
-        let r = RefCount::convert_mut(unsafe{&mut (*((current_pcb().sighand))).count}).unwrap();
-       refcount_inc(r);
+    if (clone_flags & (CLONE_SIGHAND as u64)) != 0 {
+        let r = RefCount::convert_mut(unsafe { &mut (*(current_pcb().sighand)).count }).unwrap();
+        refcount_inc(r);
+    }
+    // 在这里使用Box::leak将动态申请的内存的生命周期转换为static的
+    let mut sig: &mut sighand_struct = Box::leak(Box::new(sighand_struct::default()));
+    if (sig as *mut sighand_struct) == null_mut() {
+        return -(ENOMEM as i32);
+    }
+    // 将新的sighand赋值给pcb
+    unsafe {
+        (*pcb).sighand = sig as *mut sighand_struct as usize
+            as *mut crate::include::bindings::bindings::sighand_struct;
     }
-    0
+
+    // 拷贝sigaction
+    let mut flags: u64 = 0;
+    spin_lock_irqsave(unsafe { &mut (*current_pcb().sighand).siglock }, &mut flags);
+    for (index, x) in unsafe { (*current_pcb().sighand).action }
+        .iter()
+        .enumerate()
+    {
+        if !(x as *const crate::include::bindings::bindings::sigaction).is_null() {
+            sig.action[index] =
+                *sigaction::convert_ref(x as *const crate::include::bindings::bindings::sigaction)
+                    .unwrap();
+        } else {
+            sig.action[index] = DEFAULT_SIGACTION;
+        }
+    }
+
+    spin_unlock_irqrestore(unsafe { &mut (*current_pcb().sighand).siglock }, &flags);
+
+    // 将所有屏蔽的信号的处理函数设置为default
+    if (clone_flags & (CLONE_CLEAR_SIGHAND as u64)) != 0 {
+        todo!();
+    }
+
+    return 0;
 }
 
 #[no_mangle]
 pub extern "C" fn process_copy_signal(clone_flags: u64, pcb: *mut process_control_block) -> i32 {
     kdebug!("process_copy_signal");
-    0
+    // 如果克隆的是线程,则不拷贝信号(同一进程的各个线程之间共享信号)
+    if (clone_flags & (CLONE_THREAD as u64)) != 0 {
+        return 0;
+    }
+    let sig: &mut signal_struct = Box::leak(Box::new(signal_struct::default()));
+    if (sig as *mut signal_struct) == null_mut() {
+        return -(ENOMEM as i32);
+    }
+    atomic_set(&mut sig.sig_cnt, 1);
+    // 将sig赋值给pcb中的字段
+    unsafe {
+        (*pcb).signal = sig as *mut signal_struct as usize
+            as *mut crate::include::bindings::bindings::signal_struct;
+    }
+    return 0;
 }
 
 #[no_mangle]
-pub extern "C" fn process_exit_signal(pcb: *mut process_control_block){
-    // todo: 回收进程的信号结构体
+pub extern "C" fn process_exit_signal(pcb: *mut process_control_block) {
+    // 回收进程的信号结构体
+    unsafe {
+        drop((*pcb).sighand as *mut sighand_struct);
+        (*pcb).sighand = 0 as *mut crate::include::bindings::bindings::sighand_struct;
+    }
 }
 
 #[no_mangle]
-pub extern "C" fn process_exit_sighand(pcb: *mut process_control_block){
+pub extern "C" fn process_exit_sighand(pcb: *mut process_control_block) {
     // todo: 回收进程的sighand结构体
+    unsafe {
+        drop((*pcb).signal as *mut signal_struct);
+        (*pcb).signal = 0 as *mut crate::include::bindings::bindings::signal_struct;
+    }
 }

+ 3 - 8
kernel/src/process/initial_proc.rs

@@ -1,26 +1,21 @@
 use crate::{
     include::{
-        bindings::bindings::{atomic_t, spinlock_t, wait_queue_head_t, List},
+        bindings::bindings::{atomic_t, spinlock_t},
         DragonOS::signal::{sighand_struct, signal_struct, MAX_SIG_NUM},
     },
     ipc::signal::DEFAULT_SIGACTION,
 };
 
+/// @brief 初始进程的signal结构体
 #[no_mangle]
 pub static INITIAL_SIGNALS: signal_struct = signal_struct {
     sig_cnt: atomic_t { value: 0 },
 };
 
+/// @brief 初始进程的sighand结构体
 #[no_mangle]
 pub static mut INITIAL_SIGHAND: sighand_struct = sighand_struct {
     count: REFCOUNT_INIT!(1),
     siglock: spinlock_t { lock: 1 },
-    signal_fd_wqh: wait_queue_head_t {
-        lock: spinlock_t { lock: 1 },
-        wait_list: List {
-            prev: unsafe { &INITIAL_SIGHAND.signal_fd_wqh.wait_list as *const List } as *mut List,
-            next: unsafe { &INITIAL_SIGHAND.signal_fd_wqh.wait_list as *const List } as *mut List,
-        },
-    },
     action: [DEFAULT_SIGACTION; MAX_SIG_NUM as usize],
 };

+ 7 - 6
kernel/src/process/proc-types.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include <stdint.h>
 #include <DragonOS/signal.h>
 #include <common/wait_queue.h>
+#include <stdint.h>
 
 // 进程最大可拥有的文件描述符数量
 #define PROC_MAX_FD_NUM 16
@@ -32,11 +32,12 @@
 #define USER_DS (0x30)
 
 // 进程初始化时的数据拷贝标志位
-#define CLONE_FS (1UL << 0) // 在进程间共享打开的文件
-#define CLONE_SIGNAL (1UL << 1) // 克隆时,与父进程共享信号结构体
-#define CLONE_VM (1UL << 2) // 在进程间共享虚拟内存空间
-#define CLONE_SIGHAND (1UL << 3) // 克隆时,与父进程共享信号处理结构体
-
+#define CLONE_FS (1UL << 0)            // 在进程间共享打开的文件
+#define CLONE_SIGNAL (1UL << 1)        // 克隆时,与父进程共享信号结构体
+#define CLONE_VM (1UL << 2)            // 在进程间共享虚拟内存空间
+#define CLONE_SIGHAND (1UL << 3)       // 克隆时,与父进程共享信号处理结构体
+#define CLONE_CLEAR_SIGHAND (1UL << 4) // 克隆时,将原本被设置为SIG_IGNORE的信号,设置回SIG_DEFAULT
+#define CLONE_THREAD (1UL << 5)       // 拷贝线程
 #define PCB_NAME_LEN 16
 
 struct thread_struct