| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use { |
| anyhow::{anyhow, Error}, |
| fuchsia_inspect as finspect, |
| fuchsia_syslog::fx_log_err, |
| pkgfs::system::Client as SystemImage, |
| }; |
| |
| pub(crate) struct PkgfsInspectState { |
| _exec_restrictions_enabled: finspect::StringProperty, |
| _node: finspect::Node, |
| } |
| |
| const INSPECT_EXEC_PROP_NAME: &str = "pkgfs-executability-restrictions-enabled"; |
| const DISABLE_RESTRICTIONS_FILE_PATH: &str = "data/pkgfs_disable_executability_restrictions"; |
| |
| impl PkgfsInspectState { |
| pub async fn new( |
| system_image: impl FnOnce() -> Result<SystemImage, Error>, |
| node: finspect::Node, |
| ) -> Self { |
| match Self::load_pkgfs_exec_restrictions_enabled(system_image).await { |
| Ok(enabled) => Self { |
| _exec_restrictions_enabled: node |
| .create_string(INSPECT_EXEC_PROP_NAME, format!("{}", enabled)), |
| _node: node, |
| }, |
| Err(e) => { |
| fx_log_err!( |
| "Unexpected error trying to open file from system image: {:#}", |
| anyhow!(e) |
| ); |
| Self { |
| _exec_restrictions_enabled: node.create_string(INSPECT_EXEC_PROP_NAME, "error"), |
| _node: node, |
| } |
| } |
| } |
| } |
| |
| async fn load_pkgfs_exec_restrictions_enabled( |
| system_image: impl FnOnce() -> Result<SystemImage, Error>, |
| ) -> Result<bool, Error> { |
| let pkgfs_system = system_image()?; |
| |
| match pkgfs_system.open_file(DISABLE_RESTRICTIONS_FILE_PATH).await { |
| Ok(_) => Ok(false), |
| Err(pkgfs::system::SystemImageFileOpenError::NotFound) => Ok(true), |
| // We expect this to get zx::Status::NOT_SUPPORTED in tests that |
| // haven't actually addded system image package to pkgfs. |
| Err(other) => Err(other.into()), |
| } |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use { |
| super::*, |
| anyhow::anyhow, |
| fuchsia_async as fasync, |
| fuchsia_inspect::assert_inspect_tree, |
| std::fs::{create_dir_all, File}, |
| tempfile::TempDir, |
| }; |
| |
| struct TestPkgfs { |
| pkgfs_root: TempDir, |
| } |
| |
| impl TestPkgfs { |
| fn new_with_restrictions_enabled(restrictions_enabled: bool) -> Self { |
| let pkgfs_root = TempDir::new().unwrap(); |
| create_dir_all(pkgfs_root.path().join("system/data")).unwrap(); |
| if !restrictions_enabled { |
| File::create( |
| pkgfs_root.path().join(format!("system/{}", DISABLE_RESTRICTIONS_FILE_PATH)), |
| ) |
| .unwrap(); |
| } |
| Self { pkgfs_root } |
| } |
| |
| fn system_image(&self) -> SystemImage { |
| SystemImage::open_from_pkgfs_root(&fidl_fuchsia_io::DirectoryProxy::new( |
| fasync::Channel::from_channel( |
| fdio::transfer_fd(File::open(self.pkgfs_root.path()).unwrap()).unwrap().into(), |
| ) |
| .unwrap(), |
| )) |
| .unwrap() |
| } |
| } |
| |
| async fn assert_pkgfs_executability_restrictions_enabled( |
| system_image: impl FnOnce() -> Result<SystemImage, Error>, |
| expected_state: String, |
| ) { |
| let inspector = finspect::Inspector::new(); |
| |
| let _pkgfs_inspect = |
| PkgfsInspectState::new(system_image, inspector.root().create_child("pkgfs")).await; |
| |
| assert_inspect_tree!(inspector, root: { |
| "pkgfs": { |
| INSPECT_EXEC_PROP_NAME.to_string() => expected_state, |
| } |
| }); |
| } |
| |
| #[fasync::run_singlethreaded(test)] |
| async fn inspect_pkgfs_versions_restrictions_enabled() { |
| let env = TestPkgfs::new_with_restrictions_enabled(true); |
| |
| assert_pkgfs_executability_restrictions_enabled( |
| || Ok(env.system_image()), |
| "true".to_string(), |
| ) |
| .await; |
| } |
| |
| #[fasync::run_singlethreaded(test)] |
| async fn inspect_pkgfs_versions_restrictions_disabled() { |
| let env = TestPkgfs::new_with_restrictions_enabled(false); |
| |
| assert_pkgfs_executability_restrictions_enabled( |
| || Ok(env.system_image()), |
| "false".to_string(), |
| ) |
| .await; |
| } |
| |
| #[fasync::run_singlethreaded(test)] |
| async fn inspect_pkgfs_versions_restrictions_error() { |
| assert_pkgfs_executability_restrictions_enabled( |
| || Err(anyhow!("failed to get system image")), |
| "error".to_string(), |
| ) |
| .await; |
| } |
| } |