diff options
-rw-r--r-- | profcollectd/binder/com/android/server/profcollect/IProfCollectd.aidl | 1 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/config.rs | 3 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/report.rs | 18 | ||||
-rw-r--r-- | profcollectd/libprofcollectd/service.rs | 37 |
4 files changed, 45 insertions, 14 deletions
diff --git a/profcollectd/binder/com/android/server/profcollect/IProfCollectd.aidl b/profcollectd/binder/com/android/server/profcollect/IProfCollectd.aidl index 9d4985b4..58503abc 100644 --- a/profcollectd/binder/com/android/server/profcollect/IProfCollectd.aidl +++ b/profcollectd/binder/com/android/server/profcollect/IProfCollectd.aidl @@ -23,6 +23,7 @@ interface IProfCollectd { void trace_once(@utf8InCpp String tag); void process(boolean blocking); @utf8InCpp String report(); + void copy_report_to_bb(int bb_profile_id, @utf8InCpp String report); void delete_report(@utf8InCpp String report); @utf8InCpp String get_supported_provider(); } diff --git a/profcollectd/libprofcollectd/config.rs b/profcollectd/libprofcollectd/config.rs index c0f91d53..112f9efc 100644 --- a/profcollectd/libprofcollectd/config.rs +++ b/profcollectd/libprofcollectd/config.rs @@ -33,6 +33,9 @@ lazy_static! { pub static ref TRACE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/trace/"); pub static ref PROFILE_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/output/"); pub static ref REPORT_OUTPUT_DIR: &'static Path = Path::new("/data/misc/profcollectd/report/"); + pub static ref BETTERBUG_CACHE_DIR_PREFIX: &'static Path = Path::new("/data/user/"); + pub static ref BETTERBUG_CACHE_DIR_SUFFIX: &'static Path = + Path::new("com.google.android.apps.internal.betterbug/cache/"); pub static ref OLD_REPORT_OUTPUT_FILE: &'static Path = Path::new("/data/misc/profcollectd/report.zip"); pub static ref CONFIG_FILE: &'static Path = diff --git a/profcollectd/libprofcollectd/report.rs b/profcollectd/libprofcollectd/report.rs index 218ec875..2c524729 100644 --- a/profcollectd/libprofcollectd/report.rs +++ b/profcollectd/libprofcollectd/report.rs @@ -19,8 +19,9 @@ use anyhow::{anyhow, Result}; use lazy_static::lazy_static; use macaddr::MacAddr6; -use std::fs::{read_dir, remove_file, File}; +use std::fs::{self, File}; use std::io::{Read, Write}; +use std::os::unix::fs::OpenOptionsExt; use std::path::{Path, PathBuf}; use std::time::SystemTime; use uuid::v1::{Context, Timestamp}; @@ -36,19 +37,20 @@ lazy_static! { pub fn pack_report(profile: &Path, report: &Path, config: &Config) -> Result<String> { let mut report = PathBuf::from(report); - report.push(get_report_filename(&config.node_id)?); + let report_filename = get_report_filename(&config.node_id)?; + report.push(&report_filename); report.set_extension("zip"); - let report_path = - report.to_str().ok_or_else(|| anyhow!("Malformed report path: {}", report.display()))?; // Remove the current report file if exists. - remove_file(&report).ok(); + fs::remove_file(&report).ok(); - let report = File::create(&report)?; + // Set report file ACL bits to 644, so that this can be shared to uploaders. + // Who has permission to actually read the file is protected by SELinux policy. + let report = fs::OpenOptions::new().create_new(true).write(true).mode(0o644).open(&report)?; let options = FileOptions::default(); let mut zip = ZipWriter::new(report); - read_dir(profile)? + fs::read_dir(profile)? .filter_map(|e| e.ok()) .map(|e| e.path()) .filter(|e| e.is_file()) @@ -66,7 +68,7 @@ pub fn pack_report(profile: &Path, report: &Path, config: &Config) -> Result<Str })?; zip.finish()?; - Ok(report_path.to_string()) + Ok(report_filename) } fn get_report_filename(node_id: &MacAddr6) -> Result<String> { diff --git a/profcollectd/libprofcollectd/service.rs b/profcollectd/libprofcollectd/service.rs index 4bc08970..dc622ff3 100644 --- a/profcollectd/libprofcollectd/service.rs +++ b/profcollectd/libprofcollectd/service.rs @@ -16,25 +16,26 @@ //! ProfCollect Binder service implementation. -use anyhow::{bail, Context, Error, Result}; +use anyhow::{anyhow, bail, Context, Error, Result}; use binder::public_api::Result as BinderResult; use binder::Status; use profcollectd_aidl_interface::aidl::com::android::server::profcollect::IProfCollectd::IProfCollectd; use std::ffi::CString; -use std::fs::{create_dir, read_to_string, remove_dir_all, remove_file, write}; +use std::fs::{copy, create_dir, read_to_string, remove_dir_all, remove_file, write}; use std::path::PathBuf; use std::str::FromStr; use std::sync::{Mutex, MutexGuard}; use crate::config::{ - Config, CONFIG_FILE, OLD_REPORT_OUTPUT_FILE, PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, - TRACE_OUTPUT_DIR, + Config, BETTERBUG_CACHE_DIR_PREFIX, BETTERBUG_CACHE_DIR_SUFFIX, CONFIG_FILE, + OLD_REPORT_OUTPUT_FILE, PROFILE_OUTPUT_DIR, REPORT_OUTPUT_DIR, TRACE_OUTPUT_DIR, }; use crate::report::pack_report; use crate::scheduler::Scheduler; fn err_to_binder_status(msg: Error) -> Status { - let msg = CString::new(msg.to_string()).expect("Failed to convert to CString"); + let msg = format!("{:#?}", msg); + let msg = CString::new(msg).expect("Failed to convert to CString"); Status::new_service_specific_error(1, Some(&msg)) } @@ -95,6 +96,30 @@ impl IProfCollectd for ProfcollectdBinderService { remove_file(&report).ok(); Ok(()) } + fn copy_report_to_bb(&self, bb_profile_id: i32, report_name: &str) -> BinderResult<()> { + if bb_profile_id < 0 { + return Err(err_to_binder_status(anyhow!("Invalid profile ID"))); + } + verify_report_name(&report_name).map_err(err_to_binder_status)?; + + let mut report = PathBuf::from(&*REPORT_OUTPUT_DIR); + report.push(report_name); + report.set_extension("zip"); + + let mut dest = PathBuf::from(&*BETTERBUG_CACHE_DIR_PREFIX); + dest.push(bb_profile_id.to_string()); + dest.push(&*BETTERBUG_CACHE_DIR_SUFFIX); + if !dest.is_dir() { + return Err(err_to_binder_status(anyhow!("Cannot open BetterBug cache dir"))); + } + dest.push(report_name); + dest.set_extension("zip"); + + copy(report, dest) + .map(|_| ()) + .context("Failed to copy report to bb storage.") + .map_err(err_to_binder_status) + } fn get_supported_provider(&self) -> BinderResult<String> { Ok(self.lock().scheduler.get_trace_provider_name().to_string()) } @@ -105,7 +130,7 @@ impl IProfCollectd for ProfcollectdBinderService { fn verify_report_name(report_name: &str) -> Result<()> { match report_name.chars().all(|c| c.is_ascii_hexdigit() || c == '-') { true => Ok(()), - false => bail!("Not a report name: {}", report_name), + false => bail!("Invalid report name: {}", report_name), } } |