1use crate::mm::MemoryManager;
6use crate::security;
7use crate::signals::SignalActions;
8use crate::task::{
9 CurrentTask, Kernel, Pid, PidTableGuard, ProcessGroup, RobustListHeadPtr,
10 SeccompFilterContainer, SeccompState, Task, TaskBuilder, ThreadGroup, ThreadGroupParent,
11 ThreadGroupWriteGuard,
12};
13use crate::vfs::{FsContext, SharedFdTable};
14use starnix_sync::allow_subclass;
15use starnix_task_command::TaskCommand;
16use starnix_types::arch::ArchWidth;
17use starnix_types::release_on_error;
18use starnix_uapi::auth::Credentials;
19use starnix_uapi::errors::Errno;
20use starnix_uapi::resource_limits::Resource;
21use starnix_uapi::signals::{SIGCHLD, Signal};
22use starnix_uapi::{errno, error, from_status_like_fdio, rlimit};
23use std::ffi::CString;
24use std::sync::Arc;
25
26pub struct TaskInfo {
31 pub thread_group: Arc<ThreadGroup>,
33
34 pub memory_manager: Option<Arc<MemoryManager>>,
36}
37
38pub fn create_zircon_process(
39 kernel: &Arc<Kernel>,
40 parent: Option<ThreadGroupWriteGuard<'_>>,
41 pid: Pid,
42 exit_signal: Option<Signal>,
43 process_group: Arc<ProcessGroup>,
44 signal_actions: Arc<SignalActions>,
45 name: TaskCommand,
46) -> Result<TaskInfo, Errno> {
47 if kernel.is_shutting_down() {
49 return error!(EBUSY);
50 }
51 let (process, root_vmar) =
52 create_shared(&kernel.kthreads.starnix_process, zx::ProcessOptions::empty(), name)
53 .map_err(|status| from_status_like_fdio!(status))?;
54
55 fuchsia_runtime::job_default()
57 .set_critical(zx::JobCriticalOptions::RETCODE_NONZERO, &process)
58 .map_err(|status| from_status_like_fdio!(status))?;
59
60 let thread_group = ThreadGroup::new(
61 kernel.clone(),
62 process,
63 root_vmar,
64 parent,
65 pid,
66 exit_signal,
67 process_group,
68 signal_actions,
69 );
70
71 Ok(TaskInfo { thread_group, memory_manager: None })
72}
73
74fn create_shared(
84 process: &zx::Process,
85 options: zx::ProcessOptions,
86 name: TaskCommand,
87) -> Result<(zx::Process, zx::Vmar), zx::Status> {
88 let self_raw = process.raw_handle();
89 let name_bytes = name.as_bytes();
90 let mut process_out = 0;
91 let mut restricted_vmar_out = 0;
92 #[allow(
93 clippy::undocumented_unsafe_blocks,
94 reason = "Force documented unsafe blocks in Starnix"
95 )]
96 let status = unsafe {
97 zx::sys::zx_process_create_shared(
98 self_raw,
99 options.bits(),
100 name_bytes.as_ptr(),
101 name_bytes.len(),
102 &mut process_out,
103 &mut restricted_vmar_out,
104 )
105 };
106 zx::ok(status)?;
107 #[allow(
108 clippy::undocumented_unsafe_blocks,
109 reason = "Force documented unsafe blocks in Starnix"
110 )]
111 unsafe {
112 Ok((
113 zx::Process::from(zx::NullableHandle::from_raw(process_out)),
114 zx::Vmar::from(zx::NullableHandle::from_raw(restricted_vmar_out)),
115 ))
116 }
117}
118
119pub fn create_init_child_process(
138 kernel: &Arc<Kernel>,
139 initial_name: TaskCommand,
140 mut creds: Credentials,
141 seclabel: Option<&CString>,
142) -> Result<TaskBuilder, Errno> {
143 let init_task = kernel.get_init_task()?;
144
145 let fs = init_task.running_state()?.fs().fork();
146
147 let security_state = if let Some(seclabel) = seclabel {
148 security::task_for_context(&init_task, seclabel.as_bytes().into())?
149 } else if let Some(default_seclabel) = kernel.features.default_seclabel.as_ref() {
150 security::task_for_context(&init_task, default_seclabel.as_bytes().into())?
151 } else {
152 security::task_for_context(&init_task, b"".into()).map_err(|_| {
154 errno!(EINVAL, "Container has SELinux enabled but no Security Context specified")
155 })?
156 };
157 creds.security_state = security_state;
158
159 let task = create_task(
160 kernel,
161 initial_name.clone(),
162 fs,
163 |pid, process_group| {
164 create_zircon_process(
165 kernel,
166 None,
167 pid,
168 Some(SIGCHLD),
169 process_group,
170 SignalActions::default(),
171 initial_name.clone(),
172 )
173 },
174 creds.into(),
175 )?;
176 {
177 let mut init_writer = init_task.thread_group().write();
178 let _token = allow_subclass();
181 let mut new_process_writer = task.thread_group().write();
182 new_process_writer.parent =
183 Some(ThreadGroupParent::new(Arc::downgrade(&init_task.thread_group())));
184 init_writer.children.insert(task.tid.id, Arc::downgrade(task.thread_group()));
185 }
186 let limits = init_task.thread_group().limits.lock().clone();
189 *task.thread_group().limits.lock() = limits;
190 Ok(task)
191}
192
193pub fn create_init_process(
212 kernel: &Arc<Kernel>,
213 pid: Pid,
214 initial_name: TaskCommand,
215 fs: Arc<FsContext>,
216 rlimits: &[(Resource, u64)],
217) -> Result<TaskBuilder, Errno> {
218 assert_eq!(pid.id, 1);
219 let builder = create_task_with_pid(
220 kernel,
221 kernel.pids.lock(),
222 pid,
223 initial_name.clone(),
224 fs,
225 |pid, process_group| {
226 create_zircon_process(
227 kernel,
228 None,
229 pid,
230 Some(SIGCHLD),
231 process_group,
232 SignalActions::default(),
233 initial_name.clone(),
234 )
235 },
236 Credentials::root(),
237 rlimits,
238 )?;
239 let _ = kernel.init_task.set(Arc::downgrade(&builder.task));
240 Ok(builder)
241}
242
243pub fn create_system_task(kernel: &Arc<Kernel>, fs: Arc<FsContext>) -> Result<CurrentTask, Errno> {
255 let builder = create_task(
256 kernel,
257 TaskCommand::new(b"kthreadd"),
258 fs,
259 |pid, process_group| {
260 let thread_group = ThreadGroup::for_system(kernel.clone(), pid, process_group);
261 Ok(TaskInfo { thread_group, memory_manager: None }.into())
262 },
263 Credentials::root(),
264 )?;
265 Ok(builder.into())
266}
267
268pub fn create_task<F>(
269 kernel: &Kernel,
270 initial_name: TaskCommand,
271 root_fs: Arc<FsContext>,
272 task_info_factory: F,
273 creds: Arc<Credentials>,
274) -> Result<TaskBuilder, Errno>
275where
276 F: FnOnce(Pid, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
277{
278 let mut guard = kernel.pids.lock();
279 let pid = guard.allocate_pid()?;
280 create_task_with_pid(kernel, guard, pid, initial_name, root_fs, task_info_factory, creds, &[])
281}
282
283fn create_task_with_pid<F>(
284 kernel: &Kernel,
285 mut pids: PidTableGuard<'_>,
286 pid: Pid,
287 initial_name: TaskCommand,
288 root_fs: Arc<FsContext>,
289 task_info_factory: F,
290 creds: Arc<Credentials>,
291 rlimits: &[(Resource, u64)],
292) -> Result<TaskBuilder, Errno>
293where
294 F: FnOnce(Pid, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
295{
296 debug_assert!(pid.get_task().is_err());
297
298 let process_group = ProcessGroup::new(pid.clone(), None);
299
300 let TaskInfo { thread_group, memory_manager } =
301 task_info_factory(pid.clone(), process_group.clone())?;
302
303 pids.add_process_group(&process_group);
304 process_group.insert(&thread_group);
305
306 let default_timerslack = 50_000;
311 let builder = TaskBuilder {
312 task: Task::new(
313 pid,
314 initial_name,
315 thread_group,
316 SharedFdTable::default(),
317 memory_manager,
318 root_fs,
319 creds,
320 Arc::clone(&kernel.default_abstract_socket_namespace),
321 Arc::clone(&kernel.default_abstract_vsock_namespace),
322 Default::default(),
323 Default::default(),
324 None,
325 Default::default(),
326 kernel.root_uts_ns.clone(),
327 false,
328 SeccompState::default(),
329 SeccompFilterContainer::default(),
330 RobustListHeadPtr::null(&ArchWidth::Arch64),
331 default_timerslack,
332 ),
333 thread_state: Default::default(),
334 };
335 release_on_error!(builder, {
336 builder.thread_group().add(Arc::clone(&builder.task))?;
337 for (resource, limit) in rlimits {
338 builder
339 .thread_group()
340 .limits
341 .lock()
342 .set(*resource, rlimit { rlim_cur: *limit, rlim_max: *limit });
343 }
344
345 pids.add_task(Arc::clone(&builder.task));
346 Ok(())
347 });
348 Ok(builder)
349}
350
351pub fn create_kernel_thread(
355 system_task: &Task,
356 initial_name: TaskCommand,
357) -> Result<CurrentTask, Errno> {
358 let mut pids = system_task.kernel().pids.lock();
359 let pid = pids.allocate_pid()?;
360
361 let scheduler_state;
362 let uts_ns;
363 let default_timerslack_ns;
364 {
365 let state = system_task.read();
366 scheduler_state = state.scheduler_state;
367 uts_ns = state.uts_ns.clone();
368 default_timerslack_ns = state.default_timerslack_ns;
369 }
370
371 let mm;
372 let fs;
373 let abstract_socket_namespace;
374 let abstract_vsock_namespace;
375 {
376 let running_state = system_task.running_state()?;
377 mm = running_state.mm.upgrade();
378 fs = running_state.fs();
379 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
380 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
381 }
382
383 let current_task: CurrentTask = TaskBuilder::new(Task::new(
384 pid,
385 initial_name,
386 system_task.thread_group().clone(),
387 SharedFdTable::default(),
388 mm,
389 fs,
390 system_task.clone_creds(),
391 abstract_socket_namespace,
392 abstract_vsock_namespace,
393 Default::default(),
394 Default::default(),
395 None,
396 scheduler_state,
397 uts_ns,
398 false,
399 SeccompState::default(),
400 SeccompFilterContainer::default(),
401 RobustListHeadPtr::null(&ArchWidth::Arch64),
402 default_timerslack_ns,
403 ))
404 .into();
405 release_on_error!(current_task, {
406 current_task.thread_group().add(Arc::clone(¤t_task.task))?;
407 pids.add_task(Arc::clone(¤t_task.task));
408 Ok(())
409 });
410 Ok(current_task)
411}
412
413#[cfg(test)]
414mod test {
415 use super::*;
416 use crate::testing::*;
417
418 #[::fuchsia::test]
419 async fn test_create_task_failure_does_not_add_process_group() {
420 spawn_kernel_and_run(async |current_task| {
421 let kernel = current_task.kernel();
422 let (kept_pg_sender, kept_pg_receiver) = std::sync::mpsc::channel();
423 let result = super::create_task(
424 kernel,
425 TaskCommand::new(b"failed_task"),
426 current_task.fs(),
427 |_pid, process_group| {
428 let _ = kept_pg_sender.send(process_group);
429 error!(EINVAL)
430 },
431 Credentials::root(),
432 );
433 assert!(result.is_err());
434 let kept_pg = kept_pg_receiver.recv().unwrap();
435 let pid_entry = kernel.pids.get(kept_pg.leader.id).unwrap().clone();
436 assert_eq!(pid_entry.get_process_group(), error!(ESRCH));
437 })
438 .await;
439 }
440}