mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-14 20:26:48 +00:00
修正rwlock有的地方由于未使用ManuallyDrop导致的use after free && spinlock守卫新增leak,spinlock新增force unlock功能.(#329)
1.修正rwlock有的地方由于未使用ManuallyDrop导致的use after free 2. spinlock守卫新增leak,spinlock新增force unlock功能.
This commit is contained in:
parent
c3dad0011d
commit
90a0a49048
@ -292,12 +292,19 @@ impl<T> From<T> for RwLock<T> {
|
||||
}
|
||||
|
||||
impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
|
||||
/// @brief 释放守卫,获得保护的值的不可变引用
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
|
||||
/// 因此必须小心的手动维护好preempt count。
|
||||
///
|
||||
/// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 释放守卫,获得保护的值的不可变引用
|
||||
pub fn leak(this: Self) -> &'rwlock T {
|
||||
let Self { data, .. } = this;
|
||||
return unsafe { &*data };
|
||||
pub unsafe fn leak(this: Self) -> &'rwlock T {
|
||||
let this = ManuallyDrop::new(this);
|
||||
return unsafe { &*this.data };
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,9 +370,16 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 返回内部数据的引用,消除锁
|
||||
pub fn leak(this: Self) -> &'rwlock T {
|
||||
let this = ManuallyDrop::new(this);
|
||||
/// @brief 返回内部数据的引用,消除守卫
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
|
||||
/// 因此必须小心的手动维护好preempt count。
|
||||
///
|
||||
/// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
|
||||
pub unsafe fn leak(this: Self) -> &'rwlock T {
|
||||
let this: ManuallyDrop<RwLockUpgradableGuard<'_, T>> = ManuallyDrop::new(this);
|
||||
|
||||
unsafe { &*this.data }
|
||||
}
|
||||
@ -374,8 +388,15 @@ impl<'rwlock, T> RwLockUpgradableGuard<'rwlock, T> {
|
||||
impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
|
||||
#[allow(dead_code)]
|
||||
#[inline]
|
||||
/// @brief 返回内部数据的引用,消除锁
|
||||
pub fn leak(this: Self) -> &'rwlock T {
|
||||
/// @brief 返回内部数据的引用,消除守卫
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
|
||||
/// 因此必须小心的手动维护好preempt count。
|
||||
///
|
||||
/// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
|
||||
pub unsafe fn leak(this: Self) -> &'rwlock T {
|
||||
let this = ManuallyDrop::new(this);
|
||||
|
||||
return unsafe { &*this.data };
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
use core::cell::UnsafeCell;
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::ptr::read_volatile;
|
||||
|
||||
@ -107,6 +108,11 @@ impl RawSpinlock {
|
||||
self.0.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
/// 解锁,但是不更改preempt count
|
||||
unsafe fn unlock_no_preempt(&self) {
|
||||
self.0.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
/// @brief 放锁并开中断
|
||||
pub fn unlock_irq(&self) {
|
||||
self.unlock();
|
||||
@ -170,6 +176,24 @@ pub struct SpinLockGuard<'a, T: 'a> {
|
||||
flag: usize,
|
||||
}
|
||||
|
||||
impl<'a, T: 'a> SpinLockGuard<'a, T> {
|
||||
/// 泄露自旋锁的守卫,返回一个可变的引用
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// 由于这样做可能导致守卫在另一个线程中被释放,从而导致pcb的preempt count不正确,
|
||||
/// 因此必须小心的手动维护好preempt count。
|
||||
///
|
||||
/// 并且,leak还可能导致锁的状态不正确。因此请仔细考虑是否真的需要使用这个函数。
|
||||
#[inline]
|
||||
pub unsafe fn leak(this: Self) -> &'a mut T {
|
||||
// Use ManuallyDrop to avoid stacked-borrow invalidation
|
||||
let this = ManuallyDrop::new(this);
|
||||
// We know statically that only we are referencing data
|
||||
unsafe { &mut *this.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
/// 向编译器保证,SpinLock在线程之间是安全的.
|
||||
/// 其中要求类型T实现了Send这个Trait
|
||||
unsafe impl<T> Sync for SpinLock<T> where T: Send {}
|
||||
@ -223,6 +247,16 @@ impl<T> SpinLock<T> {
|
||||
}
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
}
|
||||
|
||||
/// 强制解锁,并且不更改preempt count
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// 由于这样做可能导致preempt count不正确,因此必须小心的手动维护好preempt count。
|
||||
/// 如非必要,请不要使用这个函数。
|
||||
pub unsafe fn force_unlock(&self) {
|
||||
self.lock.unlock_no_preempt();
|
||||
}
|
||||
}
|
||||
|
||||
/// 实现Deref trait,支持通过获取SpinLockGuard来获取临界区数据的不可变引用
|
||||
|
Loading…
x
Reference in New Issue
Block a user