1use crate::fs::tmpfs::TmpFs;
6use crate::mm::MemoryManager;
7use crate::security;
8use crate::signals::SignalActions;
9use crate::task::{
10 CurrentTask, Kernel, Pid, PidTableGuard, RobustListHeadPtr, SeccompFilterContainer,
11 SeccompState, Task, TaskBuilder, ThreadGroup, ThreadGroupParent, ThreadGroupWriteGuard,
12};
13use crate::vfs::{FsContext, Namespace, 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;
25use std::sync::atomic::Ordering;
26
27pub struct TaskInfo {
32 pub thread_group: Arc<ThreadGroup>,
34
35 pub memory_manager: Option<Arc<MemoryManager>>,
37}
38
39#[derive(Clone, Copy, Debug, PartialEq, Eq)]
41pub enum CreateDuringShutdown {
42 Never,
44 UntilDeadline,
47}
48
49pub fn create_zircon_process(
50 kernel: &Arc<Kernel>,
51 parent: Option<ThreadGroupWriteGuard<'_>>,
52 pid: Pid,
53 exit_signal: Option<Signal>,
54 signal_actions: Arc<SignalActions>,
55 name: TaskCommand,
56 create_during_shutdown: CreateDuringShutdown,
57) -> Result<TaskInfo, Errno> {
58 let deferred_shutdown_deadline = kernel.deferred_shutdown_deadline();
63 if let Some(deadline) = deferred_shutdown_deadline {
64 if create_during_shutdown == CreateDuringShutdown::Never
65 || zx::MonotonicInstant::get() >= deadline
66 {
67 return error!(EBUSY);
68 }
69 }
70 let (process, root_vmar) =
71 create_shared(&kernel.kthreads.starnix_process, zx::ProcessOptions::empty(), name)
72 .map_err(|status| from_status_like_fdio!(status))?;
73
74 fuchsia_runtime::job_default()
76 .set_critical(zx::JobCriticalOptions::RETCODE_NONZERO, &process)
77 .map_err(|status| from_status_like_fdio!(status))?;
78
79 let thread_group = ThreadGroup::new(
80 kernel.clone(),
81 process,
82 root_vmar,
83 parent,
84 pid,
85 exit_signal,
86 signal_actions,
87 );
88 if deferred_shutdown_deadline.is_some() {
89 thread_group.created_during_shutdown.store(true, Ordering::Relaxed);
90 }
91
92 Ok(TaskInfo { thread_group, memory_manager: None })
93}
94
95fn create_shared(
105 process: &zx::Process,
106 options: zx::ProcessOptions,
107 name: TaskCommand,
108) -> Result<(zx::Process, zx::Vmar), zx::Status> {
109 let self_raw = process.raw_handle();
110 let name_bytes = name.as_bytes();
111 let mut process_out = 0;
112 let mut restricted_vmar_out = 0;
113 #[allow(
114 clippy::undocumented_unsafe_blocks,
115 reason = "Force documented unsafe blocks in Starnix"
116 )]
117 let status = unsafe {
118 zx::sys::zx_process_create_shared(
119 self_raw,
120 options.bits(),
121 name_bytes.as_ptr(),
122 name_bytes.len(),
123 &mut process_out,
124 &mut restricted_vmar_out,
125 )
126 };
127 zx::ok(status)?;
128 #[allow(
129 clippy::undocumented_unsafe_blocks,
130 reason = "Force documented unsafe blocks in Starnix"
131 )]
132 unsafe {
133 Ok((
134 zx::Process::from(zx::NullableHandle::from_raw(process_out)),
135 zx::Vmar::from(zx::NullableHandle::from_raw(restricted_vmar_out)),
136 ))
137 }
138}
139
140pub fn create_init_child_process(
159 kernel: &Arc<Kernel>,
160 initial_name: TaskCommand,
161 mut creds: Credentials,
162 seclabel: Option<&CString>,
163) -> Result<TaskBuilder, Errno> {
164 let init_task = kernel.get_init_task()?;
165
166 let fs = init_task.fs()?.fork();
167
168 let security_state = if let Some(seclabel) = seclabel {
169 security::task_for_context(&init_task, seclabel.as_bytes().into())?
170 } else if let Some(default_seclabel) = kernel.features.default_seclabel.as_ref() {
171 security::task_for_context(&init_task, default_seclabel.as_bytes().into())?
172 } else {
173 security::task_for_context(&init_task, b"".into()).map_err(|_| {
175 errno!(EINVAL, "Container has SELinux enabled but no Security Context specified")
176 })?
177 };
178 creds.security_state = security_state;
179
180 let task = create_task(
181 kernel,
182 initial_name.clone(),
183 fs,
184 |pid| {
185 create_zircon_process(
186 kernel,
187 None,
188 pid,
189 Some(SIGCHLD),
190 SignalActions::default(),
191 initial_name.clone(),
192 CreateDuringShutdown::Never,
193 )
194 },
195 creds.into(),
196 )?;
197 {
198 let mut init_writer = init_task.thread_group().write();
199 let _token = allow_subclass();
202 let mut new_process_writer = task.thread_group().write();
203 new_process_writer.parent =
204 Some(ThreadGroupParent::new(Arc::downgrade(&init_task.thread_group())));
205 init_writer.children.insert(task.pid.clone());
206 }
207 let limits = init_task.thread_group().limits.lock().clone();
210 *task.thread_group().limits.lock() = limits;
211 Ok(task)
212}
213
214pub fn create_init_process(
233 kernel: &Arc<Kernel>,
234 pid: Pid,
235 initial_name: TaskCommand,
236 fs: Arc<FsContext>,
237 rlimits: &[(Resource, u64)],
238) -> Result<TaskBuilder, Errno> {
239 assert_eq!(pid.id, 1);
240 let builder = create_task_with_pid(
241 kernel,
242 kernel.pids.lock(),
243 pid,
244 initial_name.clone(),
245 fs,
246 |pid| {
247 create_zircon_process(
248 kernel,
249 None,
250 pid,
251 Some(SIGCHLD),
252 SignalActions::default(),
253 initial_name.clone(),
254 CreateDuringShutdown::Never,
255 )
256 },
257 Credentials::root(),
258 rlimits,
259 )?;
260 let _ = kernel.init_task.set(Arc::downgrade(&builder.task));
261 Ok(builder)
262}
263
264pub fn create_system_task(kernel: &Arc<Kernel>) -> Result<CurrentTask, Errno> {
278 let fs = FsContext::new(Namespace::new(TmpFs::new_fs_with_name(kernel, "rootfs".into())));
279 let builder = create_task(
280 kernel,
281 TaskCommand::new(b"kthreadd"),
282 fs,
283 |pid| {
284 let thread_group = ThreadGroup::for_system(kernel.clone(), pid);
285 Ok(TaskInfo { thread_group, memory_manager: None }.into())
286 },
287 Credentials::root(),
288 )?;
289 Ok(builder.into())
290}
291
292pub fn create_task<F>(
293 kernel: &Kernel,
294 initial_name: TaskCommand,
295 root_fs: Arc<FsContext>,
296 task_info_factory: F,
297 creds: Arc<Credentials>,
298) -> Result<TaskBuilder, Errno>
299where
300 F: FnOnce(Pid) -> Result<TaskInfo, Errno>,
301{
302 let mut guard = kernel.pids.lock();
303 let pid = guard.allocate_pid()?;
304 create_task_with_pid(kernel, guard, pid, initial_name, root_fs, task_info_factory, creds, &[])
305}
306
307fn create_task_with_pid<F>(
308 kernel: &Kernel,
309 mut pids: PidTableGuard<'_>,
310 pid: Pid,
311 initial_name: TaskCommand,
312 root_fs: Arc<FsContext>,
313 task_info_factory: F,
314 creds: Arc<Credentials>,
315 rlimits: &[(Resource, u64)],
316) -> Result<TaskBuilder, Errno>
317where
318 F: FnOnce(Pid) -> Result<TaskInfo, Errno>,
319{
320 debug_assert!(pid.get_task().is_err());
321
322 let TaskInfo { thread_group, memory_manager } = task_info_factory(pid.clone())?;
323
324 let default_timerslack = 50_000;
329 let builder = TaskBuilder {
330 task: Task::new(
331 pid,
332 initial_name,
333 thread_group,
334 SharedFdTable::default(),
335 memory_manager,
336 root_fs,
337 creds,
338 Arc::clone(&kernel.default_abstract_socket_namespace),
339 Arc::clone(&kernel.default_abstract_vsock_namespace),
340 Default::default(),
341 Default::default(),
342 None,
343 Default::default(),
344 kernel.root_uts_ns.clone(),
345 false,
346 SeccompState::default(),
347 SeccompFilterContainer::default(),
348 RobustListHeadPtr::null(&ArchWidth::Arch64),
349 default_timerslack,
350 ),
351 thread_state: Default::default(),
352 };
353 release_on_error!(builder, {
354 builder.thread_group().add(Arc::clone(&builder.task))?;
355 for (resource, limit) in rlimits {
356 builder
357 .thread_group()
358 .limits
359 .lock()
360 .set(*resource, rlimit { rlim_cur: *limit, rlim_max: *limit });
361 }
362
363 let sid = builder.thread_group().read().session.clone();
364 pids.add_task(Arc::clone(&builder.task));
365 pids.attach_pgid(&builder.thread_group().pgid(), builder.thread_group());
366 pids.attach_sid(&sid, builder.thread_group());
367 Ok(())
368 });
369 Ok(builder)
370}
371
372pub fn create_kernel_thread(
376 system_task: &Task,
377 initial_name: TaskCommand,
378) -> Result<CurrentTask, Errno> {
379 let mut pids = system_task.kernel().pids.lock();
380 let pid = pids.allocate_pid()?;
381
382 let scheduler_state = system_task.scheduler_state.lock().fork();
383 let uts_ns;
384 let default_timerslack_ns;
385 {
386 let state = system_task.read();
387 uts_ns = state.uts_ns.clone();
388 default_timerslack_ns = state.default_timerslack_ns;
389 }
390
391 let mm;
392 let fs;
393 let abstract_socket_namespace;
394 let abstract_vsock_namespace;
395 {
396 let running_state = system_task.running_state()?;
397 mm = running_state.mm.upgrade();
398 fs = running_state.fs()?;
399 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
400 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
401 }
402
403 let current_task: CurrentTask = TaskBuilder::new(Task::new(
404 pid,
405 initial_name,
406 system_task.thread_group().clone(),
407 SharedFdTable::default(),
408 mm,
409 fs,
410 system_task.clone_creds(),
411 abstract_socket_namespace,
412 abstract_vsock_namespace,
413 Default::default(),
414 Default::default(),
415 None,
416 scheduler_state,
417 uts_ns,
418 false,
419 SeccompState::default(),
420 SeccompFilterContainer::default(),
421 RobustListHeadPtr::null(&ArchWidth::Arch64),
422 default_timerslack_ns,
423 ))
424 .into();
425 release_on_error!(current_task, {
426 current_task.thread_group().add(Arc::clone(¤t_task.task))?;
427 pids.add_task(Arc::clone(¤t_task.task));
428 Ok(())
429 });
430 Ok(current_task)
431}
432
433#[cfg(test)]
434mod test {
435 use super::*;
436 use crate::testing::*;
437 use fuchsia_rcu::RcuReadScope;
438
439 #[::fuchsia::test]
440 async fn test_create_task_failure_does_not_add_process_group() {
441 spawn_kernel_and_run(async |current_task| {
442 let kernel = current_task.kernel();
443 let (kept_pid_sender, kept_pid_receiver) = std::sync::mpsc::channel();
444 let result = super::create_task(
445 kernel,
446 TaskCommand::new(b"failed_task"),
447 current_task.fs(),
448 |pid| {
449 let _ = kept_pid_sender.send(pid);
450 error!(EINVAL)
451 },
452 Credentials::root(),
453 );
454 assert!(result.is_err());
455 let kept_pid = kept_pid_receiver.recv().unwrap();
456 assert!(!kept_pid.is_process_group(&RcuReadScope::new()));
457 })
458 .await;
459 }
460}