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

* refcount初始化

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

* new: 拷贝signal
bugfix: 解决拷贝sighand时的uaf问题
This commit is contained in:
login 2022-11-23 20:18:22 +08:00 committed by GitHub
parent 66f67c6a95
commit c8025a8879
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 226 additions and 62 deletions

View File

@ -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];
};

View File

@ -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)
}
}

View File

@ -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);
}
}

View File

@ -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
kernel/src/libs/list.rs Normal file
View File

@ -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;
}
}

View File

@ -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;

View File

@ -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 },
}
};
}

View File

@ -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 }
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);
}
0
// 在这里使用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;
}
// 拷贝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;
}
}

View File

@ -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],
};

View File

@ -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