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::{FsContext, SharedFdTable};
13use starnix_sync::{RwLockWriteGuard, allow_subclass};
14use starnix_task_command::TaskCommand;
15use starnix_types::arch::ArchWidth;
16use starnix_types::release_on_error;
17use starnix_uapi::auth::Credentials;
18use starnix_uapi::errors::Errno;
19use starnix_uapi::resource_limits::Resource;
20use starnix_uapi::signals::{SIGCHLD, Signal};
21use starnix_uapi::{errno, error, from_status_like_fdio, pid_t, rlimit};
22use std::ffi::CString;
23use std::sync::Arc;
24
25pub struct TaskInfo {
30 pub thread_group: Arc<ThreadGroup>,
32
33 pub memory_manager: Option<Arc<MemoryManager>>,
35}
36
37pub fn create_zircon_process(
38 kernel: &Arc<Kernel>,
39 parent: Option<ThreadGroupWriteGuard<'_>>,
40 pid: pid_t,
41 exit_signal: Option<Signal>,
42 process_group: Arc<ProcessGroup>,
43 signal_actions: Arc<SignalActions>,
44 name: TaskCommand,
45) -> Result<TaskInfo, Errno> {
46 if kernel.is_shutting_down() {
48 return error!(EBUSY);
49 }
50 let (process, root_vmar) =
51 create_shared(&kernel.kthreads.starnix_process, zx::ProcessOptions::empty(), name)
52 .map_err(|status| from_status_like_fdio!(status))?;
53
54 fuchsia_runtime::job_default()
56 .set_critical(zx::JobCriticalOptions::RETCODE_NONZERO, &process)
57 .map_err(|status| from_status_like_fdio!(status))?;
58
59 let thread_group = ThreadGroup::new(
60 kernel.clone(),
61 process,
62 root_vmar,
63 parent,
64 pid,
65 exit_signal,
66 process_group,
67 signal_actions,
68 );
69
70 Ok(TaskInfo { thread_group, memory_manager: None })
71}
72
73fn create_shared(
83 process: &zx::Process,
84 options: zx::ProcessOptions,
85 name: TaskCommand,
86) -> Result<(zx::Process, zx::Vmar), zx::Status> {
87 let self_raw = process.raw_handle();
88 let name_bytes = name.as_bytes();
89 let mut process_out = 0;
90 let mut restricted_vmar_out = 0;
91 #[allow(
92 clippy::undocumented_unsafe_blocks,
93 reason = "Force documented unsafe blocks in Starnix"
94 )]
95 let status = unsafe {
96 zx::sys::zx_process_create_shared(
97 self_raw,
98 options.bits(),
99 name_bytes.as_ptr(),
100 name_bytes.len(),
101 &mut process_out,
102 &mut restricted_vmar_out,
103 )
104 };
105 zx::ok(status)?;
106 #[allow(
107 clippy::undocumented_unsafe_blocks,
108 reason = "Force documented unsafe blocks in Starnix"
109 )]
110 unsafe {
111 Ok((
112 zx::Process::from(zx::NullableHandle::from_raw(process_out)),
113 zx::Vmar::from(zx::NullableHandle::from_raw(restricted_vmar_out)),
114 ))
115 }
116}
117
118pub fn create_init_child_process(
137 kernel: &Arc<Kernel>,
138 initial_name: TaskCommand,
139 mut creds: Credentials,
140 seclabel: Option<&CString>,
141) -> Result<TaskBuilder, Errno> {
142 let init_task = kernel.get_init_task()?;
143
144 let fs = init_task.running_state()?.fs().fork();
145
146 let security_state = if let Some(seclabel) = seclabel {
147 security::task_for_context(&init_task, seclabel.as_bytes().into())?
148 } else if let Some(default_seclabel) = kernel.features.default_seclabel.as_ref() {
149 security::task_for_context(&init_task, default_seclabel.as_bytes().into())?
150 } else {
151 security::task_for_context(&init_task, b"".into()).map_err(|_| {
153 errno!(EINVAL, "Container has SELinux enabled but no Security Context specified")
154 })?
155 };
156 creds.security_state = security_state;
157
158 let task = create_task(
159 kernel,
160 initial_name.clone(),
161 fs,
162 |pid, process_group| {
163 create_zircon_process(
164 kernel,
165 None,
166 pid,
167 Some(SIGCHLD),
168 process_group,
169 SignalActions::default(),
170 initial_name.clone(),
171 )
172 },
173 creds.into(),
174 )?;
175 {
176 let mut init_writer = init_task.thread_group().write();
177 let _token = allow_subclass();
180 let mut new_process_writer = task.thread_group().write();
181 new_process_writer.parent =
182 Some(ThreadGroupParent::new(Arc::downgrade(&init_task.thread_group())));
183 init_writer.children.insert(task.tid, Arc::downgrade(task.thread_group()));
184 }
185 let limits = init_task.thread_group().limits.lock().clone();
188 *task.thread_group().limits.lock() = limits;
189 Ok(task)
190}
191
192pub fn create_init_process(
211 kernel: &Arc<Kernel>,
212 pid: pid_t,
213 initial_name: TaskCommand,
214 fs: Arc<FsContext>,
215 rlimits: &[(Resource, u64)],
216) -> Result<TaskBuilder, Errno> {
217 assert_eq!(pid, 1);
218 let pids = kernel.pids.write();
219 let builder = create_task_with_pid(
220 kernel,
221 pids,
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(i32, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
277{
278 let mut pids = kernel.pids.write();
279 let pid = pids.allocate_pid();
280 create_task_with_pid(kernel, pids, pid, initial_name, root_fs, task_info_factory, creds, &[])
281}
282
283fn create_task_with_pid<F>(
284 kernel: &Kernel,
285 mut pids: RwLockWriteGuard<'_, PidTable>,
286 pid: pid_t,
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(i32, Arc<ProcessGroup>) -> Result<TaskInfo, Errno>,
295{
296 debug_assert!(pids.get_task(pid).is_err());
297
298 let process_group = ProcessGroup::new(pid, None);
299 pids.add_process_group(process_group.clone());
300
301 let TaskInfo { thread_group, memory_manager } = task_info_factory(pid, process_group.clone())?;
302
303 process_group.insert(&thread_group);
304
305 let default_timerslack = 50_000;
310 let builder = TaskBuilder {
311 task: Task::new(
312 pid,
313 initial_name,
314 thread_group,
315 SharedFdTable::default(),
316 memory_manager,
317 root_fs,
318 creds,
319 Arc::clone(&kernel.default_abstract_socket_namespace),
320 Arc::clone(&kernel.default_abstract_vsock_namespace),
321 Default::default(),
322 Default::default(),
323 None,
324 Default::default(),
325 kernel.root_uts_ns.clone(),
326 false,
327 SeccompState::default(),
328 SeccompFilterContainer::default(),
329 RobustListHeadPtr::null(&ArchWidth::Arch64),
330 default_timerslack,
331 ),
332 thread_state: Default::default(),
333 };
334 release_on_error!(builder, {
335 builder.thread_group().add(Arc::clone(&builder.task))?;
336 for (resource, limit) in rlimits {
337 builder
338 .thread_group()
339 .limits
340 .lock()
341 .set(*resource, rlimit { rlim_cur: *limit, rlim_max: *limit });
342 }
343
344 pids.add_task(Arc::clone(&builder.task));
345 Ok(())
346 });
347 Ok(builder)
348}
349
350pub fn create_kernel_thread(
354 system_task: &Task,
355 initial_name: TaskCommand,
356) -> Result<CurrentTask, Errno> {
357 let mut pids = system_task.kernel().pids.write();
358 let pid = pids.allocate_pid();
359
360 let scheduler_state;
361 let uts_ns;
362 let default_timerslack_ns;
363 {
364 let state = system_task.read();
365 scheduler_state = state.scheduler_state;
366 uts_ns = state.uts_ns.clone();
367 default_timerslack_ns = state.default_timerslack_ns;
368 }
369
370 let mm;
371 let fs;
372 let abstract_socket_namespace;
373 let abstract_vsock_namespace;
374 {
375 let running_state = system_task.running_state()?;
376 mm = running_state.mm.to_option_arc();
377 fs = running_state.fs.to_arc();
378 abstract_socket_namespace = running_state.abstract_socket_namespace.clone();
379 abstract_vsock_namespace = running_state.abstract_vsock_namespace.clone();
380 }
381
382 let current_task: CurrentTask = TaskBuilder::new(Task::new(
383 pid,
384 initial_name,
385 system_task.thread_group().clone(),
386 SharedFdTable::default(),
387 mm,
388 fs,
389 system_task.clone_creds(),
390 abstract_socket_namespace,
391 abstract_vsock_namespace,
392 Default::default(),
393 Default::default(),
394 None,
395 scheduler_state,
396 uts_ns,
397 false,
398 SeccompState::default(),
399 SeccompFilterContainer::default(),
400 RobustListHeadPtr::null(&ArchWidth::Arch64),
401 default_timerslack_ns,
402 ))
403 .into();
404 release_on_error!(current_task, {
405 current_task.thread_group().add(Arc::clone(¤t_task.task))?;
406 pids.add_task(Arc::clone(¤t_task.task));
407 Ok(())
408 });
409 Ok(current_task)
410}