Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions libkernel/src/memory/proc_vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,35 @@ pub mod vmarea;

const BRK_PERMISSIONS: VMAPermissions = VMAPermissions::rw();

/// Address bounds for the argv and environment strings in a process image.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ArgsEnvBounds {
/// First byte of the argument strings.
pub arg_start: VA,
/// One byte past the argument strings.
pub arg_end: VA,
/// First byte of the environment strings.
pub env_start: VA,
/// One byte past the environment strings.
pub env_end: VA,
}

impl Default for ArgsEnvBounds {
fn default() -> Self {
Self {
arg_start: VA::null(),
arg_end: VA::null(),
env_start: VA::null(),
env_end: VA::null(),
}
}
}

/// The virtual memory state of a user-space process.
pub struct ProcessVM<AS: UserAddressSpace> {
mm: MemoryMap<AS>,
brk: VirtMemoryRegion,
args_env_bounds: ArgsEnvBounds,
}

impl<AS: UserAddressSpace> ProcessVM<AS> {
Expand All @@ -35,7 +60,11 @@ impl<AS: UserAddressSpace> ProcessVM<AS> {

let brk = VirtMemoryRegion::new(vma.region.end_address().align_up(PAGE_SIZE), 0);

Self { mm, brk }
Self {
mm,
brk,
args_env_bounds: ArgsEnvBounds::default(),
}
}

/// Constructs a new Process VM structure from the given VMA. The heap is
Expand All @@ -47,7 +76,11 @@ impl<AS: UserAddressSpace> ProcessVM<AS> {

let brk = VirtMemoryRegion::new(vma.region.end_address().align_up(PAGE_SIZE), 0);

Ok(Self { mm, brk })
Ok(Self {
mm,
brk,
args_env_bounds: ArgsEnvBounds::default(),
})
}

/// Constructs a `ProcessVM` from an existing memory map.
Expand All @@ -66,6 +99,7 @@ impl<AS: UserAddressSpace> ProcessVM<AS> {
Self {
mm: map,
brk: VirtMemoryRegion::new(brk, 0),
args_env_bounds: ArgsEnvBounds::default(),
}
}

Expand All @@ -74,6 +108,7 @@ impl<AS: UserAddressSpace> ProcessVM<AS> {
Ok(Self {
mm: MemoryMap::new()?,
brk: VirtMemoryRegion::empty(),
args_env_bounds: ArgsEnvBounds::default(),
})
}

Expand Down Expand Up @@ -103,6 +138,36 @@ impl<AS: UserAddressSpace> ProcessVM<AS> {
self.brk.start_address()
}

/// Returns the argv/environment address bounds for this process image.
pub fn args_env_bounds(&self) -> ArgsEnvBounds {
self.args_env_bounds
}

/// Sets the argv/environment address bounds for this process image.
pub fn set_args_env_bounds(&mut self, bounds: ArgsEnvBounds) {
self.args_env_bounds = bounds;
}

/// Sets the first byte of the argument strings.
pub fn set_arg_start(&mut self, addr: VA) {
self.args_env_bounds.arg_start = addr;
}

/// Sets one byte past the argument strings.
pub fn set_arg_end(&mut self, addr: VA) {
self.args_env_bounds.arg_end = addr;
}

/// Sets the first byte of the environment strings.
pub fn set_env_start(&mut self, addr: VA) {
self.args_env_bounds.env_start = addr;
}

/// Sets one byte past the environment strings.
pub fn set_env_end(&mut self, addr: VA) {
self.args_env_bounds.env_end = addr;
}

/// Returns the current end address of the program break (heap).
pub fn current_brk(&self) -> VA {
self.brk.end_address()
Expand Down Expand Up @@ -178,6 +243,7 @@ impl<AS: UserAddressSpace> ProcessVM<AS> {
Ok(Self {
mm: self.mm.clone_as_cow()?,
brk: self.brk,
args_env_bounds: self.args_env_bounds,
})
}
}
Expand Down Expand Up @@ -207,6 +273,7 @@ mod tests {
let initial_brk_start = VA::from_value(0x1000 + PAGE_SIZE);
assert_eq!(vm.brk.start_address(), initial_brk_start);
assert_eq!(vm.brk.size(), 0);
assert_eq!(vm.args_env_bounds(), ArgsEnvBounds::default());
assert_eq!(vm.current_brk(), initial_brk_start);

// And the break region itself should not be mapped
Expand Down
2 changes: 1 addition & 1 deletion src/arch/arm64/exceptions/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ pub async fn handle_syscall(mut ctx: ProcessCtx) {
0xa1 => sys_sethostname(&ctx, TUA::from_value(arg1 as _), arg2 as _).await,
0xa3 => Err(KernelError::InvalidValue),
0xa6 => sys_umask(&ctx, arg1 as _).map_err(|e| match e {}),
0xa7 => sys_prctl(&ctx, arg1 as _, arg2, arg3).await,
0xa7 => sys_prctl(&ctx, arg1 as _, arg2, arg3, arg4, arg5).await,
0xa8 => sys_getcpu(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
0xa9 => sys_gettimeofday(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
0xaa => sys_settimeofday(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
Expand Down
9 changes: 5 additions & 4 deletions src/drivers/fs/proc/task/task_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ Threads:\t{tasks}\n",
}

let start_brk = vm.start_brk().value();
let args_env_bounds = vm.args_env_bounds();

let mut output = String::new();
output.push_str(&format!("{} ", task.process.tgid.value())); // pid
Expand Down Expand Up @@ -205,10 +206,10 @@ Threads:\t{tasks}\n",
output.push_str(&format!("{start_data} ")); // start_data
output.push_str(&format!("{end_data} ")); // end_data
output.push_str(&format!("{start_brk} ")); // start_brk
output.push_str(&format!("{} ", 0)); // arg_start
output.push_str(&format!("{} ", 0)); // arg_end
output.push_str(&format!("{} ", 0)); // env_start
output.push_str(&format!("{} ", 0)); // env_end
output.push_str(&format!("{} ", args_env_bounds.arg_start.value())); // arg_start
output.push_str(&format!("{} ", args_env_bounds.arg_end.value())); // arg_end
output.push_str(&format!("{} ", args_env_bounds.env_start.value())); // env_start
output.push_str(&format!("{} ", args_env_bounds.env_end.value())); // env_end
output.push_str(&format!("{} ", 0)); // exit_code
output.push('\n');
output
Expand Down
36 changes: 32 additions & 4 deletions src/process/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
address::{TUA, VA},
paging::permissions::PtePermissions,
proc_vm::{
ProcessVM,
ArgsEnvBounds, ProcessVM,
memory_map::MemoryMap,
vmarea::{VMAPermissions, VMArea, VMAreaKind},
},
Expand Down Expand Up @@ -181,13 +181,14 @@
vmas.push(stack_vma);

let mut mem_map = MemoryMap::from_vmas(vmas)?;
let stack_ptr = setup_user_stack(&mut mem_map, &argv, &envp, auxv)?;
let (stack_ptr, args_env_bounds) = setup_user_stack(&mut mem_map, &argv, &envp, auxv)?;

// We are now committed to the exec. Inform ptrace.
ptrace_stop(ctx, TracePoint::Exec).await;

let user_ctx = ArchImpl::new_user_context(entry_addr, stack_ptr);
let mut vm = ProcessVM::from_map(mem_map);
vm.set_args_env_bounds(args_env_bounds);

// We don't have to worry about actually calling for a full context switch
// here. Parts of the old process that are replaced will go out of scope and
Expand Down Expand Up @@ -237,7 +238,7 @@
.ok_or(ExecError::InvalidScriptFormat)?;
let parts: Vec<&str> = first_line[2..].split_whitespace().collect();
if parts.is_empty() {
return Err(ExecError::InvalidScriptFormat)?;

Check failure on line 241 in src/process/exec.rs

View workflow job for this annotation

GitHub Actions / build-test

unneeded `return` statement with `?` operator
}
let interp_path = parts[0];
let interp_args: Vec<String> = parts[1..].iter().map(|s| s.to_string()).collect();
Expand Down Expand Up @@ -292,7 +293,7 @@
argv: &[String],
envp: &[String],
mut auxv: Vec<u64>,
) -> Result<VA> {
) -> Result<(VA, ArgsEnvBounds)> {
// Calculate the space needed and the virtual addresses for all strings and
// pointers.
let mut string_addrs = Vec::new();
Expand All @@ -314,6 +315,33 @@

let (envp_addrs, argv_addrs) = string_addrs.split_at(envp.len());

let arg_start = argv_addrs
.first()
.copied()
.map(VA::from_value)
.unwrap_or_else(VA::null);
let arg_end = argv_addrs
.last()
.zip(argv.last())
.map(|(&addr, s)| VA::from_value(addr + s.len() + 1))
.unwrap_or_else(VA::null);
let env_start = envp_addrs
.first()
.copied()
.map(VA::from_value)
.unwrap_or_else(VA::null);
let env_end = envp_addrs
.last()
.zip(envp.last())
.map(|(&addr, s)| VA::from_value(addr + s.len() + 1))
.unwrap_or_else(VA::null);
let args_env_bounds = ArgsEnvBounds {
arg_start,
arg_end,
env_start,
env_end,
};

let mut info_block = Vec::<u64>::new();
info_block.push(argv.len() as u64); // argc
info_block.extend(argv_addrs.iter().map(|&addr| addr as u64));
Expand Down Expand Up @@ -384,7 +412,7 @@
.map_page(page.leak(), page_va, PtePermissions::rw(true))?;
}

Ok(VA::from_value(final_sp_val))
Ok((VA::from_value(final_sp_val), args_env_bounds))
}

// Dynamic linker path: map PT_INTERP interpreter and return start address of
Expand Down
Loading
Loading