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,
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 mut new_process_writer = task.thread_group().write();
191 new_process_writer.parent =
192 Some(ThreadGroupParent::new(Arc::downgrade(&init_task.thread_group())));
193 init_writer.children.insert(task.tid, Arc::downgrade(task.thread_group()));
194 }
195 let limits = init_task.thread_group().limits.lock(locked.cast_locked::<TaskRelease>()).clone();
198 *task.thread_group().limits.lock(locked.cast_locked::<TaskRelease>()) = limits;
199 Ok(task)
200}
201
202pub fn create_init_process(
221 locked: &mut Locked<Unlocked>,
222 kernel: &Arc<Kernel>,
223 pid: pid_t,
224 initial_name: TaskCommand,
225 fs: Arc<FsContext>,
226 rlimits: &[(Resource, u64)],
227) -> Result<TaskBuilder, Errno> {
228 assert_eq!(pid, 1);
229 let pids = kernel.pids.write();
230 let builder = create_task_with_pid(
231 locked,
232 kernel,
233 pids,
234 pid,
235 initial_name.clone(),
236 fs,
237 |locked, pid, process_group| {
238 create_zircon_process(
239 locked,
240 kernel,
241 None,
242 pid,
243 Some(SIGCHLD),
244 process_group,
245 SignalActions::default(),
246 initial_name.clone(),
247 )
248 },
249 Credentials::root(),
250 rlimits,
251 )?;
252 let _ = kernel.init_task.set(Arc::downgrade(&builder.task));
253 Ok(builder)
254}
255
256pub fn create_system_task<L>(
268 locked: &mut Locked<L>,
269 kernel: &Arc<Kernel>,
270 fs: Arc<FsContext>,
271) -> Result<CurrentTask, Errno>
272where
273 L: LockBefore<TaskRelease>,
274{
275 let builder = create_task(
276 locked,
277 kernel,
278 TaskCommand::new(b"kthreadd"),
279 fs,
280 |locked, pid, process_group| {
281 let thread_group = ThreadGroup::for_system(
282 locked.cast_locked::<TaskRelease>(),
283 kernel.clone(),
284 pid,
285 process_group,
286 );
287 Ok(TaskInfo { thread_group, memory_manager: None }.into())
288 },
289 Credentials::root(),
290 )?;
291 Ok(builder.into())
292}
293
294pub fn create_task<F, L>(
295 locked: &mut Locked<L>,
296 kernel: &Kernel,
297 initial_name: TaskCommand,
298 root_fs: Arc<FsContext>,
299 task_info_factory: F,
300 creds: Arc<Credentials>,
301) -> Result<TaskBuilder, Errno>
302where
303 F: FnOnce(&mut Locked<L>, i32, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
304 L: LockBefore<TaskRelease>,
305{
306 let mut pids = kernel.pids.write();
307 let pid = pids.allocate_pid();
308 create_task_with_pid(
309 locked,
310 kernel,
311 pids,
312 pid,
313 initial_name,
314 root_fs,
315 task_info_factory,
316 creds,
317 &[],
318 )
319}
320
321fn create_task_with_pid<F, L>(
322 locked: &mut Locked<L>,
323 kernel: &Kernel,
324 mut pids: RwLockWriteGuard<'_, PidTable>,
325 pid: pid_t,
326 initial_name: TaskCommand,
327 root_fs: Arc<FsContext>,
328 task_info_factory: F,
329 creds: Arc<Credentials>,
330 rlimits: &[(Resource, u64)],
331) -> Result<TaskBuilder, Errno>
332where
333 F: FnOnce(&mut Locked<L>, i32, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
334 L: LockBefore<TaskRelease>,
335{
336 debug_assert!(pids.get_task(pid).is_err());
337
338 let process_group = ProcessGroup::new(pid, None);
339 pids.add_process_group(process_group.clone());
340
341 let TaskInfo { thread_group, memory_manager } =
342 task_info_factory(locked, pid, process_group.clone())?;
343
344 process_group.insert(locked.cast_locked::<TaskRelease>(), &thread_group);
345
346 let default_timerslack = 50_000;
351 let builder = TaskBuilder {
352 task: Task::new(
353 pid,
354 initial_name,
355 thread_group,
356 FdTable::default(),
357 memory_manager,
358 root_fs,
359 creds,
360 Arc::clone(&kernel.default_abstract_socket_namespace),
361 Arc::clone(&kernel.default_abstract_vsock_namespace),
362 Default::default(),
363 Default::default(),
364 None,
365 Default::default(),
366 kernel.root_uts_ns.clone(),
367 false,
368 SeccompState::default(),
369 SeccompFilterContainer::default(),
370 RobustListHeadPtr::null(&ArchWidth::Arch64),
371 default_timerslack,
372 ),
373 thread_state: Default::default(),
374 };
375 release_on_error!(builder, locked, {
376 builder.thread_group().add(Arc::clone(&builder.task))?;
377 for (resource, limit) in rlimits {
378 builder
379 .thread_group()
380 .limits
381 .lock(locked.cast_locked::<TaskRelease>())
382 .set(*resource, rlimit { rlim_cur: *limit, rlim_max: *limit });
383 }
384
385 pids.add_task(Arc::clone(&builder.task));
386 Ok(())
387 });
388 Ok(builder)
389}
390
391pub fn create_kernel_thread<L>(
395 locked: &mut Locked<L>,
396 system_task: &Task,
397 initial_name: TaskCommand,
398) -> Result<CurrentTask, Errno>
399where
400 L: LockBefore<TaskRelease>,
401{
402 let mut pids = system_task.kernel().pids.write();
403 let pid = pids.allocate_pid();
404
405 let scheduler_state;
406 let uts_ns;
407 let default_timerslack_ns;
408 {
409 let state = system_task.read();
410 scheduler_state = state.scheduler_state;
411 uts_ns = state.uts_ns.clone();
412 default_timerslack_ns = state.default_timerslack_ns;
413 }
414
415 let mm;
416 let fs;
417 let abstract_socket_namespace;
418 let abstract_vsock_namespace;
419 {
420 let running_state = system_task.running_state()?;
421 mm = running_state.mm.to_option_arc();
422 fs = running_state.fs.to_arc();
423 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
424 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
425 }
426
427 let current_task: CurrentTask = TaskBuilder::new(Task::new(
428 pid,
429 initial_name,
430 system_task.thread_group().clone(),
431 FdTable::default(),
432 mm,
433 fs,
434 system_task.clone_creds(),
435 abstract_socket_namespace,
436 abstract_vsock_namespace,
437 Default::default(),
438 Default::default(),
439 None,
440 scheduler_state,
441 uts_ns,
442 false,
443 SeccompState::default(),
444 SeccompFilterContainer::default(),
445 RobustListHeadPtr::null(&ArchWidth::Arch64),
446 default_timerslack_ns,
447 ))
448 .into();
449 release_on_error!(current_task, locked, {
450 current_task.thread_group().add(Arc::clone(¤t_task.task))?;
451 pids.add_task(Arc::clone(¤t_task.task));
452 Ok(())
453 });
454 Ok(current_task)
455}