fix(dso): ensure all (r|run)paths are relative to sysroot

Also make sure we split them on colons.
This commit is contained in:
Kai Stuhlemmer 2025-06-02 17:44:10 +02:00 committed by Matteo Settenvini
parent f2fc705fa0
commit 6d06377154
Signed by: matteo
GPG key ID: 1C1B12600D81DE05
3 changed files with 54 additions and 38 deletions

View file

@ -3,7 +3,10 @@
use std::path::PathBuf;
use clap::{builder::{PathBufValueParser, TypedValueParser}, Parser};
use clap::{
Parser,
builder::{PathBufValueParser, TypedValueParser},
};
#[derive(Clone, Default)]
struct AbsolutePathBufValueParser;
@ -20,10 +23,8 @@ impl TypedValueParser for AbsolutePathBufValueParser {
let pathbuf_parser = PathBufValueParser::new();
let v = pathbuf_parser.parse_ref(cmd, arg, value)?;
v.canonicalize().map_err(|e| clap::Error::raw(
clap::error::ErrorKind::Io,
e,
))
v.canonicalize()
.map_err(|e| clap::Error::raw(clap::error::ErrorKind::Io, e))
}
}
@ -59,4 +60,3 @@ pub struct Args {
/// The location of the sysroot to clean up
pub sysroot_location: PathBuf,
}

View file

@ -206,7 +206,12 @@ impl Runner {
"regular file"
};
let size = Self::get_file_size(path)?;
log::info!("(dry-run) would remove {} {} ({})", ty, path.display(), size);
log::info!(
"(dry-run) would remove {} {} ({})",
ty,
path.display(),
size
);
Ok(size)
})
} else {
@ -225,8 +230,8 @@ impl Runner {
Err(err) => {
log::error!("failed to get metadata from: {}, {}", file.display(), err);
FileSize(0)
},
Ok(lstat) => FileSize(lstat.st_size as u64)
}
Ok(lstat) => FileSize(lstat.st_size as u64),
};
Ok(size)
}

View file

@ -159,7 +159,7 @@ impl State {
}
let current_dir = std::env::current_dir()?;
let mut dst_path = std::fs::read_link(path)?;
let mut dst_path = fs::read_link(path)?;
if dst_path.is_absolute() {
dst_path = dst_path.strip_prefix("/")?.into();
} else {
@ -197,10 +197,12 @@ impl State {
}
let search_paths = determine_lib_search_paths(path, elf)?;
log::trace!("determined search paths {:#?}", search_paths);
'next_lib: for &library in elf.libraries.iter() {
for lib_path in search_paths.iter() {
let tentative_path = PathBuf::from(lib_path).strip_prefix("/")?.join(library);
assert!(Path::new(&lib_path).is_relative());
let tentative_path = PathBuf::from(lib_path).join(library);
let dst = match nix::sys::stat::lstat(&tentative_path) {
Ok(dst) => dst,
Err(Errno::ENOENT) => continue,
@ -219,7 +221,11 @@ impl State {
continue 'next_lib;
}
log::warn!("{}: unable to find library {}, ignoring (this might produce wrong results)!", path.display(), library);
log::warn!(
"{}: unable to find library {}, ignoring (this might produce wrong results)!",
path.display(),
library
);
}
Ok(())
@ -257,7 +263,7 @@ impl State {
{:?}
}}"
},
petgraph::dot::Dot::with_attr_getters(
dot::Dot::with_attr_getters(
&self.graph,
&[
dot::Config::NodeNoLabel,
@ -267,8 +273,12 @@ impl State {
&|_, _| { String::new() },
&|_, n| {
let paths = self.paths_map.get(&n.id()).unwrap();
let first_path = paths.iter().next().unwrap_or_else(|| panic!("dso: you have a path map with an empty entry for inode {}",
n.id()));
let first_path = paths.iter().next().unwrap_or_else(|| {
panic!(
"dso: you have a path map with an empty entry for inode {}",
n.id()
)
});
format!(
"label = \"({}, {})\"",
n.weight(),
@ -285,10 +295,13 @@ impl State {
}
fn determine_lib_search_paths(path: &Path, elf: &Elf<'_>) -> Result<Vec<String>> {
log::trace!("elf.runpaths = {:#?}", elf.runpaths);
log::trace!("elf.rpaths = {:#?}", elf.rpaths);
let mut search_paths = vec![];
let current_dir = std::env::current_dir()?;
let origin = std::fs::canonicalize(path)?
let origin = fs::canonicalize(path)?
.parent()
.unwrap()
.strip_prefix(current_dir)?
@ -297,34 +310,32 @@ fn determine_lib_search_paths(path: &Path, elf: &Elf<'_>) -> Result<Vec<String>>
.into_string()
.map_err(|s| anyhow::anyhow!("cannot represent {:?} as a UTF-8 string", s))?;
if elf.rpaths != vec![""] {
if elf.runpaths != vec![""] {
let mut rpaths = elf
.rpaths
.iter()
.map(|p| p.replace("$ORIGIN", &origin))
.collect::<Vec<_>>();
search_paths.append(&mut rpaths);
}
search_paths.append(&mut get_env_library_paths());
if elf.runpaths.is_empty() {
collect_paths(&elf.rpaths, &mut search_paths, &origin);
}
if elf.runpaths != vec![""] {
let mut runpaths = elf
.runpaths
.iter()
.map(|p| p.replace("$ORIGIN", &origin))
.collect::<Vec<_>>();
search_paths.append(&mut runpaths);
}
search_paths.append(&mut get_env_library_paths());
search_paths.push("/usr/local/lib".into());
search_paths.push("/lib".into());
search_paths.push("/usr/lib".into());
collect_paths(&elf.runpaths, &mut search_paths, &origin);
search_paths.push("usr/local/lib".into());
search_paths.push("lib".into());
search_paths.push("usr/lib".into());
Ok(search_paths)
}
fn collect_paths(elf_paths: &Vec<&str>, search_paths: &mut Vec<String>, origin: &str) {
if elf_paths.iter().any(|p| !p.is_empty()) {
let mut paths = elf_paths
.iter()
.flat_map(|p| p.split(':'))
.map(|p| p.replace("$ORIGIN", origin))
.map(|p| p.trim_start_matches('/').to_string())
.collect::<Vec<_>>();
search_paths.append(&mut paths);
}
}
fn get_env_library_paths() -> Vec<String> {
let ld_config_path = std::env::var("LD_LIBRARY_PATH");
ld_config_path