Skip to content

Commit

Permalink
x64: Fix memory leaks in a process internal buffers (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
nuta authored Dec 19, 2021
1 parent 5b7d70e commit c0ef730
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 46 deletions.
98 changes: 56 additions & 42 deletions kernel/arch/x64/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ use crate::result::Result;
use crate::{arch::KERNEL_STACK_SIZE, process::signal::Signal};
use crossbeam::atomic::AtomicCell;
use kerla_runtime::address::{UserVAddr, VAddr};
use kerla_runtime::page_allocator::{alloc_pages_owned, OwnedPages};
use kerla_runtime::{
arch::x64_specific::{cpu_local_head, TSS, USER_CS64, USER_DS, USER_RPL},
arch::PtRegs,
arch::PAGE_SIZE,
page_allocator::{alloc_pages, AllocPageFlags},
page_allocator::AllocPageFlags,
};
use x86::current::segmentation::wrfsbase;

#[repr(C, packed)]
pub struct Process {
rsp: UnsafeCell<u64>,
pub(super) fsbase: AtomicCell<u64>,
pub(super) xsave_area: Option<VAddr>,
interrupt_stack: VAddr,
syscall_stack: VAddr,
pub(super) xsave_area: Option<OwnedPages>,
kernel_stack: OwnedPages,
// FIXME: Do we really need these stacks?
interrupt_stack: OwnedPages,
syscall_stack: OwnedPages,
}

unsafe impl Sync for Process {}
Expand All @@ -39,18 +42,21 @@ unsafe fn push_stack(mut rsp: *mut u64, value: u64) -> *mut u64 {
impl Process {
#[allow(unused)]
pub fn new_kthread(ip: VAddr, sp: VAddr) -> Process {
let interrupt_stack = alloc_pages(
let interrupt_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack")
.as_vaddr();
let syscall_stack = alloc_pages(
.expect("failed to allocate kernel stack");
let syscall_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack")
.as_vaddr();
.expect("failed to allocate kernel stack");
let kernel_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocat kernel stack");

let rsp = unsafe {
let mut rsp: *mut u64 = sp.as_mut_ptr();
Expand All @@ -77,28 +83,31 @@ impl Process {
xsave_area: None,
interrupt_stack,
syscall_stack,
kernel_stack,
}
}

pub fn new_user_thread(ip: UserVAddr, sp: UserVAddr, kernel_sp: VAddr) -> Process {
let interrupt_stack = alloc_pages(
pub fn new_user_thread(ip: UserVAddr, sp: UserVAddr) -> Process {
let kernel_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack")
.as_vaddr();
let syscall_stack = alloc_pages(
.expect("failed to allocat kernel stack");
let interrupt_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack")
.as_vaddr();
// TODO: Check the size of XSAVE area.
let xsave_area = alloc_pages(1, AllocPageFlags::KERNEL)
.expect("failed to allocate xsave area")
.as_vaddr();
.expect("failed to allocate kernel stack");
let syscall_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack");
let xsave_area =
alloc_pages_owned(1, AllocPageFlags::KERNEL).expect("failed to allocate xsave area");

let rsp = unsafe {
let kernel_sp = kernel_stack.as_vaddr().add(KERNEL_STACK_SIZE);
let mut rsp: *mut u64 = kernel_sp.as_mut_ptr();

// Registers to be restored by IRET.
Expand Down Expand Up @@ -127,41 +136,47 @@ impl Process {
xsave_area: Some(xsave_area),
interrupt_stack,
syscall_stack,
kernel_stack,
}
}

pub fn new_idle_thread() -> Process {
let interrupt_stack = alloc_pages(
let interrupt_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack")
.as_vaddr();
let syscall_stack = alloc_pages(
.expect("failed to allocate kernel stack");
let syscall_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocate kernel stack")
.as_vaddr();
.expect("failed to allocate kernel stack");
let kernel_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocat kernel stack");

Process {
rsp: UnsafeCell::new(0),
fsbase: AtomicCell::new(0),
xsave_area: None,
interrupt_stack,
syscall_stack,
kernel_stack,
}
}

pub fn fork(&self, frame: &PtRegs) -> Result<Process> {
// TODO: Check the size of XSAVE area.
let xsave_area = alloc_pages(1, AllocPageFlags::KERNEL)
.expect("failed to allocate xsave area")
.as_vaddr();

let xsave_area =
alloc_pages_owned(1, AllocPageFlags::KERNEL).expect("failed to allocate xsave area");
let kernel_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed to allocat kernel stack");
let rsp = unsafe {
let kernel_sp = alloc_pages(KERNEL_STACK_SIZE / PAGE_SIZE, AllocPageFlags::KERNEL)
.expect("failed allocate kernel stack");
let kernel_sp = kernel_stack.as_vaddr().add(KERNEL_STACK_SIZE);
let mut rsp: *mut u64 = kernel_sp.as_mut_ptr();

// Registers to be restored by IRET.
Expand Down Expand Up @@ -194,25 +209,24 @@ impl Process {
rsp
};

let interrupt_stack = alloc_pages(
let interrupt_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed allocate kernel stack")
.as_vaddr();
let syscall_stack = alloc_pages(
.expect("failed allocate kernel stack");
let syscall_stack = alloc_pages_owned(
KERNEL_STACK_SIZE / PAGE_SIZE,
AllocPageFlags::KERNEL | AllocPageFlags::DIRTY_OK,
)
.expect("failed allocate kernel stack")
.as_vaddr();
.expect("failed allocate kernel stack");

Ok(Process {
rsp: UnsafeCell::new(rsp as u64),
fsbase: AtomicCell::new(self.fsbase.load()),
xsave_area: Some(xsave_area),
interrupt_stack,
syscall_stack,
kernel_stack,
})
}

Expand Down Expand Up @@ -275,9 +289,9 @@ pub fn switch_thread(prev: &Process, next: &Process) {
let head = cpu_local_head();

// Switch the kernel stack.
head.rsp0 = (next.syscall_stack.value() + KERNEL_STACK_SIZE) as u64;
head.rsp0 = (next.syscall_stack.as_vaddr().value() + KERNEL_STACK_SIZE) as u64;
TSS.as_mut()
.set_rsp0((next.interrupt_stack.value() + KERNEL_STACK_SIZE) as u64);
.set_rsp0((next.interrupt_stack.as_vaddr().value() + KERNEL_STACK_SIZE) as u64);

// Save and restore the XSAVE area (i.e. XMM/YMM registrers).
unsafe {
Expand Down
6 changes: 2 additions & 4 deletions kernel/process/process.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
arch::{self, KERNEL_STACK_SIZE, USER_STACK_TOP},
arch::{self, USER_STACK_TOP},
ctypes::*,
fs::{
devfs::SERIAL_TTY,
Expand Down Expand Up @@ -189,8 +189,6 @@ impl Process {

let entry = setup_userspace(executable_path, argv, &[], &root_fs)?;
let pid = PId::new(1);
let stack_bottom = alloc_pages(KERNEL_STACK_SIZE / PAGE_SIZE, AllocPageFlags::KERNEL)?;
let kernel_sp = stack_bottom.as_vaddr().add(KERNEL_STACK_SIZE);
let process_group = ProcessGroup::new(PgId::new(1));
let process = Arc::new(Process {
is_idle: false,
Expand All @@ -200,7 +198,7 @@ impl Process {
children: SpinLock::new(Vec::new()),
state: AtomicCell::new(ProcessState::Runnable),
cmdline: AtomicRefCell::new(Cmdline::from_argv(argv)),
arch: arch::Process::new_user_thread(entry.ip, entry.user_sp, kernel_sp),
arch: arch::Process::new_user_thread(entry.ip, entry.user_sp),
vm: AtomicRefCell::new(Some(Arc::new(SpinLock::new(entry.vm)))),
opened_files: SpinLock::new(opened_files),
root_fs,
Expand Down

0 comments on commit c0ef730

Please sign in to comment.