Remove libcompos_client
CompOS APEX no longer needs to provide libcompos_client API (added
recently during T development).
Some of the code is still reusable, so the remaining code is moved to
composd/src/fd_server_helper.rs.
Bug: 205750213
Test: m
Test: atest ComposHostTestCases
Change-Id: I584b700c41ffc0e08c6ac6c171cb17ab21c7d8ff
diff --git a/compos/apex/Android.bp b/compos/apex/Android.bp
index 36e3c3e..c68899a 100644
--- a/compos/apex/Android.bp
+++ b/compos/apex/Android.bp
@@ -45,16 +45,12 @@
"compos_verify_key",
"composd",
"composd_cmd",
- "pvm_exec", // to be superseded by libcompos_client
+ "pvm_exec", // deprecated
// Used in VM
"compsvc",
],
- native_shared_libs: [
- "libcompos_client",
- ],
-
apps: [
"CompOSPayloadApp",
],
diff --git a/compos/composd/Android.bp b/compos/composd/Android.bp
index a76d96c..2ab12e3 100644
--- a/compos/composd/Android.bp
+++ b/compos/composd/Android.bp
@@ -18,6 +18,8 @@
"libbinder_rs",
"libcompos_common",
"libcomposd_native_rust",
+ "libminijail_rust",
+ "libnix",
"libnum_traits",
"liblog_rust",
"librustutils",
diff --git a/compos/composd/src/composd_main.rs b/compos/composd/src/composd_main.rs
index f9751c3..57f64a5 100644
--- a/compos/composd/src/composd_main.rs
+++ b/compos/composd/src/composd_main.rs
@@ -19,6 +19,7 @@
//! them, and orchestrating trusted compilation.
mod compilation_task;
+mod fd_server_helper;
mod instance_manager;
mod instance_starter;
mod internal_service;
diff --git a/compos/composd/src/fd_server_helper.rs b/compos/composd/src/fd_server_helper.rs
new file mode 100644
index 0000000..2dab9a3
--- /dev/null
+++ b/compos/composd/src/fd_server_helper.rs
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! A helper library to start a fd_server.
+//!
+//! TODO(205750213): Make it easy to spawn a fd_server.
+
+use anyhow::{Context, Result};
+use log::debug;
+use minijail::Minijail;
+use nix::fcntl::OFlag;
+use nix::unistd::pipe2;
+use std::fs::File;
+use std::io::Read;
+use std::os::unix::io::{AsRawFd, FromRawFd};
+use std::path::Path;
+
+const FD_SERVER_BIN: &str = "/apex/com.android.virt/bin/fd_server";
+
+#[allow(dead_code)]
+fn spawn_fd_server(input_fds: &[i32], output_fds: &[i32], ready_file: File) -> Result<Minijail> {
+ let mut inheritable_fds = Vec::new();
+ let mut args = vec![FD_SERVER_BIN.to_string()];
+ for fd in input_fds {
+ args.push("--ro-fds".to_string());
+ args.push(fd.to_string());
+ inheritable_fds.push(*fd);
+ }
+ for fd in output_fds {
+ args.push("--rw-fds".to_string());
+ args.push(fd.to_string());
+ inheritable_fds.push(*fd);
+ }
+ let ready_fd = ready_file.as_raw_fd();
+ args.push("--ready-fd".to_string());
+ args.push(ready_fd.to_string());
+ inheritable_fds.push(ready_fd);
+
+ let jail = Minijail::new()?;
+ let _pid = jail.run(Path::new(FD_SERVER_BIN), &inheritable_fds, &args)?;
+ Ok(jail)
+}
+
+#[allow(dead_code)]
+fn create_pipe() -> Result<(File, File)> {
+ let (raw_read, raw_write) = pipe2(OFlag::O_CLOEXEC)?;
+ // SAFETY: We are the sole owners of these fds as they were just created.
+ let read_fd = unsafe { File::from_raw_fd(raw_read) };
+ let write_fd = unsafe { File::from_raw_fd(raw_write) };
+ Ok((read_fd, write_fd))
+}
+
+#[allow(dead_code)]
+fn wait_for_fd_server_ready(mut ready_fd: File) -> Result<()> {
+ let mut buffer = [0];
+ // When fd_server is ready it closes its end of the pipe. And if it exits, the pipe is also
+ // closed. Either way this read will return 0 bytes at that point, and there's no point waiting
+ // any longer.
+ let _ = ready_fd.read(&mut buffer).context("Waiting for fd_server to be ready")?;
+ debug!("fd_server is ready");
+ Ok(())
+}
diff --git a/compos/libcompos_client/Android.bp b/compos/libcompos_client/Android.bp
deleted file mode 100644
index db6294e..0000000
--- a/compos/libcompos_client/Android.bp
+++ /dev/null
@@ -1,58 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library {
- name: "libcompos_client",
- whole_static_libs: ["libcompos_client_ffi"],
- min_sdk_version: "apex_inherit",
- shared_libs: [
- "libbinder_ndk",
- "libbinder_rpc_unstable",
- "libminijail",
- ],
- export_include_dirs: ["include"],
- stubs: {
- symbol_file: "libcompos_client.map.txt",
- },
- apex_available: [
- "com.android.compos",
- ],
- visibility: [
- "//packages/modules/Virtualization/compos:__subpackages__",
- "//art/odrefresh:__subpackages__",
- ],
-}
-
-// TODO(203478530): Once rust_ffi supports stubs/symbol file, remove the wrapping cc_library above.
-rust_ffi {
- name: "libcompos_client_ffi",
- crate_name: "compos_client_ffi",
- srcs: ["libcompos_client.rs"],
- include_dirs: ["include"],
- rustlibs: [
- "android.system.composd.internal-rust",
- "compos_aidl_interface-rust",
- "libandroid_logger",
- "libanyhow",
- "libbinder_common",
- "libbinder_rs",
- "libcompos_common",
- "liblibc",
- "liblog_rust",
- "libminijail_rust",
- "libnix",
- "libscopeguard",
- ],
- prefer_rlib: true,
- shared_libs: [
- "libbinder_ndk",
- ],
- apex_available: [
- "com.android.compos",
- ],
- visibility: [
- "//packages/modules/Virtualization/compos:__subpackages__",
- "//art/odrefresh:__subpackages__",
- ],
-}
diff --git a/compos/libcompos_client/include/libcompos_client.h b/compos/libcompos_client/include/libcompos_client.h
deleted file mode 100644
index 171854d..0000000
--- a/compos/libcompos_client/include/libcompos_client.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-/**
- * Sends request encoded in a marshaled byte buffer to the Compilation OS service, which will
- * execute the compiler with context encoded in the marshaled byte buffer.
- *
- * @param cid the VM's cid to send the request to.
- * @param marshaled pointer to a marshaled byte buffer.
- * @param size size of the marshaled byte buffer pointed by `marshaled`.
- * @param ro_fds pointer to a int array of read-only file descriptor numbers.
- * @param ro_fds_num size of the array pointed by `ro_fds`.
- * @param rw_fds pointer to a int array of read-writable file descriptor numbers.
- * @param rw_fds_num size of the array pointed by `rw_fds`.
- * @return the exit code of the compiler.
- *
- * Available since API level 33.
- */
-int AComposClient_Request(int cid, const uint8_t* marshaled, size_t size, const int* ro_fds,
- size_t ro_fds_num, const int* rw_fds, size_t rw_fds_num)
- __INTRODUCED_IN(33);
-
-__END_DECLS
diff --git a/compos/libcompos_client/libcompos_client.map.txt b/compos/libcompos_client/libcompos_client.map.txt
deleted file mode 100644
index 9d47c53..0000000
--- a/compos/libcompos_client/libcompos_client.map.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-LIBCOMPOS_CLIENT {
- global:
- AComposClient_Request; # apex
- local:
- *;
-};
diff --git a/compos/libcompos_client/libcompos_client.rs b/compos/libcompos_client/libcompos_client.rs
deleted file mode 100644
index 701e515..0000000
--- a/compos/libcompos_client/libcompos_client.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//! A library for a client to send requests to the CompOS service in the VM.
-
-use anyhow::{Context, Result};
-use binder_common::rpc_client::connect_rpc_binder;
-use libc::c_int;
-use log::{debug, error, warn};
-use minijail::Minijail;
-use nix::fcntl::OFlag;
-use nix::unistd::pipe2;
-use std::fs::File;
-use std::io::Read;
-use std::os::unix::io::{AsRawFd, FromRawFd};
-use std::path::Path;
-use std::slice::from_raw_parts;
-
-use android_system_composd_internal::{
- aidl::android::system::composd::internal::ICompilationInternal::ICompilationInternal,
- binder::wait_for_interface,
-};
-use compos_aidl_interface::aidl::com::android::compos::{
- FdAnnotation::FdAnnotation, ICompOsService::ICompOsService,
-};
-use compos_aidl_interface::binder::Strong;
-use compos_common::{COMPOS_VSOCK_PORT, VMADDR_CID_ANY};
-
-const FD_SERVER_BIN: &str = "/apex/com.android.virt/bin/fd_server";
-
-fn get_composd() -> Result<Strong<dyn ICompilationInternal>> {
- wait_for_interface::<dyn ICompilationInternal>("android.system.composd.internal")
- .context("Failed to find ICompilationInternal")
-}
-
-fn spawn_fd_server(fd_annotation: &FdAnnotation, ready_file: File) -> Result<Minijail> {
- let mut inheritable_fds = Vec::new();
- let mut args = vec![FD_SERVER_BIN.to_string()];
- for fd in &fd_annotation.input_fds {
- args.push("--ro-fds".to_string());
- args.push(fd.to_string());
- inheritable_fds.push(*fd);
- }
- for fd in &fd_annotation.output_fds {
- args.push("--rw-fds".to_string());
- args.push(fd.to_string());
- inheritable_fds.push(*fd);
- }
- let ready_fd = ready_file.as_raw_fd();
- args.push("--ready-fd".to_string());
- args.push(ready_fd.to_string());
- inheritable_fds.push(ready_fd);
-
- let jail = Minijail::new()?;
- let _pid = jail.run(Path::new(FD_SERVER_BIN), &inheritable_fds, &args)?;
- Ok(jail)
-}
-
-fn create_pipe() -> Result<(File, File)> {
- let (raw_read, raw_write) = pipe2(OFlag::O_CLOEXEC)?;
- // SAFETY: We are the sole owners of these fds as they were just created.
- let read_fd = unsafe { File::from_raw_fd(raw_read) };
- let write_fd = unsafe { File::from_raw_fd(raw_write) };
- Ok((read_fd, write_fd))
-}
-
-fn wait_for_fd_server_ready(mut ready_fd: File) -> Result<()> {
- let mut buffer = [0];
- // When fd_server is ready it closes its end of the pipe. And if it exits, the pipe is also
- // closed. Either way this read will return 0 bytes at that point, and there's no point waiting
- // any longer.
- let _ = ready_fd.read(&mut buffer).context("Waiting for fd_server to be ready")?;
- debug!("fd_server is ready");
- Ok(())
-}
-
-fn try_request(cid: c_int, marshaled: &[u8], fd_annotation: FdAnnotation) -> Result<c_int> {
- // 1. Spawn a fd_server to serve remote read/write requests.
- let (ready_read_fd, ready_write_fd) = create_pipe()?;
- let fd_server_jail = spawn_fd_server(&fd_annotation, ready_write_fd)?;
- let fd_server_lifetime = scopeguard::guard(fd_server_jail, |fd_server_jail| {
- if let Err(e) = fd_server_jail.kill() {
- if !matches!(e, minijail::Error::Killed(_)) {
- warn!("Failed to kill fd_server: {}", e);
- }
- }
- });
-
- // 2. Send the marshaled request the remote.
- let cid = cid as u32;
- let result = if cid == VMADDR_CID_ANY {
- // Sentinel value that indicates we should use composd
- let composd = get_composd()?;
- wait_for_fd_server_ready(ready_read_fd)?;
- composd.compile(marshaled, &fd_annotation)
- } else {
- // Call directly into the VM
- let compos_vm = connect_rpc_binder::<dyn ICompOsService>(cid, COMPOS_VSOCK_PORT)
- .context("Cannot connect to RPC binder")?;
- wait_for_fd_server_ready(ready_read_fd)?;
- compos_vm.compile(marshaled, &fd_annotation)
- };
- let result = result.context("Binder call failed")?;
-
- // Be explicit about the lifetime, which should last at least until the task is finished.
- drop(fd_server_lifetime);
-
- Ok(c_int::from(result))
-}
-
-/// A public C API. See libcompos_client.h for the canonical doc.
-///
-/// # Safety
-///
-/// The client must provide legitimate pointers with correct sizes to the backing arrays.
-#[no_mangle]
-pub unsafe extern "C" fn AComposClient_Request(
- cid: c_int,
- marshaled: *const u8,
- size: usize,
- ro_fds: *const c_int,
- ro_fds_num: usize,
- rw_fds: *const c_int,
- rw_fds_num: usize,
-) -> c_int {
- if marshaled.is_null() || ro_fds.is_null() || rw_fds.is_null() {
- error!("Argument pointers should not be null");
- return -1;
- }
-
- // The unsafe parts.
- let ro_fd_slice = from_raw_parts(ro_fds, ro_fds_num);
- let rw_fd_slice = from_raw_parts(rw_fds, rw_fds_num);
- let marshaled_slice = from_raw_parts(marshaled, size);
-
- let fd_annotation =
- FdAnnotation { input_fds: ro_fd_slice.to_vec(), output_fds: rw_fd_slice.to_vec() };
-
- match try_request(cid, marshaled_slice, fd_annotation) {
- Ok(exit_code) => exit_code,
- Err(e) => {
- error!("AComposClient_Request failed: {:?}", e);
- -1
- }
- }
-}