composd: prepare staging directory w/ libartpalette-system

Output files are staged until they are fully generated, then move to the
final location. The staging directory has a different SELinux context to
prevent misuse, and should change when it's moved to the final
directory.

This change makes composd to follow the same setup, using libartpalette.
As a result, the output are no longer stored in CompOS's own apexdata
(which was not intentional).

This change does not use bindgen, which seems have some difficulty to
bridge `const char**` correctly. Neither cxx, since it doesn't seem to
simplify the (already simple) call.

Bug: 205750213
Test: See odrefresh produces output in the staging directory

Change-Id: Ifc97b31a98052a31209556449d1642089a8c0e2e
This commit is contained in:
Victor Hsieh 2021-12-03 16:30:04 -08:00
parent 5f34abe565
commit 6fb8b256c1
3 changed files with 48 additions and 16 deletions

View File

@ -7,12 +7,17 @@ rust_library {
crate_name: "composd_native",
srcs: ["lib.rs"],
rustlibs: [
"libanyhow",
"libcxx",
"liblibc",
],
static_libs: [
"libcomposd_native_cpp",
],
shared_libs: ["libcrypto"],
shared_libs: [
"libartpalette-system",
"libcrypto",
],
apex_available: ["com.android.compos"],
}

View File

@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! Bindings native helpers for composd.
//! Native helpers for composd.
pub use ffi::*;
pub use art::*;
pub use crypto::*;
#[cxx::bridge]
mod ffi {
mod crypto {
/// Contains either a key or a reason why the key could not be extracted.
struct KeyResult {
/// The extracted key. If empty, the attempt to extract the key failed.
@ -36,3 +37,38 @@ mod ffi {
fn extract_rsa_public_key(der_certificate: &[u8]) -> KeyResult;
}
}
mod art {
use anyhow::{anyhow, Result};
use libc::c_char;
use std::ffi::{CStr, OsStr};
use std::io::Error;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr::null;
// From libartpalette(-system)
extern "C" {
fn PaletteCreateOdrefreshStagingDirectory(out_staging_dir: *mut *const c_char) -> i32;
}
const PALETTE_STATUS_OK: i32 = 0;
const PALETTE_STATUS_CHECK_ERRNO: i32 = 1;
/// Creates and returns the staging directory for odrefresh.
pub fn palette_create_odrefresh_staging_directory() -> Result<&'static Path> {
let mut staging_dir: *const c_char = null();
// SAFETY: The C function always returns a non-null C string (after created the directory).
let status = unsafe { PaletteCreateOdrefreshStagingDirectory(&mut staging_dir) };
match status {
PALETTE_STATUS_OK => {
// SAFETY: The previously returned `*const c_char` should point to a legitimate C
// string.
let cstr = unsafe { CStr::from_ptr(staging_dir) };
let path = OsStr::from_bytes(cstr.to_bytes()).as_ref();
Ok(path)
}
PALETTE_STATUS_CHECK_ERRNO => Err(anyhow!(Error::last_os_error().to_string())),
_ => Err(anyhow!("Failed with palette status {}", status)),
}
}
}

View File

@ -20,7 +20,6 @@
use crate::compilation_task::CompilationTask;
use crate::fd_server_helper::FdServerConfig;
use crate::instance_manager::InstanceManager;
use crate::instance_starter::CompOsInstance;
use crate::util::to_binder_result;
use android_system_composd::aidl::android::system::composd::{
ICompilationTask::{BnCompilationTask, ICompilationTask},
@ -31,12 +30,11 @@ use android_system_composd::binder::{
self, BinderFeatures, ExceptionCode, Interface, Status, Strong, ThreadState,
};
use anyhow::{Context, Result};
use compos_common::COMPOS_DATA_ROOT;
use rustutils::{system_properties, users::AID_ROOT, users::AID_SYSTEM};
use std::fs::{create_dir, File, OpenOptions};
use std::fs::{File, OpenOptions};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::sync::Arc;
pub struct IsolatedCompilationService {
@ -100,19 +98,12 @@ impl IsolatedCompilationService {
}
fn do_odrefresh_for_test(&self) -> Result<i8> {
let mut staging_dir_path = PathBuf::from(COMPOS_DATA_ROOT);
staging_dir_path.push("test-artifacts");
to_binder_result(create_dir(&staging_dir_path))?;
let compos = self
.instance_manager
.start_test_instance()
.context("Starting CompOS for odrefresh test")?;
self.do_odrefresh(compos, &staging_dir_path)
}
fn do_odrefresh(&self, compos: Arc<CompOsInstance>, staging_dir_path: &Path) -> Result<i8> {
let output_dir = open_dir(staging_dir_path)?;
let output_dir = open_dir(composd_native::palette_create_odrefresh_staging_directory()?)?;
let system_dir = open_dir(Path::new("/system"))?;
// Spawn a fd_server to serve the FDs.