mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 05:46:48 +00:00
Fix a bug of InitStack during doing fork+exec
This commit is contained in:
parent
d22277a3e6
commit
6bde87d33a
@ -106,7 +106,6 @@ pub struct InitStack {
|
|||||||
/// After initialized, `pos` points to the user stack pointer(rsp)
|
/// After initialized, `pos` points to the user stack pointer(rsp)
|
||||||
/// of the process.
|
/// of the process.
|
||||||
pos: Arc<AtomicUsize>,
|
pos: Arc<AtomicUsize>,
|
||||||
vmo: Vmo<Full>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for InitStack {
|
impl Clone for InitStack {
|
||||||
@ -114,8 +113,7 @@ impl Clone for InitStack {
|
|||||||
Self {
|
Self {
|
||||||
initial_top: self.initial_top,
|
initial_top: self.initial_top,
|
||||||
max_size: self.max_size,
|
max_size: self.max_size,
|
||||||
pos: self.pos.clone(),
|
pos: Arc::new(AtomicUsize::new(self.pos.load(Ordering::Relaxed))),
|
||||||
vmo: self.vmo.dup(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,36 +128,13 @@ impl InitStack {
|
|||||||
let initial_top = MAX_USERSPACE_VADDR - PAGE_SIZE * nr_pages_padding;
|
let initial_top = MAX_USERSPACE_VADDR - PAGE_SIZE * nr_pages_padding;
|
||||||
let max_size = INIT_STACK_SIZE;
|
let max_size = INIT_STACK_SIZE;
|
||||||
|
|
||||||
let vmo = {
|
|
||||||
let vmo_options = VmoOptions::<Full>::new(max_size);
|
|
||||||
vmo_options.alloc().unwrap()
|
|
||||||
};
|
|
||||||
Self {
|
Self {
|
||||||
initial_top,
|
initial_top,
|
||||||
max_size,
|
max_size,
|
||||||
pos: Arc::new(AtomicUsize::new(initial_top)),
|
pos: Arc::new(AtomicUsize::new(initial_top)),
|
||||||
vmo,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps the vmo of the init stack.
|
|
||||||
pub(super) fn map_init_stack_vmo(&self, root_vmar: &Vmar<Full>) -> Result<()> {
|
|
||||||
let vmar_map_options = {
|
|
||||||
let perms = VmPerms::READ | VmPerms::WRITE;
|
|
||||||
let map_addr = self.initial_top - self.max_size;
|
|
||||||
debug_assert!(map_addr % PAGE_SIZE == 0);
|
|
||||||
root_vmar
|
|
||||||
.new_map(self.max_size, perms)?
|
|
||||||
.offset(map_addr)
|
|
||||||
.vmo(self.vmo.dup().to_dyn())
|
|
||||||
};
|
|
||||||
|
|
||||||
vmar_map_options.build()?;
|
|
||||||
|
|
||||||
self.set_uninitialized();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the user stack top(highest address), used to setup rsp.
|
/// Returns the user stack top(highest address), used to setup rsp.
|
||||||
///
|
///
|
||||||
/// This method should only be called after the stack is initialized.
|
/// This method should only be called after the stack is initialized.
|
||||||
@ -170,32 +145,48 @@ impl InitStack {
|
|||||||
stack_top
|
stack_top
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a writer to initialize the content of an `InitStack`.
|
/// Maps the VMO of the init stack and constructs a writer to initialize its content.
|
||||||
pub(super) fn writer(
|
pub(super) fn map_and_write(
|
||||||
&self,
|
&self,
|
||||||
|
root_vmar: &Vmar<Full>,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
auxvec: AuxVec,
|
auxvec: AuxVec,
|
||||||
) -> InitStackWriter<'_> {
|
) -> Result<()> {
|
||||||
// The stack should be written only once.
|
self.set_uninitialized();
|
||||||
debug_assert!(!self.is_initialized());
|
|
||||||
InitStackWriter {
|
let vmo = {
|
||||||
|
let vmo_options = VmoOptions::<Full>::new(self.max_size);
|
||||||
|
vmo_options.alloc()?
|
||||||
|
};
|
||||||
|
let vmar_map_options = {
|
||||||
|
let perms = VmPerms::READ | VmPerms::WRITE;
|
||||||
|
let map_addr = self.initial_top - self.max_size;
|
||||||
|
debug_assert!(map_addr % PAGE_SIZE == 0);
|
||||||
|
root_vmar
|
||||||
|
.new_map(self.max_size, perms)?
|
||||||
|
.offset(map_addr)
|
||||||
|
.vmo(vmo.dup().to_dyn())
|
||||||
|
};
|
||||||
|
vmar_map_options.build()?;
|
||||||
|
|
||||||
|
let writer = InitStackWriter {
|
||||||
pos: self.pos.clone(),
|
pos: self.pos.clone(),
|
||||||
vmo: &self.vmo,
|
vmo,
|
||||||
argv,
|
argv,
|
||||||
envp,
|
envp,
|
||||||
auxvec,
|
auxvec,
|
||||||
map_addr: self.initial_top - self.max_size,
|
map_addr: self.initial_top - self.max_size,
|
||||||
}
|
};
|
||||||
|
writer.write()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a reader to parse the content of an `InitStack`.
|
/// Constructs a reader to parse the content of an `InitStack`.
|
||||||
/// The `InitStack` should only be read after initialized
|
/// The `InitStack` should only be read after initialized
|
||||||
pub(super) fn reader(&self) -> InitStackReader<'_> {
|
pub(super) fn reader(&self) -> InitStackReader {
|
||||||
debug_assert!(self.is_initialized());
|
debug_assert!(self.is_initialized());
|
||||||
InitStackReader {
|
InitStackReader {
|
||||||
base: self.pos(),
|
base: self.pos(),
|
||||||
vmo: &self.vmo,
|
|
||||||
map_addr: self.initial_top - self.max_size,
|
map_addr: self.initial_top - self.max_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,9 +205,9 @@ impl InitStack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A writer to initialize the content of an `InitStack`.
|
/// A writer to initialize the content of an `InitStack`.
|
||||||
pub struct InitStackWriter<'a> {
|
struct InitStackWriter {
|
||||||
pos: Arc<AtomicUsize>,
|
pos: Arc<AtomicUsize>,
|
||||||
vmo: &'a Vmo<Full>,
|
vmo: Vmo<Full>,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
auxvec: AuxVec,
|
auxvec: AuxVec,
|
||||||
@ -224,8 +215,8 @@ pub struct InitStackWriter<'a> {
|
|||||||
map_addr: usize,
|
map_addr: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InitStackWriter<'a> {
|
impl InitStackWriter {
|
||||||
pub fn write(mut self) -> Result<()> {
|
fn write(mut self) -> Result<()> {
|
||||||
// FIXME: Some OSes may put the first page of excutable file here
|
// FIXME: Some OSes may put the first page of excutable file here
|
||||||
// for interpreting elf headers.
|
// for interpreting elf headers.
|
||||||
|
|
||||||
@ -371,18 +362,17 @@ fn generate_random_for_aux_vec() -> [u8; 16] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A reader to parse the content of an `InitStack`.
|
/// A reader to parse the content of an `InitStack`.
|
||||||
pub struct InitStackReader<'a> {
|
pub struct InitStackReader {
|
||||||
base: Vaddr,
|
base: Vaddr,
|
||||||
vmo: &'a Vmo<Full>,
|
|
||||||
/// The mapping address of the `InitStack`.
|
/// The mapping address of the `InitStack`.
|
||||||
map_addr: usize,
|
map_addr: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InitStackReader<'a> {
|
impl InitStackReader {
|
||||||
/// Reads argc from the process init stack
|
/// Reads argc from the process init stack
|
||||||
pub fn argc(&self) -> Result<u64> {
|
pub fn argc(&self) -> Result<u64> {
|
||||||
let stack_base = self.init_stack_bottom();
|
let stack_base = self.init_stack_bottom();
|
||||||
Ok(self.vmo.read_val(stack_base - self.map_addr)?)
|
CurrentUserSpace::get().read_val(stack_base)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads argv from the process init stack
|
/// Reads argv from the process init stack
|
||||||
|
@ -19,8 +19,8 @@ pub use self::{
|
|||||||
heap::USER_HEAP_SIZE_LIMIT,
|
heap::USER_HEAP_SIZE_LIMIT,
|
||||||
init_stack::{
|
init_stack::{
|
||||||
aux_vec::{AuxKey, AuxVec},
|
aux_vec::{AuxKey, AuxVec},
|
||||||
InitStack, InitStackReader, InitStackWriter, INIT_STACK_SIZE, MAX_ARGV_NUMBER, MAX_ARG_LEN,
|
InitStack, InitStackReader, INIT_STACK_SIZE, MAX_ARGV_NUMBER, MAX_ARG_LEN, MAX_ENVP_NUMBER,
|
||||||
MAX_ENVP_NUMBER, MAX_ENV_LEN,
|
MAX_ENV_LEN,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::{prelude::*, vm::vmar::Vmar};
|
use crate::{prelude::*, vm::vmar::Vmar};
|
||||||
@ -83,7 +83,6 @@ impl ProcessVm {
|
|||||||
pub fn alloc() -> Self {
|
pub fn alloc() -> Self {
|
||||||
let root_vmar = Vmar::<Full>::new_root();
|
let root_vmar = Vmar::<Full>::new_root();
|
||||||
let init_stack = InitStack::new();
|
let init_stack = InitStack::new();
|
||||||
init_stack.map_init_stack_vmo(&root_vmar).unwrap();
|
|
||||||
let heap = Heap::new();
|
let heap = Heap::new();
|
||||||
heap.alloc_and_map_vmo(&root_vmar).unwrap();
|
heap.alloc_and_map_vmo(&root_vmar).unwrap();
|
||||||
Self {
|
Self {
|
||||||
@ -120,13 +119,14 @@ impl ProcessVm {
|
|||||||
self.init_stack.user_stack_top()
|
self.init_stack.user_stack_top()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn init_stack_writer(
|
pub(super) fn map_and_write_init_stack(
|
||||||
&self,
|
&self,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
aux_vec: AuxVec,
|
aux_vec: AuxVec,
|
||||||
) -> InitStackWriter {
|
) -> Result<()> {
|
||||||
self.init_stack.writer(argv, envp, aux_vec)
|
self.init_stack
|
||||||
|
.map_and_write(self.root_vmar(), argv, envp, aux_vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn heap(&self) -> &Heap {
|
pub(super) fn heap(&self) -> &Heap {
|
||||||
@ -136,7 +136,6 @@ impl ProcessVm {
|
|||||||
/// Clears existing mappings and then maps stack and heap vmo.
|
/// Clears existing mappings and then maps stack and heap vmo.
|
||||||
pub(super) fn clear_and_map(&self) {
|
pub(super) fn clear_and_map(&self) {
|
||||||
self.root_vmar.clear().unwrap();
|
self.root_vmar.clear().unwrap();
|
||||||
self.init_stack.map_init_stack_vmo(&self.root_vmar).unwrap();
|
|
||||||
self.heap.alloc_and_map_vmo(&self.root_vmar).unwrap();
|
self.heap.alloc_and_map_vmo(&self.root_vmar).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,7 @@ pub fn load_elf_to_vm(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let init_stack_writer = process_vm.init_stack_writer(argv, envp, aux_vec);
|
process_vm.map_and_write_init_stack(argv, envp, aux_vec)?;
|
||||||
init_stack_writer.write().unwrap();
|
|
||||||
|
|
||||||
let user_stack_top = process_vm.user_stack_top();
|
let user_stack_top = process_vm.user_stack_top();
|
||||||
Ok(ElfLoadInfo {
|
Ok(ElfLoadInfo {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user