blob: a90a2d13aa3d73f6346aa19cdc0130b0d992e1bf [file] [log] [blame]
// 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::{Context, Error},
fidl::endpoints::Proxy,
fidl_test_policy as ftest, fuchsia_async as fasync,
fuchsia_component::client,
fuchsia_zircon::{self as zx, AsHandleRef},
matches::assert_matches,
security_policy_test_util::{bind_child, start_policy_test},
};
const CM_URL: &str =
"fuchsia-pkg://fuchsia.com/security-policy-vmex-integration-test#meta/cm_for_test.cmx";
const ROOT_URL: &str =
"fuchsia-pkg://fuchsia.com/security-policy-vmex-integration-test#meta/test_root.cm";
const TEST_CONFIG_PATH: &str = "/pkg/data/cm_config";
#[fasync::run_singlethreaded(test)]
async fn verify_ambient_vmex_default_denied() -> Result<(), Error> {
let (_test, realm) = start_policy_test(CM_URL, ROOT_URL, TEST_CONFIG_PATH).await?;
let child_name = "policy_not_requested";
let exposed_dir = bind_child(&realm, child_name).await.expect("bind should succeed");
let ops =
client::connect_to_protocol_at_dir_root::<ftest::ProtectedOperationsMarker>(&exposed_dir)
.context("failed to connect to test service after bind")?;
let vmo = zx::Vmo::create(1).unwrap();
let result = ops.ambient_replace_as_executable(vmo).await.context("fidl call failed")?;
assert_matches!(result.map_err(zx::Status::from_raw), Err(zx::Status::ACCESS_DENIED));
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn verify_ambient_vmex_allowed() -> Result<(), Error> {
let (_test, realm) = start_policy_test(CM_URL, ROOT_URL, TEST_CONFIG_PATH).await?;
let child_name = "policy_allowed";
let exposed_dir = bind_child(&realm, child_name).await.expect("bind should succeed");
let ops =
client::connect_to_protocol_at_dir_root::<ftest::ProtectedOperationsMarker>(&exposed_dir)
.context("failed to connect to test service after bind")?;
let vmo = zx::Vmo::create(1).unwrap();
let result = ops.ambient_replace_as_executable(vmo).await.context("fidl call failed")?;
match result.map_err(zx::Status::from_raw) {
Ok(exec_vmo) => {
assert!(exec_vmo.basic_info().unwrap().rights.contains(zx::Rights::EXECUTE));
}
Err(zx::Status::ACCESS_DENIED) => {
panic!("Unexpected ACCESS_DENIED when policy should be allowed")
}
Err(err) => panic!("Unexpected error {}", err),
}
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn verify_ambient_vmex_denied() -> Result<(), Error> {
let (_test, realm) = start_policy_test(CM_URL, ROOT_URL, TEST_CONFIG_PATH).await?;
// This security policy is enforced inside the ELF runner. The component will fail to launch
// because of the denial, but BindChild will return success because the runtime successfully
// asks the runner to start the component. We watch for the exposed_dir to get dropped to detect
// the launch failure.
// N.B. We could alternatively look for a Started and then a Stopped event to verify that the
// component failed to launch, but fxbug.dev/53414 prevented that at the time this was written.
let child_name = "policy_denied";
let exposed_dir = bind_child(&realm, child_name).await.expect("bind should succeed");
exposed_dir.on_closed().await.expect("failed to wait for exposed_dir PEER_CLOSED");
Ok(())
}