Merge branch 'exec-cache' into 'master'

Implement exec cache from ld_so cache

See merge request redox-os/relibc!1140
This commit is contained in:
Jeremy Soller
2026-03-29 15:31:56 -06:00
2 changed files with 48 additions and 8 deletions
+8
View File
@@ -3,9 +3,11 @@ use crate::{
error::{Errno, ResultExt},
header::{
fcntl::O_CREAT,
sys_stat::stat,
unistd::{SEEK_CUR, SEEK_END, SEEK_SET},
},
io,
out::Out,
platform::{Pal, Sys, types::*},
};
use core::ops::Deref;
@@ -57,6 +59,12 @@ impl File {
Sys::ftruncate(self.fd, size as off_t).map_err(Errno::sync)
}
pub fn fstat(&self) -> Result<stat, Errno> {
let mut file_st = stat::default();
Sys::fstat(self.fd, Out::from_mut(&mut file_st)).map_err(Errno::sync)?;
Ok(file_st)
}
pub fn try_clone(&self) -> io::Result<Self> {
Ok(Self::new(Sys::dup(self.fd)?))
}
+40 -8
View File
@@ -74,12 +74,46 @@ 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 mut src_stat = Stat::default();
redox_rt::sys::fstat(*src_fd as usize, &mut src_stat)?;
#[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 +127,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 {