bugfix: 解决取消低地址映射时,错误的把重映射的物理页释放,从而导致的use after free问题。 (#321)

This commit is contained in:
LoGin 2023-08-07 01:38:52 +08:00 committed by GitHub
parent 729a96ef47
commit 26887c6334
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 22 additions and 15 deletions

View File

@ -610,10 +610,10 @@ impl LowAddressRemapping {
assert!(mapper.as_mut().is_some()); assert!(mapper.as_mut().is_some());
for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) { for i in 0..(Self::REMAP_SIZE / MMArch::PAGE_SIZE) {
let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE); let vaddr = VirtAddr::new(i * MMArch::PAGE_SIZE);
let flusher = mapper let (_, _, flusher) = mapper
.as_mut() .as_mut()
.unwrap() .unwrap()
.unmap(vaddr, true) .unmap_phys(vaddr, true)
.expect("Failed to unmap frame"); .expect("Failed to unmap frame");
if flush == false { if flush == false {
flusher.ignore(); flusher.ignore();

View File

@ -1,6 +1,5 @@
#include "multiboot2.h" #include "multiboot2.h"
#include <common/glib.h> #include <common/glib.h>
#include <common/kprint.h> #include <common/kprint.h>
uintptr_t multiboot2_boot_info_addr; uintptr_t multiboot2_boot_info_addr;
@ -11,8 +10,7 @@ bool multiboot2_init(void)
{ {
uintptr_t *addr = (uintptr_t *)multiboot2_boot_info_addr; uintptr_t *addr = (uintptr_t *)multiboot2_boot_info_addr;
if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC) if (multiboot2_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
; return false;
return false;
// addr+0 处保存了大小 // addr+0 处保存了大小
multiboot2_boot_info_size = *(unsigned int *)addr; multiboot2_boot_info_size = *(unsigned int *)addr;
return true; return true;
@ -24,7 +22,7 @@ void multiboot2_iter(bool (*_fun)(const struct iter_data_t *, void *, unsigned i
uintptr_t addr = multiboot2_boot_info_addr; uintptr_t addr = multiboot2_boot_info_addr;
// 接下来的第8字节开始为 tag 信息 // 接下来的第8字节开始为 tag 信息
struct iter_data_t *tag = (struct iter_data_t *)((void*)addr + 8); struct iter_data_t *tag = (struct iter_data_t *)((void *)addr + 8);
for (; tag->type != MULTIBOOT_TAG_TYPE_END; for (; tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8))) tag = (struct iter_data_t *)((uint8_t *)tag + ALIGN(tag->size, 8)))
{ {

View File

@ -3,6 +3,6 @@ pub mod fat;
pub mod mbr; pub mod mbr;
pub mod procfs; pub mod procfs;
pub mod ramfs; pub mod ramfs;
pub mod syscall;
pub mod sysfs; pub mod sysfs;
pub mod vfs; pub mod vfs;
pub mod syscall;

View File

@ -1,3 +1,4 @@
#![allow(dead_code)]
use crate::{ use crate::{
kwarn, kwarn,
libs::{rwlock::RwLock, spinlock::SpinLock}, libs::{rwlock::RwLock, spinlock::SpinLock},

View File

@ -7,7 +7,7 @@ use crate::arch::MMArch;
use crate::mm::allocator::bump::BumpAllocator; use crate::mm::allocator::bump::BumpAllocator;
use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage}; use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage};
use crate::mm::{MemoryManagementArch, PhysAddr, VirtAddr}; use crate::mm::{MemoryManagementArch, PhysAddr, VirtAddr};
use crate::{kdebug, kerror, kwarn}; use crate::{kdebug, kwarn};
use core::cmp::{max, min}; use core::cmp::{max, min};
use core::fmt::Debug; use core::fmt::Debug;
use core::intrinsics::{likely, unlikely}; use core::intrinsics::{likely, unlikely};
@ -207,7 +207,8 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
assert!(remain_bytes < (1 << MAX_ORDER - 1)); assert!(remain_bytes < (1 << MAX_ORDER - 1));
for i in (MIN_ORDER..MAX_ORDER).rev() { for i in (MIN_ORDER..MAX_ORDER).rev() {
if remain_bytes & (1 << i) != 0 { if remain_bytes >= (1 << i) {
assert!(paddr & ((1 << i) - 1) == 0);
let page_list_paddr: PhysAddr = free_area[Self::order2index(i as u8)]; let page_list_paddr: PhysAddr = free_area[Self::order2index(i as u8)];
let mut page_list: PageList<A> = Self::read_page(page_list_paddr); let mut page_list: PageList<A> = Self::read_page(page_list_paddr);
@ -281,8 +282,6 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
let mut page_list_addr = self.free_area[Self::order2index(spec_order)]; let mut page_list_addr = self.free_area[Self::order2index(spec_order)];
let mut page_list: PageList<A> = Self::read_page(page_list_addr); let mut page_list: PageList<A> = Self::read_page(page_list_addr);
// kdebug!("page_list={page_list:?}");
// 循环删除头部的空闲链表页 // 循环删除头部的空闲链表页
while page_list.entry_num == 0 { while page_list.entry_num == 0 {
let next_page_list_addr = page_list.next_page; let next_page_list_addr = page_list.next_page;
@ -315,8 +314,15 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
page_list.entry_num - 1, page_list.entry_num - 1,
)) ))
}; };
// 清除该entry
unsafe {
A::write(
Self::entry_virt_addr(page_list_addr, page_list.entry_num - 1),
PhysAddr::new(0),
)
};
if entry.is_null() { if entry.is_null() {
kerror!( panic!(
"entry is null, entry={:?}, order={}, entry_num = {}", "entry is null, entry={:?}, order={}, entry_num = {}",
entry, entry,
spec_order, spec_order,
@ -324,6 +330,7 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
); );
} }
// kdebug!("entry={entry:?}"); // kdebug!("entry={entry:?}");
// 更新page_list的entry_num // 更新page_list的entry_num
page_list.entry_num -= 1; page_list.entry_num -= 1;
let tmp_current_entry_num = page_list.entry_num; let tmp_current_entry_num = page_list.entry_num;
@ -344,7 +351,7 @@ impl<A: MemoryManagementArch> BuddyAllocator<A> {
// 检测entry 是否对齐 // 检测entry 是否对齐
if !entry.check_aligned(1 << spec_order) { if !entry.check_aligned(1 << spec_order) {
panic!("entry={:?} is not aligned, spec_order={spec_order}, page_list.entry_num={}", entry,tmp_current_entry_num); panic!("entry={:?} is not aligned, spec_order={spec_order}, page_list.entry_num={}", entry, tmp_current_entry_num);
} }
return Some(entry); return Some(entry);
} }

View File

@ -12,7 +12,7 @@ output_dir=$(ROOT_PATH)/bin/user
CFLAGS := $(GLOBAL_CFLAGS) -I $(shell pwd)/libs -I $(shell pwd)/libs/libc/src/include -I $(shell pwd)/libs/libc/src/include/export CFLAGS := $(GLOBAL_CFLAGS) -I $(shell pwd)/libs -I $(shell pwd)/libs/libc/src/include -I $(shell pwd)/libs/libc/src/include/export
current_CFLAGS := $(CFLAGS) current_CFLAGS := $(CFLAGS)
DADK_VERSION = $(shell dadk -V | awk 'END {print $2}') DADK_VERSION=$(shell dadk -V | awk 'END {print $$2}')
# 最小的DADK版本 # 最小的DADK版本
MIN_DADK_VERSION = 0.1.2 MIN_DADK_VERSION = 0.1.2
DADK_CACHE_DIR = $(ROOT_PATH)/bin/dadk_cache DADK_CACHE_DIR = $(ROOT_PATH)/bin/dadk_cache
@ -37,9 +37,10 @@ ifeq ("$(DADK_VERSION)", "")
@echo "Auto installing dadk..." @echo "Auto installing dadk..."
CC=gcc AS=as AR=ar LD=ld OBJCOPY=objcopy NM=nm cargo install dadk CC=gcc AS=as AR=ar LD=ld OBJCOPY=objcopy NM=nm cargo install dadk
else else
# 如果DADK版本过低则自动更新
@echo "dadk version $(DADK_VERSION) installed" @echo "dadk version $(DADK_VERSION) installed"
# 如果DADK版本过低则自动更新 # 如果DADK版本过低则自动更新
ifeq ($(shell printf '%s\n' "$(DADK_VERSION)" "$(MIN_DADK_VERSION)" | sort -V | head -n1), $(MIN_DADK_VERSION)) ifneq ($(shell printf '%s\n%s' "$(DADK_VERSION)" "$(MIN_DADK_VERSION)" | sort -V | head -n1), $(MIN_DADK_VERSION))
@echo "dadk version is too low, please update to $(MIN_DADK_VERSION) or higher version" @echo "dadk version is too low, please update to $(MIN_DADK_VERSION) or higher version"
@echo "Updating dadk..." @echo "Updating dadk..."
CC=gcc AS=as AR=ar LD=ld OBJCOPY=objcopy NM=nm cargo install dadk || (echo "dadk update failed" && exit 1) CC=gcc AS=as AR=ar LD=ld OBJCOPY=objcopy NM=nm cargo install dadk || (echo "dadk update failed" && exit 1)