Implement exec cache from ld_so cache

This commit is contained in:
Wildan M
2026-03-29 13:11:36 +07:00
parent a78c1f5cfd
commit b2de3d6e2e
2 changed files with 48 additions and 8 deletions
+7
View File
@@ -9,6 +9,7 @@ use crate::{
platform::{Pal, Sys, types::*},
};
use core::ops::Deref;
use syscall::Stat;
pub struct File {
pub fd: c_int,
@@ -57,6 +58,12 @@ impl File {
Sys::ftruncate(self.fd, size as off_t).map_err(Errno::sync)
}
pub fn fstat(&self) -> Result<Stat, syscall::Error> {
let mut stat = Stat::default();
redox_rt::sys::fstat(self.fd as usize, &mut stat)?;
Ok(stat)
}
pub fn try_clone(&self) -> io::Result<Self> {
Ok(Self::new(Sys::dup(self.fd)?))
}
+41 -8
View File
@@ -74,12 +74,47 @@ pub fn execve(
) -> Result<Infallible> {
// NOTE: We must omit O_CLOEXEC and close manually, otherwise it will be closed before we
// have even read it!
let (mut image_file, arg0) = match exec {
Executable::AtPath(path) => (
File::open(path, O_RDONLY as c_int).map_err(|_| Error::new(ENOENT))?,
path.to_bytes(),
),
Executable::InFd { file, arg0 } => (file, arg0),
let (mut image_file, stat, arg0) = match exec {
Executable::AtPath(path) => {
let Ok(src_fd) = File::open(path, O_RDONLY as c_int) else {
return Err(Error::new(ENOENT));
};
let Ok(src_stat) = src_fd.fstat() else {
return Err(Error::new(ENOENT));
};
#[cfg(feature = "ld_so_cache")]
let src_fd = {
let mtime_sec = src_stat.st_mtime;
let mtime_nsec = src_stat.st_mtime_nsec;
let safe_path = path.to_str().unwrap_or("").replace('/', "_");
let shm_path_owned = format!(
"/scheme/shm/ld.so.cache.{}.{}.{}\0",
safe_path, mtime_sec, mtime_nsec
);
let shm_path =
unsafe { CStr::from_bytes_with_nul_unchecked(shm_path_owned.as_bytes()) };
let mut file_opt = None;
if let Ok(shm_fd) = File::open(shm_path, O_RDONLY as c_int) {
if let Ok(shm_stat) = shm_fd.fstat()
&& shm_stat.st_size > 0
{
file_opt = Some(shm_fd);
}
}
file_opt.unwrap_or(src_fd)
};
(src_fd, src_stat, path.to_bytes())
}
Executable::InFd { file, arg0 } => {
let mut stat = Stat::default();
redox_rt::sys::fstat(*file as usize, &mut stat)?;
(file, stat, arg0)
}
};
// With execve now being implemented in userspace, we need to check ourselves that this
@@ -93,8 +128,6 @@ pub fn execve(
// TODO: At some point we might have capabilities limiting the ability to allocate
// executable memory.
let mut stat = Stat::default();
redox_rt::sys::fstat(*image_file as usize, &mut stat)?;
let Resugid { ruid, rgid, .. } = redox_rt::sys::posix_getresugid();
let mode = if ruid == stat.st_uid {