1use crate::mm::MemoryManager;
6use crate::security;
7use crate::signals::SignalActions;
8use crate::task::{
9 CurrentTask, Kernel, PidTable, ProcessGroup, RobustListHeadPtr, SeccompFilterContainer,
10 SeccompState, Task, TaskBuilder, ThreadGroup, ThreadGroupParent, ThreadGroupWriteGuard,
11};
12use crate::vfs::{FdTable, FsContext};
13use starnix_sync::{
14 LockBefore, Locked, ProcessGroupState, RwLockWriteGuard, TaskRelease, Unlocked, allow_subclass,
15};
16use starnix_task_command::TaskCommand;
17use starnix_types::arch::ArchWidth;
18use starnix_types::release_on_error;
19use starnix_uapi::auth::Credentials;
20use starnix_uapi::errors::Errno;
21use starnix_uapi::resource_limits::Resource;
22use starnix_uapi::signals::{SIGCHLD, Signal};
23use starnix_uapi::{errno, error, from_status_like_fdio, pid_t, rlimit};
24use std::ffi::CString;
25use std::sync::Arc;
26
27pub struct TaskInfo {
32 pub thread_group: Arc<ThreadGroup>,
34
35 pub memory_manager: Option<Arc<MemoryManager>>,
37}
38
39pub fn create_zircon_process<L>(
40 locked: &mut Locked<L>,
41 kernel: &Arc<Kernel>,
42 parent: Option<ThreadGroupWriteGuard<'_>>,
43 pid: pid_t,
44 exit_signal: Option<Signal>,
45 process_group: Arc<ProcessGroup>,
46 signal_actions: Arc<SignalActions>,
47 name: TaskCommand,
48) -> Result<TaskInfo, Errno>
49where
50 L: LockBefore<ProcessGroupState>,
51{
52 if kernel.is_shutting_down() {
54 return error!(EBUSY);
55 }
56 let (process, root_vmar) =
57 create_shared(&kernel.kthreads.starnix_process, zx::ProcessOptions::empty(), name)
58 .map_err(|status| from_status_like_fdio!(status))?;
59
60 fuchsia_runtime::job_default()
62 .set_critical(zx::JobCriticalOptions::RETCODE_NONZERO, &process)
63 .map_err(|status| from_status_like_fdio!(status))?;
64
65 let thread_group = ThreadGroup::new(
66 locked,
67 kernel.clone(),
68 process,
69 root_vmar,
70 parent,
71 pid,
72 exit_signal,
73 process_group,
74 signal_actions,
75 );
76
77 Ok(TaskInfo { thread_group, memory_manager: None })
78}
79
80fn create_shared(
90 process: &zx::Process,
91 options: zx::ProcessOptions,
92 name: TaskCommand,
93) -> Result<(zx::Process, zx::Vmar), zx::Status> {
94 let self_raw = process.raw_handle();
95 let name_bytes = name.as_bytes();
96 let mut process_out = 0;
97 let mut restricted_vmar_out = 0;
98 #[allow(
99 clippy::undocumented_unsafe_blocks,
100 reason = "Force documented unsafe blocks in Starnix"
101 )]
102 let status = unsafe {
103 zx::sys::zx_process_create_shared(
104 self_raw,
105 options.bits(),
106 name_bytes.as_ptr(),
107 name_bytes.len(),
108 &mut process_out,
109 &mut restricted_vmar_out,
110 )
111 };
112 zx::ok(status)?;
113 #[allow(
114 clippy::undocumented_unsafe_blocks,
115 reason = "Force documented unsafe blocks in Starnix"
116 )]
117 unsafe {
118 Ok((
119 zx::Process::from(zx::NullableHandle::from_raw(process_out)),
120 zx::Vmar::from(zx::NullableHandle::from_raw(restricted_vmar_out)),
121 ))
122 }
123}
124
125pub fn create_init_child_process<L>(
144 locked: &mut Locked<L>,
145 kernel: &Arc<Kernel>,
146 initial_name: TaskCommand,
147 mut creds: Credentials,
148 seclabel: Option<&CString>,
149) -> Result<TaskBuilder, Errno>
150where
151 L: LockBefore<TaskRelease>,
152{
153 let init_task = kernel.get_init_task()?;
154
155 let fs = init_task.running_state()?.fs().fork();
156
157 let security_state = if let Some(seclabel) = seclabel {
158 security::task_for_context(&init_task, seclabel.as_bytes().into())?
159 } else if let Some(default_seclabel) = kernel.features.default_seclabel.as_ref() {
160 security::task_for_context(&init_task, default_seclabel.as_bytes().into())?
161 } else {
162 security::task_for_context(&init_task, b"".into()).map_err(|_| {
164 errno!(EINVAL, "Container has SELinux enabled but no Security Context specified")
165 })?
166 };
167 creds.security_state = security_state;
168
169 let task = create_task(
170 locked,
171 kernel,
172 initial_name.clone(),
173 fs,
174 |locked, pid, process_group| {
175 create_zircon_process(
176 locked.cast_locked::<TaskRelease>(),
177 kernel,
178 None,
179 pid,
180 Some(SIGCHLD),
181 process_group,
182 SignalActions::default(),
183 initial_name.clone(),
184 )
185 },
186 creds.into(),
187 )?;
188 {
189 let mut init_writer = init_task.thread_group().write();
190 let _token = allow_subclass();
193 let mut new_process_writer = task.thread_group().write();
194 new_process_writer.parent =
195 Some(ThreadGroupParent::new(Arc::downgrade(&init_task.thread_group())));
196 init_writer.children.insert(task.tid, Arc::downgrade(task.thread_group()));
197 }
198 let limits = init_task.thread_group().limits.lock(locked.cast_locked::<TaskRelease>()).clone();
201 *task.thread_group().limits.lock(locked.cast_locked::<TaskRelease>()) = limits;
202 Ok(task)
203}
204
205pub fn create_init_process(
224 locked: &mut Locked<Unlocked>,
225 kernel: &Arc<Kernel>,
226 pid: pid_t,
227 initial_name: TaskCommand,
228 fs: Arc<FsContext>,
229 rlimits: &[(Resource, u64)],
230) -> Result<TaskBuilder, Errno> {
231 assert_eq!(pid, 1);
232 let pids = kernel.pids.write();
233 let builder = create_task_with_pid(
234 locked,
235 kernel,
236 pids,
237 pid,
238 initial_name.clone(),
239 fs,
240 |locked, pid, process_group| {
241 create_zircon_process(
242 locked,
243 kernel,
244 None,
245 pid,
246 Some(SIGCHLD),
247 process_group,
248 SignalActions::default(),
249 initial_name.clone(),
250 )
251 },
252 Credentials::root(),
253 rlimits,
254 )?;
255 let _ = kernel.init_task.set(Arc::downgrade(&builder.task));
256 Ok(builder)
257}
258
259pub fn create_system_task<L>(
271 locked: &mut Locked<L>,
272 kernel: &Arc<Kernel>,
273 fs: Arc<FsContext>,
274) -> Result<CurrentTask, Errno>
275where
276 L: LockBefore<TaskRelease>,
277{
278 let builder = create_task(
279 locked,
280 kernel,
281 TaskCommand::new(b"kthreadd"),
282 fs,
283 |locked, pid, process_group| {
284 let thread_group = ThreadGroup::for_system(
285 locked.cast_locked::<TaskRelease>(),
286 kernel.clone(),
287 pid,
288 process_group,
289 );
290 Ok(TaskInfo { thread_group, memory_manager: None }.into())
291 },
292 Credentials::root(),
293 )?;
294 Ok(builder.into())
295}
296
297pub fn create_task<F, L>(
298 locked: &mut Locked<L>,
299 kernel: &Kernel,
300 initial_name: TaskCommand,
301 root_fs: Arc<FsContext>,
302 task_info_factory: F,
303 creds: Arc<Credentials>,
304) -> Result<TaskBuilder, Errno>
305where
306 F: FnOnce(&mut Locked<L>, i32, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
307 L: LockBefore<TaskRelease>,
308{
309 let mut pids = kernel.pids.write();
310 let pid = pids.allocate_pid();
311 create_task_with_pid(
312 locked,
313 kernel,
314 pids,
315 pid,
316 initial_name,
317 root_fs,
318 task_info_factory,
319 creds,
320 &[],
321 )
322}
323
324fn create_task_with_pid<F, L>(
325 locked: &mut Locked<L>,
326 kernel: &Kernel,
327 mut pids: RwLockWriteGuard<'_, PidTable>,
328 pid: pid_t,
329 initial_name: TaskCommand,
330 root_fs: Arc<FsContext>,
331 task_info_factory: F,
332 creds: Arc<Credentials>,
333 rlimits: &[(Resource, u64)],
334) -> Result<TaskBuilder, Errno>
335where
336 F: FnOnce(&mut Locked<L>, i32, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
337 L: LockBefore<TaskRelease>,
338{
339 debug_assert!(pids.get_task(pid).is_err());
340
341 let process_group = ProcessGroup::new(pid, None);
342 pids.add_process_group(process_group.clone());
343
344 let TaskInfo { thread_group, memory_manager } =
345 task_info_factory(locked, pid, process_group.clone())?;
346
347 process_group.insert(locked.cast_locked::<TaskRelease>(), &thread_group);
348
349 let default_timerslack = 50_000;
354 let builder = TaskBuilder {
355 task: Task::new(
356 pid,
357 initial_name,
358 thread_group,
359 FdTable::default(),
360 memory_manager,
361 root_fs,
362 creds,
363 Arc::clone(&kernel.default_abstract_socket_namespace),
364 Arc::clone(&kernel.default_abstract_vsock_namespace),
365 Default::default(),
366 Default::default(),
367 None,
368 Default::default(),
369 kernel.root_uts_ns.clone(),
370 false,
371 SeccompState::default(),
372 SeccompFilterContainer::default(),
373 RobustListHeadPtr::null(&ArchWidth::Arch64),
374 default_timerslack,
375 ),
376 thread_state: Default::default(),
377 };
378 release_on_error!(builder, locked, {
379 builder.thread_group().add(Arc::clone(&builder.task))?;
380 for (resource, limit) in rlimits {
381 builder
382 .thread_group()
383 .limits
384 .lock(locked.cast_locked::<TaskRelease>())
385 .set(*resource, rlimit { rlim_cur: *limit, rlim_max: *limit });
386 }
387
388 pids.add_task(Arc::clone(&builder.task));
389 Ok(())
390 });
391 Ok(builder)
392}
393
394pub fn create_kernel_thread<L>(
398 locked: &mut Locked<L>,
399 system_task: &Task,
400 initial_name: TaskCommand,
401) -> Result<CurrentTask, Errno>
402where
403 L: LockBefore<TaskRelease>,
404{
405 let mut pids = system_task.kernel().pids.write();
406 let pid = pids.allocate_pid();
407
408 let scheduler_state;
409 let uts_ns;
410 let default_timerslack_ns;
411 {
412 let state = system_task.read();
413 scheduler_state = state.scheduler_state;
414 uts_ns = state.uts_ns.clone();
415 default_timerslack_ns = state.default_timerslack_ns;
416 }
417
418 let mm;
419 let fs;
420 let abstract_socket_namespace;
421 let abstract_vsock_namespace;
422 {
423 let running_state = system_task.running_state()?;
424 mm = running_state.mm.to_option_arc();
425 fs = running_state.fs.to_arc();
426 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
427 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
428 }
429
430 let current_task: CurrentTask = TaskBuilder::new(Task::new(
431 pid,
432 initial_name,
433 system_task.thread_group().clone(),
434 FdTable::default(),
435 mm,
436 fs,
437 system_task.clone_creds(),
438 abstract_socket_namespace,
439 abstract_vsock_namespace,
440 Default::default(),
441 Default::default(),
442 None,
443 scheduler_state,
444 uts_ns,
445 false,
446 SeccompState::default(),
447 SeccompFilterContainer::default(),
448 RobustListHeadPtr::null(&ArchWidth::Arch64),
449 default_timerslack_ns,
450 ))
451 .into();
452 release_on_error!(current_task, locked, {
453 current_task.thread_group().add(Arc::clone(¤t_task.task))?;
454 pids.add_task(Arc::clone(¤t_task.task));
455 Ok(())
456 });
457 Ok(current_task)
458}