diff --git a/src/libos/src/process/do_spawn/mod.rs b/src/libos/src/process/do_spawn/mod.rs index 8f5744ba..dd1ed213 100644 --- a/src/libos/src/process/do_spawn/mod.rs +++ b/src/libos/src/process/do_spawn/mod.rs @@ -3,7 +3,7 @@ use std::path::Path; use self::aux_vec::{AuxKey, AuxVec}; use self::exec_loader::{load_exec_file_to_vec, load_file_to_vec}; -use super::elf_file::{ElfFile, ElfHeader, ProgramHeader, ProgramHeaderExt}; +use super::elf_file::{ElfFile, ElfHeader, ProgramHeader, ProgramHeaderExt, SegmentData}; use super::process::ProcessBuilder; use super::task::Task; use super::thread::ThreadName; @@ -117,12 +117,22 @@ fn new_process( file_path.to_string() }; - let ldso_path = "/lib/ld-musl-x86_64.so.1"; - let ldso_elf_buf = load_file_to_vec(ldso_path, current_ref) - .cause_err(|e| errno!(e.errno(), "cannot load ld.so"))?; - let exec_elf_file = ElfFile::new(&elf_buf).cause_err(|e| errno!(e.errno(), "invalid executable"))?; + // Get the ldso_path of the executable + let exec_interp_segment = exec_elf_file + .program_headers() + .find(|segment| segment.is_interpreter()) + .ok_or_else(|| errno!(EINVAL, "cannot find the interpreter segment"))?; + let ldso_path = match exec_interp_segment.get_content(&exec_elf_file) { + SegmentData::Undefined(bytes) => std::ffi::CStr::from_bytes_with_nul(bytes) + .unwrap() + .to_str() + .unwrap(), + _ => return_errno!(EINVAL, "cannot get ldso_path from executable"), + }; + let ldso_elf_buf = load_file_to_vec(ldso_path, current_ref) + .cause_err(|e| errno!(e.errno(), "cannot load ld.so"))?; let ldso_elf_file = ElfFile::new(&ldso_elf_buf).cause_err(|e| errno!(e.errno(), "invalid ld.so"))?; diff --git a/src/libos/src/process/elf_file.rs b/src/libos/src/process/elf_file.rs index 0ed490a0..3ed0bcfe 100644 --- a/src/libos/src/process/elf_file.rs +++ b/src/libos/src/process/elf_file.rs @@ -4,7 +4,7 @@ use xmas_elf::{header, program, sections}; use crate::prelude::*; pub use xmas_elf::header::HeaderPt2 as ElfHeader; -pub use xmas_elf::program::{ProgramHeader, ProgramIter}; +pub use xmas_elf::program::{ProgramHeader, ProgramIter, SegmentData}; #[derive(Debug)] pub struct ElfFile<'a> { @@ -37,6 +37,10 @@ impl<'a> ElfFile<'a> { // Validate the ELF header xmas_elf::header::sanity_check(elf_inner) .map_err(|e| errno!(ENOEXEC, "invalid ELF header"))?; + // Validate ELF type + if elf_inner.header.pt2.type_().as_type() != xmas_elf::header::Type::SharedObject { + return_errno!(ENOEXEC, "ELF is not position-independent"); + } // Validate the segments for segment in elf_inner.program_iter() { segment.validate()?; @@ -45,18 +49,29 @@ impl<'a> ElfFile<'a> { } } -pub trait ProgramHeaderExt { +pub trait ProgramHeaderExt<'a> { fn loadable(&self) -> bool; + fn is_interpreter(&self) -> bool; fn validate(&self) -> Result<()>; + fn get_content(&self, elf_file: &ElfFile<'a>) -> SegmentData<'a>; } -impl<'a> ProgramHeaderExt for ProgramHeader<'a> { +impl<'a> ProgramHeaderExt<'a> for ProgramHeader<'a> { /// Is the segment loadable? fn loadable(&self) -> bool { let type_ = self.get_type().unwrap(); type_ == xmas_elf::program::Type::Load } + fn is_interpreter(&self) -> bool { + let type_ = self.get_type().unwrap(); + type_ == xmas_elf::program::Type::Interp + } + + fn get_content(&self, elf_file: &ElfFile<'a>) -> SegmentData<'a> { + self.get_data(&elf_file.elf_inner).unwrap() + } + /// Do some basic sanity checks in case the ELF is corrupted somehow fn validate(&self) -> Result<()> { let ph64 = match self {