/*
 * 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.
 */

//! compsvc is a service to run computational tasks in a PVM upon request. It is able to set up
//! file descriptors backed by fd_server and pass the file descriptors to the actual tasks for
//! read/write. The service also attempts to sandbox the execution so that one task cannot leak or
//! impact future tasks.
//!
//! Example:
//! $ compsvc /system/bin/sleep
//!
//! The current architecture / process hierarchy looks like:
//! - compsvc (handle requests)
//!   - compsvc_worker (for environment setup)
//!     - authfs (fd translation)
//!     - actual task

use anyhow::{bail, Context, Result};
use binder::unstable_api::AsNative;
use log::{debug, error};
use minijail::{self, Minijail};
use std::path::PathBuf;

use compos_aidl_interface::aidl::com::android::compos::ICompService::{
    BnCompService, ICompService,
};
use compos_aidl_interface::aidl::com::android::compos::Metadata::Metadata;
use compos_aidl_interface::binder::{
    add_service, BinderFeatures, Interface, ProcessState, Result as BinderResult, Status,
    StatusCode, Strong,
};

mod common;
use common::{SERVICE_NAME, VSOCK_PORT};

const WORKER_BIN: &str = "/apex/com.android.compos/bin/compsvc_worker";
// TODO: Replace with a valid directory setup in the VM.
const AUTHFS_MOUNTPOINT: &str = "/data/local/tmp/authfs_mnt";

struct CompService {
    worker_bin: PathBuf,
    task_bin: String,
    rpc_binder: bool,
    debuggable: bool,
}

impl CompService {
    pub fn new_binder(service: CompService) -> Strong<dyn ICompService> {
        BnCompService::new_binder(service, BinderFeatures::default())
    }

    fn run_worker_in_jail_and_wait(&self, args: &[String]) -> Result<(), minijail::Error> {
        let mut jail = Minijail::new()?;

        // TODO(b/185175567): New user and uid namespace when supported. Run as nobody.
        // New mount namespace to isolate the FUSE mount.
        jail.namespace_vfs();

        let inheritable_fds = if self.debuggable {
            vec![1, 2] // inherit/redirect stdout/stderr for debugging
        } else {
            vec![]
        };
        let _pid = jail.run(&self.worker_bin, &inheritable_fds, &args)?;
        jail.wait()
    }

    fn build_worker_args(&self, args: &[String], metadata: &Metadata) -> Vec<String> {
        let mut worker_args = vec![
            WORKER_BIN.to_string(),
            "--authfs-root".to_string(),
            AUTHFS_MOUNTPOINT.to_string(),
        ];
        for annotation in &metadata.input_fd_annotations {
            worker_args.push("--in-fd".to_string());
            worker_args.push(format!("{}:{}", annotation.fd, annotation.file_size));
        }
        for annotation in &metadata.output_fd_annotations {
            worker_args.push("--out-fd".to_string());
            worker_args.push(annotation.fd.to_string());
        }
        if self.debuggable {
            worker_args.push("--debug".to_string());
        }
        worker_args.push("--".to_string());

        // Do not accept arbitrary code execution. We want to execute some specific task of this
        // service. Use the associated executable.
        worker_args.push(self.task_bin.clone());
        worker_args.extend_from_slice(&args[1..]);
        worker_args
    }
}

impl Interface for CompService {}

impl ICompService for CompService {
    fn execute(&self, args: &[String], metadata: &Metadata) -> BinderResult<i8> {
        let worker_args = self.build_worker_args(args, metadata);

        match self.run_worker_in_jail_and_wait(&worker_args) {
            Ok(_) => Ok(0), // TODO(b/161471326): Sign the output on succeed.
            Err(minijail::Error::ReturnCode(exit_code)) => {
                error!("Task failed with exit code {}", exit_code);
                Err(Status::from(StatusCode::FAILED_TRANSACTION))
            }
            Err(e) => {
                error!("Unexpected error: {}", e);
                Err(Status::from(StatusCode::UNKNOWN_ERROR))
            }
        }
    }
}

fn parse_args() -> Result<CompService> {
    #[rustfmt::skip]
    let matches = clap::App::new("compsvc")
        .arg(clap::Arg::with_name("debug")
             .long("debug"))
        .arg(clap::Arg::with_name("task_bin")
             .required(true))
        .arg(clap::Arg::with_name("rpc_binder")
             .long("rpc-binder"))
        .get_matches();

    Ok(CompService {
        task_bin: matches.value_of("task_bin").unwrap().to_string(),
        worker_bin: PathBuf::from(WORKER_BIN),
        rpc_binder: matches.is_present("rpc_binder"),
        debuggable: matches.is_present("debug"),
    })
}

fn main() -> Result<()> {
    android_logger::init_once(
        android_logger::Config::default().with_tag("compsvc").with_min_level(log::Level::Debug),
    );

    let service = parse_args()?;

    if service.rpc_binder {
        let mut service = CompService::new_binder(service).as_binder();
        debug!("compsvc is starting as a rpc service.");
        // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
        // Plus the binder objects are threadsafe.
        let retval = unsafe {
            binder_rpc_unstable_bindgen::RunRpcServer(
                service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder,
                VSOCK_PORT,
            )
        };
        if retval {
            debug!("RPC server has shut down gracefully");
            Ok(())
        } else {
            bail!("Premature termination of RPC server");
        }
    } else {
        ProcessState::start_thread_pool();
        debug!("compsvc is starting as a local service.");
        add_service(SERVICE_NAME, CompService::new_binder(service).as_binder())
            .with_context(|| format!("Failed to register service {}", SERVICE_NAME))?;
        ProcessState::join_thread_pool();
        bail!("Unexpected exit after join_thread_pool")
    }
}
