David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 1 | // Copyright 2022, The Android Open Source Project |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | //! Android Virtualization Manager |
| 16 | |
| 17 | mod aidl; |
| 18 | mod atom; |
| 19 | mod composite; |
| 20 | mod crosvm; |
Jaewan Kim | c03f661 | 2023-02-20 00:06:26 +0900 | [diff] [blame] | 21 | mod debug_config; |
Shikha Panwar | 55e10ec | 2024-02-13 12:53:49 +0000 | [diff] [blame] | 22 | mod dt_overlay; |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 23 | mod payload; |
| 24 | mod selinux; |
| 25 | |
David Brazdil | 4b4c510 | 2022-12-19 22:56:20 +0000 | [diff] [blame] | 26 | use crate::aidl::{GLOBAL_SERVICE, VirtualizationService}; |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 27 | use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::BnVirtualizationService; |
Jiyong Park | 7d67171 | 2024-09-11 08:29:22 +0900 | [diff] [blame] | 28 | use anyhow::{bail, Result}; |
David Brazdil | 4b4c510 | 2022-12-19 22:56:20 +0000 | [diff] [blame] | 29 | use binder::{BinderFeatures, ProcessState}; |
Jeff Vander Stoep | 57da157 | 2024-01-31 10:52:16 +0100 | [diff] [blame] | 30 | use log::{info, LevelFilter}; |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 31 | use rpcbinder::{FileDescriptorTransportMode, RpcServer}; |
Jiyong Park | 7d67171 | 2024-09-11 08:29:22 +0900 | [diff] [blame] | 32 | use std::os::unix::io::{AsFd, RawFd}; |
Andrew Walbran | 9c03a3a | 2024-09-03 12:12:59 +0100 | [diff] [blame] | 33 | use std::sync::LazyLock; |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 34 | use clap::Parser; |
Seungjae Yoo | daf396a | 2024-04-15 12:58:07 +0900 | [diff] [blame] | 35 | use nix::unistd::{write, Pid, Uid}; |
Jiyong Park | 7d67171 | 2024-09-11 08:29:22 +0900 | [diff] [blame] | 36 | use rustutils::inherited_fd::take_fd_ownership; |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 37 | use std::os::unix::raw::{pid_t, uid_t}; |
| 38 | |
| 39 | const LOG_TAG: &str = "virtmgr"; |
| 40 | |
Andrew Walbran | 9c03a3a | 2024-09-03 12:12:59 +0100 | [diff] [blame] | 41 | static PID_CURRENT: LazyLock<Pid> = LazyLock::new(Pid::this); |
| 42 | static PID_PARENT: LazyLock<Pid> = LazyLock::new(Pid::parent); |
| 43 | static UID_CURRENT: LazyLock<Uid> = LazyLock::new(Uid::current); |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 44 | |
Seungjae Yoo | 13af0b6 | 2024-05-20 14:15:13 +0900 | [diff] [blame] | 45 | fn get_this_pid() -> pid_t { |
| 46 | // Return the process ID of this process. |
| 47 | PID_CURRENT.as_raw() |
| 48 | } |
| 49 | |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 50 | fn get_calling_pid() -> pid_t { |
| 51 | // The caller is the parent of this process. |
| 52 | PID_PARENT.as_raw() |
| 53 | } |
| 54 | |
| 55 | fn get_calling_uid() -> uid_t { |
| 56 | // The caller and this process share the same UID. |
| 57 | UID_CURRENT.as_raw() |
| 58 | } |
| 59 | |
| 60 | #[derive(Parser)] |
| 61 | struct Args { |
| 62 | /// File descriptor inherited from the caller to run RpcBinder server on. |
| 63 | /// This should be one end of a socketpair() compatible with RpcBinder's |
| 64 | /// UDS bootstrap transport. |
| 65 | #[clap(long)] |
| 66 | rpc_server_fd: RawFd, |
| 67 | /// File descriptor inherited from the caller to signal RpcBinder server |
| 68 | /// readiness. This should be one end of pipe() and the caller should be |
| 69 | /// waiting for HUP on the other end. |
| 70 | #[clap(long)] |
| 71 | ready_fd: RawFd, |
| 72 | } |
| 73 | |
Alan Stokes | c4d5def | 2023-02-14 17:01:59 +0000 | [diff] [blame] | 74 | fn check_vm_support() -> Result<()> { |
| 75 | if hypervisor_props::is_any_vm_supported()? { |
| 76 | Ok(()) |
| 77 | } else { |
| 78 | // This should never happen, it indicates a misconfigured device where the virt APEX |
| 79 | // is present but VMs are not supported. If it does happen, fail fast to avoid wasting |
| 80 | // resources trying. |
| 81 | bail!("Device doesn't support protected or non-protected VMs") |
| 82 | } |
Alan Stokes | 8d39a9b | 2023-01-10 15:01:00 +0000 | [diff] [blame] | 83 | } |
| 84 | |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 85 | fn main() { |
Jiyong Park | 7d67171 | 2024-09-11 08:29:22 +0900 | [diff] [blame] | 86 | // SAFETY: nobody has taken ownership of the inherited FDs yet. |
| 87 | unsafe { rustutils::inherited_fd::init_once() } |
| 88 | .expect("Failed to take ownership of inherited FDs"); |
| 89 | |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 90 | android_logger::init_once( |
| 91 | android_logger::Config::default() |
| 92 | .with_tag(LOG_TAG) |
Jeff Vander Stoep | 57da157 | 2024-01-31 10:52:16 +0100 | [diff] [blame] | 93 | .with_max_level(LevelFilter::Info) |
| 94 | .with_log_buffer(android_logger::LogId::System), |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 95 | ); |
| 96 | |
Alan Stokes | c4d5def | 2023-02-14 17:01:59 +0000 | [diff] [blame] | 97 | check_vm_support().unwrap(); |
Alan Stokes | 8d39a9b | 2023-01-10 15:01:00 +0000 | [diff] [blame] | 98 | |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 99 | let args = Args::parse(); |
| 100 | |
Jiyong Park | 7d67171 | 2024-09-11 08:29:22 +0900 | [diff] [blame] | 101 | let rpc_server_fd = |
| 102 | take_fd_ownership(args.rpc_server_fd).expect("Failed to take ownership of rpc_server_fd"); |
| 103 | let ready_fd = take_fd_ownership(args.ready_fd).expect("Failed to take ownership of ready_fd"); |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 104 | |
David Brazdil | 4b4c510 | 2022-12-19 22:56:20 +0000 | [diff] [blame] | 105 | // Start thread pool for kernel Binder connection to VirtualizationServiceInternal. |
| 106 | ProcessState::start_thread_pool(); |
| 107 | |
Inseob Kim | b198f6e | 2024-07-22 18:06:15 +0900 | [diff] [blame] | 108 | if cfg!(early) { |
Inseob Kim | ecde8c0 | 2024-09-03 13:11:08 +0900 | [diff] [blame] | 109 | // we can't access VirtualizationServiceInternal, so directly call rlimit |
| 110 | let pid = i32::from(*PID_CURRENT); |
| 111 | let lim = libc::rlimit { rlim_cur: libc::RLIM_INFINITY, rlim_max: libc::RLIM_INFINITY }; |
| 112 | |
| 113 | // SAFETY: borrowing the new limit struct only. prlimit doesn't use lim outside its lifetime |
| 114 | let ret = unsafe { libc::prlimit(pid, libc::RLIMIT_MEMLOCK, &lim, std::ptr::null_mut()) }; |
| 115 | if ret == -1 { |
| 116 | panic!("rlimit error: {}", std::io::Error::last_os_error()); |
| 117 | } else if ret != 0 { |
| 118 | panic!("Unexpected return value from prlimit(): {ret}"); |
| 119 | } |
Inseob Kim | b198f6e | 2024-07-22 18:06:15 +0900 | [diff] [blame] | 120 | } else { |
| 121 | GLOBAL_SERVICE.removeMemlockRlimit().expect("Failed to remove memlock rlimit"); |
| 122 | } |
David Brazdil | 4b4c510 | 2022-12-19 22:56:20 +0000 | [diff] [blame] | 123 | |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 124 | let service = VirtualizationService::init(); |
| 125 | let service = |
| 126 | BnVirtualizationService::new_binder(service, BinderFeatures::default()).as_binder(); |
| 127 | |
| 128 | let server = RpcServer::new_unix_domain_bootstrap(service, rpc_server_fd) |
| 129 | .expect("Failed to start RpcServer"); |
| 130 | server.set_supported_file_descriptor_transport_modes(&[FileDescriptorTransportMode::Unix]); |
| 131 | |
| 132 | info!("Started VirtualizationService RpcServer. Ready to accept connections"); |
| 133 | |
| 134 | // Signal readiness to the caller by closing our end of the pipe. |
Seungjae Yoo | daf396a | 2024-04-15 12:58:07 +0900 | [diff] [blame] | 135 | write(ready_fd.as_fd(), "o".as_bytes()) |
| 136 | .expect("Failed to write a single character through ready_fd"); |
David Brazdil | 1f53070 | 2022-10-03 12:18:10 +0100 | [diff] [blame] | 137 | drop(ready_fd); |
| 138 | |
| 139 | server.join(); |
| 140 | info!("Shutting down VirtualizationService RpcServer"); |
| 141 | } |