crosvm/crosvm/sys/linux/
ext2.rs1use std::path::Path;
26
27use anyhow::Context;
28use anyhow::Result;
29use base::error;
30use base::AsRawDescriptor;
31use base::Pid;
32use base::SharedMemory;
33use base::Tube;
34use jail::create_base_minijail;
35use jail::create_sandbox_minijail;
36use jail::fork_process;
37use jail::JailConfig;
38use jail::RunAsUser;
39use jail::SandboxConfig;
40use vm_control::api::VmMemoryClient;
41use vm_control::VmMemoryFileMapping;
42use vm_memory::GuestAddress;
43
44pub fn launch(
46 mapping_address: GuestAddress,
47 vm_memory_client: VmMemoryClient,
48 device_tube: Tube, path: &Path,
50 ugid: &(Option<u32>, Option<u32>),
51 ugid_map: (&str, &str),
52 mut builder: ext2::Builder,
53 jail_config: Option<&JailConfig>,
54) -> Result<Pid> {
55 let max_open_files = base::linux::max_open_files()
56 .context("failed to get max number of open files")?
57 .rlim_max;
58
59 let jail = if let Some(jail_config) = jail_config {
60 let mut config = SandboxConfig::new(jail_config, "virtual_ext2");
61 config.limit_caps = false;
62 config.ugid_map = Some(ugid_map);
63 config.remount_mode = Some(libc::MS_SLAVE);
66 config.run_as = match *ugid {
67 (None, None) => RunAsUser::Unspecified,
68 (uid_opt, gid_opt) => RunAsUser::Specified(uid_opt.unwrap_or(0), gid_opt.unwrap_or(0)),
69 };
70 create_sandbox_minijail(path, max_open_files, &config)?
71 } else {
72 create_base_minijail(path, max_open_files)?
73 };
74
75 builder.root_dir = Some(std::path::PathBuf::from("/"));
77
78 let shm = SharedMemory::new("pmem_ext2_shm", builder.size as u64)
79 .context("failed to create shared memory")?;
80 let mut keep_rds = vec![
81 shm.as_raw_descriptor(),
82 vm_memory_client.as_raw_descriptor(),
83 device_tube.as_raw_descriptor(),
84 ];
85 base::syslog::push_descriptors(&mut keep_rds);
86
87 let child_process = fork_process(jail, keep_rds, Some(String::from("mkfs process")), || {
88 if let Err(e) = mkfs_callback(vm_memory_client, mapping_address, device_tube, builder, shm)
89 {
90 error!("failed to create file system: {:#}", e);
91 unsafe { libc::exit(1) };
93 }
94 })
95 .context("failed to fork a process for mkfs")?;
96 Ok(child_process.pid)
97}
98
99fn mkfs_callback(
102 mem_client: VmMemoryClient,
103 mapping_address: GuestAddress,
104 device_tube: Tube, builder: ext2::Builder,
106 shm: SharedMemory,
107) -> Result<()> {
108 let file_mappings = builder
109 .build_on_shm(&shm)
110 .context("failed to build memory region")?
111 .build_mmap_info()
112 .context("failed to build ext2")?
113 .mapping_info;
114
115 let file_mapping_info: Vec<_> = file_mappings
116 .into_iter()
117 .map(|info| VmMemoryFileMapping {
118 file: info.file,
119 length: info.length,
120 mem_offset: info.mem_offset,
121 file_offset: info.file_offset as u64,
122 })
123 .collect();
124
125 let slot = mem_client
126 .mmap_and_register_memory(mapping_address, shm, file_mapping_info)
127 .context("failed to request mmaping and registering memory")?;
128 device_tube
129 .send(&slot)
130 .context("failed to send VmMemoryRequest::RegisterMemory")?;
131 Ok(())
132}