Revert "`ProgramToLoad` only needs a `elf_inode: Arc<dyn Inode>` instead of a `Path`"
This reverts commit 71632a51b5.
This commit is contained in:
parent
66ac28c4c2
commit
fb8c9e0c27
|
|
@ -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)?;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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!(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue