From c769e42886a960b41620690cd50e8b5987cfa8b4 Mon Sep 17 00:00:00 2001 From: Javier Honduvilla Coto Date: Mon, 23 Sep 2024 15:17:16 +0100 Subject: [PATCH] Fix object path absolute paths (#75) To support processes running in mount namespaces that aren't the root one we can access the files in their mount via procfs's root directory. Not only this was broken in terms of the paths being joined, but also the way `Path::join` works is that the joined path starts with a slash (so it's recognised as absolute) it will replace the whole path (!). This was reported upstream in https://github.com/rust-lang/rust/issues/16507. Test Plan ========= Ran lightswitch for a little bit, and containerised workloads worked fine. --- src/profiler.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/profiler.rs b/src/profiler.rs index ef90608..138e1d8 100644 --- a/src/profiler.rs +++ b/src/profiler.rs @@ -1267,13 +1267,11 @@ impl Profiler<'_> { } match &map.pathname { procfs::process::MMapPath::Path(path) => { - let mut abs_path = proc.exe()?; - abs_path.push("/root"); - abs_path.push(path); + let abs_path = format!("/proc/{}/root/{}", pid, path.to_string_lossy()); // We've seen debug info executables that get deleted in Rust applications. // There are probably other cases, but we'll handle them as we bump into them. - if abs_path.to_str().unwrap().contains("(deleted)") { + if abs_path.contains("(deleted)") { continue; } @@ -1282,17 +1280,17 @@ impl Profiler<'_> { let file = match fs::File::open(&abs_path) { Ok(f) => f, Err(e) => { - warn!("failed to open file {} due to {:?}", abs_path.display(), e); + warn!("failed to open file {} due to {:?}", abs_path, e); // Rather than returning here, we prefer to be able to profile some // parts of the binary continue; } }; - let object_file = match ObjectFile::new(&abs_path) { + let object_file = match ObjectFile::new(&PathBuf::from(abs_path.clone())) { Ok(f) => f, Err(e) => { - warn!("object_file {} failed with {:?}", abs_path.display(), e); + warn!("object_file {} failed with {:?}", abs_path, e); // Rather than returning here, we prefer to be able to profile some // parts of the binary continue; @@ -1311,7 +1309,7 @@ impl Profiler<'_> { }; let Ok(executable_id) = object_file.id() else { - debug!("could not get id for object file: {:?}", abs_path); + debug!("could not get id for object file: {}", abs_path); continue; }; @@ -1343,7 +1341,7 @@ impl Profiler<'_> { Entry::Vacant(entry) => match object_file.elf_load() { Ok(elf_load) => { entry.insert(ObjectFileInfo { - path: abs_path, + path: PathBuf::from(abs_path), file, load_offset: elf_load.offset, load_vaddr: elf_load.vaddr,