Align execve argument limits with Linux

This commit is contained in:
jiangjianfeng 2025-07-08 06:12:51 +00:00 committed by Ruihan Li
parent e5c5bc7992
commit 010da31b3e
4 changed files with 25 additions and 20 deletions

View File

@ -27,9 +27,7 @@ pub use process::{
Pid, Process, ProcessGroup, Session, Sid, Terminal,
};
pub use process_filter::ProcessFilter;
pub use process_vm::{
renew_vm_and_map, MAX_ARGV_NUMBER, MAX_ARG_LEN, MAX_ENVP_NUMBER, MAX_ENV_LEN,
};
pub use process_vm::{renew_vm_and_map, MAX_LEN_STRING_ARG, MAX_NR_STRING_ARGS};
pub use program_loader::{check_executable_file, ProgramToLoad};
pub use rlimit::ResourceType;
pub use term_status::TermStatus;

View File

@ -42,14 +42,17 @@ pub mod aux_vec;
/// Set the initial stack size to 8 megabytes, following the default Linux stack size limit.
pub const INIT_STACK_SIZE: usize = 8 * 1024 * 1024; // 8 MB
/// The max number of arguments that can be used to creating a new process.
pub const MAX_ARGV_NUMBER: usize = 128;
/// The max number of environmental variables that can be used to creating a new process.
pub const MAX_ENVP_NUMBER: usize = 128;
/// The max length of each argument to create a new process.
pub const MAX_ARG_LEN: usize = 2048;
/// The max length of each environmental variable (the total length of key-value pair) to create a new process.
pub const MAX_ENV_LEN: usize = 128;
/// The maximum number of argument or environment strings that can be supplied to
/// the `execve` system call.
///
/// Reference: <https://elixir.bootlin.com/linux/v6.15/source/include/uapi/linux/binfmts.h#L15>.
pub const MAX_NR_STRING_ARGS: usize = i32::MAX as usize;
/// The maximum size, in bytes, of a single argument or environment string
/// (`argv` / `envp`) accepted by `execve`.
///
/// Reference: <https://elixir.bootlin.com/linux/v6.15/source/include/uapi/linux/binfmts.h#L16>.
pub const MAX_LEN_STRING_ARG: usize = PAGE_SIZE * 32;
/*
* Illustration of the virtual memory space containing the processes' init stack:
@ -399,7 +402,7 @@ impl InitStackReader<'_> {
};
let argc = frame.read_val::<u64>(stack_base - page_base_addr)?;
if argc > MAX_ARGV_NUMBER as u64 {
if argc > MAX_NR_STRING_ARGS as u64 {
return_errno_with_message!(Errno::EINVAL, "argc is corrupted");
}
@ -435,7 +438,7 @@ impl InitStackReader<'_> {
.checked_sub(page_base_addr)
.ok_or_else(|| Error::with_message(Errno::EINVAL, "arg_ptr is corrupted"))?;
let mut arg_reader = frame.reader().to_fallible();
arg_reader.skip(arg_offset).limit(MAX_ARG_LEN);
arg_reader.skip(arg_offset).limit(MAX_LEN_STRING_ARG);
arg_reader.read_cstring()?
};
argv.push(arg);
@ -472,7 +475,7 @@ impl InitStackReader<'_> {
let mut envp_ptr_reader = frame.reader();
envp_ptr_reader.skip(read_offset - page_base_addr);
for _ in 0..MAX_ENVP_NUMBER {
for _ in 0..MAX_NR_STRING_ARGS {
let env = {
let envp_ptr = envp_ptr_reader.read_val::<Vaddr>()?;
@ -484,7 +487,7 @@ impl InitStackReader<'_> {
.checked_sub(page_base_addr)
.ok_or_else(|| Error::with_message(Errno::EINVAL, "envp is corrupted"))?;
let mut envp_reader = frame.reader().to_fallible();
envp_reader.skip(envp_offset).limit(MAX_ENV_LEN);
envp_reader.skip(envp_offset).limit(MAX_LEN_STRING_ARG);
envp_reader.read_cstring()?
};
envp.push(env);

View File

@ -20,8 +20,7 @@ pub use self::{
heap::USER_HEAP_SIZE_LIMIT,
init_stack::{
aux_vec::{AuxKey, AuxVec},
InitStack, InitStackReader, INIT_STACK_SIZE, MAX_ARGV_NUMBER, MAX_ARG_LEN, MAX_ENVP_NUMBER,
MAX_ENV_LEN,
InitStack, InitStackReader, INIT_STACK_SIZE, MAX_LEN_STRING_ARG, MAX_NR_STRING_ARGS,
},
};
use crate::{prelude::*, vm::vmar::Vmar};

View File

@ -16,7 +16,7 @@ use crate::{
prelude::*,
process::{
check_executable_file, posix_thread::ThreadName, renew_vm_and_map, Credentials, Process,
ProgramToLoad, MAX_ARGV_NUMBER, MAX_ARG_LEN, MAX_ENVP_NUMBER, MAX_ENV_LEN,
ProgramToLoad, MAX_LEN_STRING_ARG, MAX_NR_STRING_ARGS,
},
};
@ -95,8 +95,13 @@ fn do_execve(
} = ctx;
let executable_path = elf_file.abs_path();
let argv = read_cstring_vec(argv_ptr_ptr, MAX_ARGV_NUMBER, MAX_ARG_LEN, ctx)?;
let envp = read_cstring_vec(envp_ptr_ptr, MAX_ENVP_NUMBER, MAX_ENV_LEN, ctx)?;
// FIXME: A malicious user could cause a kernel panic by exhausting available memory.
// Currently, the implementation reads up to `MAX_NR_STRING_ARGS` arguments, each up to
// `MAX_LEN_STRING_ARG` in length, without first verifying the total combined size.
// To prevent excessive memory allocation, a preliminary check should sum the lengths
// of all strings to enforce a sensible overall limit.
let argv = read_cstring_vec(argv_ptr_ptr, MAX_NR_STRING_ARGS, MAX_LEN_STRING_ARG, ctx)?;
let envp = read_cstring_vec(envp_ptr_ptr, MAX_NR_STRING_ARGS, MAX_LEN_STRING_ARG, ctx)?;
debug!(
"filename: {:?}, argv = {:?}, envp = {:?}",
executable_path, argv, envp