Revert "`ProgramToLoad` only needs a `elf_inode: Arc<dyn Inode>` instead of a `Path`"

This reverts commit 71632a51b5.
This commit is contained in:
Wang Siyuan 2026-01-25 13:12:11 +00:00 committed by Tate, Hongliang Tian
parent 66ac28c4c2
commit fb8c9e0c27
4 changed files with 29 additions and 33 deletions

View File

@ -54,9 +54,8 @@ pub fn do_execve(
envp envp
); );
let elf_inode = elf_file.inode();
let program_to_load = let program_to_load =
ProgramToLoad::build_from_inode(elf_inode.clone(), &path_resolver, argv, envp)?; ProgramToLoad::build_from_file(elf_file.clone(), &path_resolver, argv, envp)?;
let new_vmar = Vmar::new(ProcessVm::new(elf_file.clone())); let new_vmar = Vmar::new(ProcessVm::new(elf_file.clone()));
let elf_load_info = program_to_load.load_to_vmar(new_vmar.as_ref(), &path_resolver)?; let elf_load_info = program_to_load.load_to_vmar(new_vmar.as_ref(), &path_resolver)?;

View File

@ -110,7 +110,7 @@ fn create_init_task(
let path_resolver = fs.resolver().read(); let path_resolver = fs.resolver().read();
let program_to_load = let program_to_load =
ProgramToLoad::build_from_inode(elf_path.inode().clone(), &path_resolver, argv, envp)?; ProgramToLoad::build_from_file(elf_path.clone(), &path_resolver, argv, envp)?;
let vmar = process.lock_vmar(); let vmar = process.lock_vmar();
let elf_load_info = program_to_load.load_to_vmar(vmar.unwrap(), &path_resolver)?; let elf_load_info = program_to_load.load_to_vmar(vmar.unwrap(), &path_resolver)?;
let elf_abs_path = path_resolver.make_abs_path(&elf_path).into_string(); let elf_abs_path = path_resolver.make_abs_path(&elf_path).into_string();

View File

@ -9,10 +9,7 @@ use super::{
relocate::RelocatedRange, relocate::RelocatedRange,
}; };
use crate::{ use crate::{
fs::{ fs::path::{FsPath, Path, PathResolver},
path::{FsPath, Path, PathResolver},
utils::Inode,
},
prelude::*, prelude::*,
process::{ process::{
process_vm::{AuxKey, AuxVec}, process_vm::{AuxKey, AuxVec},
@ -22,7 +19,6 @@ use crate::{
vm::{ vm::{
perms::VmPerms, perms::VmPerms,
vmar::{VMAR_CAP_ADDR, VMAR_LOWEST_ADDR, Vmar}, vmar::{VMAR_CAP_ADDR, VMAR_LOWEST_ADDR, Vmar},
vmo::Vmo,
}, },
}; };
@ -51,20 +47,20 @@ pub struct ElfLoadInfo {
/// initialize the init stack and heap. /// initialize the init stack and heap.
pub fn load_elf_to_vmar( pub fn load_elf_to_vmar(
vmar: &Vmar, vmar: &Vmar,
elf_inode: &Arc<dyn Inode>, elf_file: Path,
path_resolver: &PathResolver, path_resolver: &PathResolver,
elf_headers: ElfHeaders, elf_headers: ElfHeaders,
argv: Vec<CString>, argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
) -> Result<ElfLoadInfo> { ) -> Result<ElfLoadInfo> {
let ldso = lookup_and_parse_ldso(&elf_headers, elf_inode, path_resolver)?; let ldso = lookup_and_parse_ldso(&elf_headers, &elf_file, path_resolver)?;
#[cfg_attr( #[cfg_attr(
not(any(target_arch = "x86_64", target_arch = "riscv64")), not(any(target_arch = "x86_64", target_arch = "riscv64")),
expect(unused_mut) expect(unused_mut)
)] )]
let (elf_mapped_info, entry_point, mut aux_vec) = let (elf_mapped_info, entry_point, mut aux_vec) =
map_vmos_and_build_aux_vec(vmar, ldso, &elf_headers, elf_inode)?; map_vmos_and_build_aux_vec(vmar, ldso, &elf_headers, &elf_file)?;
// Map the vDSO and set the entry. // Map the vDSO and set the entry.
// Since the vDSO does not require being mapped to any specific address, // Since the vDSO does not require being mapped to any specific address,
@ -93,12 +89,12 @@ pub fn load_elf_to_vmar(
fn lookup_and_parse_ldso( fn lookup_and_parse_ldso(
headers: &ElfHeaders, headers: &ElfHeaders,
elf_inode: &Arc<dyn Inode>, elf_file: &Path,
path_resolver: &PathResolver, path_resolver: &PathResolver,
) -> Result<Option<(Path, ElfHeaders)>> { ) -> Result<Option<(Path, ElfHeaders)>> {
let ldso_file = { let ldso_file = {
let ldso_path = if let Some(interp_phdr) = headers.interp_phdr() { let ldso_path = if let Some(interp_phdr) = headers.interp_phdr() {
interp_phdr.read_ldso_path(elf_inode)? interp_phdr.read_ldso_path(elf_file.inode())?
} else { } else {
return Ok(None); return Ok(None);
}; };
@ -139,7 +135,7 @@ fn map_vmos_and_build_aux_vec(
vmar: &Vmar, vmar: &Vmar,
ldso: Option<(Path, ElfHeaders)>, ldso: Option<(Path, ElfHeaders)>,
parsed_elf: &ElfHeaders, parsed_elf: &ElfHeaders,
elf_inode: &Arc<dyn Inode>, elf_file: &Path,
) -> Result<(ElfMappedInfo, Vaddr, AuxVec)> { ) -> Result<(ElfMappedInfo, Vaddr, AuxVec)> {
let ldso_load_info = if let Some((ldso_file, ldso_elf)) = ldso { let ldso_load_info = if let Some((ldso_file, ldso_elf)) = ldso {
Some(load_ldso(vmar, &ldso_file, &ldso_elf)?) Some(load_ldso(vmar, &ldso_file, &ldso_elf)?)
@ -147,7 +143,7 @@ fn map_vmos_and_build_aux_vec(
None None
}; };
let elf_mapped_info = map_segment_vmos(parsed_elf, vmar, elf_inode, ldso_load_info.is_some())?; let elf_mapped_info = map_segment_vmos(parsed_elf, vmar, elf_file, ldso_load_info.is_some())?;
let mut aux_vec = { let mut aux_vec = {
let ldso_base = ldso_load_info let ldso_base = ldso_load_info
@ -157,7 +153,7 @@ fn map_vmos_and_build_aux_vec(
}; };
// Set AT_SECURE based on setuid/setgid bits of the executable file. // Set AT_SECURE based on setuid/setgid bits of the executable file.
let mode = elf_inode.mode()?; let mode = elf_file.inode().mode()?;
let secure = if mode.has_set_uid() || mode.has_set_gid() { let secure = if mode.has_set_uid() || mode.has_set_gid() {
1 1
} else { } else {
@ -192,7 +188,7 @@ struct LdsoLoadInfo {
} }
fn load_ldso(vmar: &Vmar, ldso_file: &Path, ldso_elf: &ElfHeaders) -> Result<LdsoLoadInfo> { fn load_ldso(vmar: &Vmar, ldso_file: &Path, ldso_elf: &ElfHeaders) -> Result<LdsoLoadInfo> {
let elf_mapped_info = map_segment_vmos(ldso_elf, vmar, ldso_file.inode(), false)?; let elf_mapped_info = map_segment_vmos(ldso_elf, vmar, ldso_file, false)?;
let range = elf_mapped_info.full_range; let range = elf_mapped_info.full_range;
let entry_point = range let entry_point = range
.relocated_addr_of(ldso_elf.entry_point()) .relocated_addr_of(ldso_elf.entry_point())
@ -226,7 +222,7 @@ struct ElfMappedInfo {
fn map_segment_vmos( fn map_segment_vmos(
elf: &ElfHeaders, elf: &ElfHeaders,
vmar: &Vmar, vmar: &Vmar,
elf_inode: &Arc<dyn Inode>, elf_file: &Path,
has_interpreter: bool, has_interpreter: bool,
) -> Result<ElfMappedInfo> { ) -> Result<ElfMappedInfo> {
let elf_va_range = elf.calc_total_vaddr_bounds(); let elf_va_range = elf.calc_total_vaddr_bounds();
@ -330,14 +326,11 @@ fn map_segment_vmos(
let relocated_range = RelocatedRange::new(elf_va_range, map_range.start) let relocated_range = RelocatedRange::new(elf_va_range, map_range.start)
.expect("`map_range` should not overflow"); .expect("`map_range` should not overflow");
let Some(elf_vmo) = elf_inode.page_cache() else {
return_errno_with_message!(Errno::ENOEXEC, "the executable has no page cache");
};
for loadable_phdr in elf.loadable_phdrs() { for loadable_phdr in elf.loadable_phdrs() {
let map_at = relocated_range let map_at = relocated_range
.relocated_addr_of(loadable_phdr.virt_range().start) .relocated_addr_of(loadable_phdr.virt_range().start)
.expect("`calc_total_vaddr_bounds()` should cover all segments"); .expect("`calc_total_vaddr_bounds()` should cover all segments");
map_segment_vmo(loadable_phdr, &elf_vmo, vmar, map_at)?; map_segment_vmo(loadable_phdr, elf_file, vmar, map_at)?;
} }
// Calculate the data segment size. // Calculate the data segment size.
@ -358,10 +351,14 @@ fn map_segment_vmos(
/// this applies to the `.bss` segment. /// this applies to the `.bss` segment.
fn map_segment_vmo( fn map_segment_vmo(
loadable_phdr: &LoadablePhdr, loadable_phdr: &LoadablePhdr,
elf_vmo: &Arc<Vmo>, elf_file: &Path,
vmar: &Vmar, vmar: &Vmar,
map_at: Vaddr, map_at: Vaddr,
) -> Result<()> { ) -> Result<()> {
let Some(elf_vmo) = elf_file.inode().page_cache() else {
return_errno_with_message!(Errno::ENOEXEC, "the executable has no page cache");
};
let virt_range = loadable_phdr.virt_range(); let virt_range = loadable_phdr.virt_range();
let file_range = loadable_phdr.file_range(); let file_range = loadable_phdr.file_range();
trace!( trace!(

View File

@ -9,7 +9,7 @@ use self::{
}; };
use crate::{ use crate::{
fs::{ fs::{
path::{FsPath, PathResolver}, path::{FsPath, Path, PathResolver},
utils::{Inode, InodeType, Permission}, utils::{Inode, InodeType, Permission},
}, },
prelude::*, prelude::*,
@ -21,22 +21,22 @@ use crate::{
/// This struct encapsulates the ELF file to be executed along with its header data, /// This struct encapsulates the ELF file to be executed along with its header data,
/// the `argv` and the `envp` which is required for the program execution. /// the `argv` and the `envp` which is required for the program execution.
pub(super) struct ProgramToLoad { pub(super) struct ProgramToLoad {
elf_inode: Arc<dyn Inode>, elf_file: Path,
elf_headers: ElfHeaders, elf_headers: ElfHeaders,
argv: Vec<CString>, argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
} }
impl ProgramToLoad { impl ProgramToLoad {
/// Constructs a new `ProgramToLoad` from an inode and handles shebang interpretation if /// Constructs a new `ProgramToLoad` from a file and handles shebang interpretation if
/// necessary. /// necessary.
pub(super) fn build_from_inode( pub(super) fn build_from_file(
mut elf_inode: Arc<dyn Inode>, mut elf_file: Path,
path_resolver: &PathResolver, path_resolver: &PathResolver,
mut argv: Vec<CString>, mut argv: Vec<CString>,
envp: Vec<CString>, envp: Vec<CString>,
) -> Result<Self> { ) -> Result<Self> {
check_executable_inode(elf_inode.as_ref())?; check_executable_inode(elf_file.inode().as_ref())?;
// A limit to the recursion depth of shebang executables. // A limit to the recursion depth of shebang executables.
// //
@ -48,7 +48,7 @@ impl ProgramToLoad {
// Read the first page of the file, which should contain a shebang or an ELF header. // Read the first page of the file, which should contain a shebang or an ELF header.
let (file_first_page, len) = { let (file_first_page, len) = {
let mut buffer = Box::new([0u8; PAGE_SIZE]); let mut buffer = Box::new([0u8; PAGE_SIZE]);
let len = elf_inode.read_bytes_at(0, &mut *buffer)?; let len = elf_file.inode().read_bytes_at(0, &mut *buffer)?;
(buffer, len) (buffer, len)
}; };
@ -71,13 +71,13 @@ impl ProgramToLoad {
// Update the argument list and the executable inode. Then, try again. // Update the argument list and the executable inode. Then, try again.
new_argv.extend(argv); new_argv.extend(argv);
argv = new_argv; argv = new_argv;
elf_inode = interpreter.inode().clone(); elf_file = interpreter;
}; };
let elf_headers = ElfHeaders::parse(&file_first_page[..len])?; let elf_headers = ElfHeaders::parse(&file_first_page[..len])?;
Ok(Self { Ok(Self {
elf_inode, elf_file,
elf_headers, elf_headers,
argv, argv,
envp, envp,
@ -94,7 +94,7 @@ impl ProgramToLoad {
) -> Result<ElfLoadInfo> { ) -> Result<ElfLoadInfo> {
let elf_load_info = load_elf_to_vmar( let elf_load_info = load_elf_to_vmar(
vmar, vmar,
&self.elf_inode, self.elf_file,
path_resolver, path_resolver,
self.elf_headers, self.elf_headers,
self.argv, self.argv,