1use crate::{
5 memory::{AddressSpace, UserSliceRead, VmaFlags, VmaPageSize, VmaType},
6 process::{
7 current_task_clone,
8 elf::{load_elf_image, LoadedElfInfo, USER_STACK_BASE, USER_STACK_PAGES, USER_STACK_TOP},
9 get_task_ids_in_tgid,
10 },
11 syscall::{error::SyscallError, SyscallFrame},
12 vfs,
13};
14use alloc::vec::Vec;
15
16const AT_NULL: u64 = 0;
17const AT_PHDR: u64 = 3;
18const AT_PHENT: u64 = 4;
19const AT_PHNUM: u64 = 5;
20const AT_PAGESZ: u64 = 6;
21const AT_BASE: u64 = 7;
22const AT_ENTRY: u64 = 9;
23const AT_RANDOM: u64 = 25;
24const AT_EXECFN: u64 = 31;
25
26fn read_exec_image(path: &str) -> Result<Option<Vec<u8>>, SyscallError> {
28 if crate::vfs::get_initfs_file_bytes(path).is_some() {
29 return Ok(None);
30 }
31
32 let fd = vfs::open(path, vfs::OpenFlags::READ)?;
33
34 const MAX_EXEC_SIZE: usize = 64 * 1024 * 1024;
35 let mut elf_data = Vec::new();
36 let mut buf = [0u8; 4096];
37 loop {
38 match vfs::read(fd, &mut buf) {
39 Ok(n) => {
40 if n == 0 {
41 break;
42 }
43 if elf_data.len() + n > MAX_EXEC_SIZE {
44 let _ = vfs::close(fd);
45 return Err(SyscallError::OutOfMemory);
46 }
47 elf_data.extend_from_slice(&buf[..n]);
48 }
49 Err(e) => {
50 let _ = vfs::close(fd);
51 return Err(e);
52 }
53 }
54 }
55 let _ = vfs::close(fd);
56
57 Ok(Some(elf_data))
58}
59
60pub fn sys_execve(
75 frame: &mut SyscallFrame,
76 path_ptr: u64,
77 argv_ptr: u64,
78 envp_ptr: u64,
79) -> Result<u64, SyscallError> {
80 let current = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
81
82 if get_task_ids_in_tgid(current.tgid).len() > 1 {
86 return Err(SyscallError::NotSupported);
87 }
88
89 let mut path_buf = [0u8; 4096];
90 let path_slice = UserSliceRead::new(path_ptr, 4096).map_err(|_| SyscallError::Fault)?;
91
92 let mut len = 0;
93
94 loop {
95 if len >= 4096 {
96 return Err(SyscallError::ArgumentListTooLong);
97 } let b = path_slice.read_u8(len).map_err(|_| SyscallError::Fault)?;
99 if b == 0 {
100 break;
101 }
102 path_buf[len] = b;
103 len += 1;
104 }
105 let path_str =
106 core::str::from_utf8(&path_buf[..len]).map_err(|_| SyscallError::InvalidArgument)?;
107
108 let exec_path = vfs::resolve_and_check_path_for_current_task(path_str, true, false, true)?;
109
110 let owned_elf_data = read_exec_image(&exec_path)?;
111 let elf_data = owned_elf_data
112 .as_deref()
113 .or_else(|| crate::vfs::get_initfs_file_bytes(&exec_path))
114 .ok_or(SyscallError::NotFound)?;
115
116 if elf_data.len() < 4 {
117 return Err(SyscallError::ExecFormatError);
118 }
119
120 let new_as = AddressSpace::new_user().map_err(|_| SyscallError::OutOfMemory)?;
121 let new_as_arc = alloc::sync::Arc::new(new_as);
122 new_as_arc.set_owner_pid(current.pid);
123
124 let load_info = match load_elf_image(elf_data, &new_as_arc) {
125 Ok(info) => info,
126 Err("PT_INTERP execute denied") => return Err(SyscallError::PermissionDenied),
127 Err(_) => return Err(SyscallError::ExecFormatError),
128 };
129
130 let stack_flags = VmaFlags {
131 readable: true,
132 writable: true,
133 executable: false,
134 user_accessible: true,
135 };
136 new_as_arc
137 .map_region(
138 USER_STACK_BASE,
139 USER_STACK_PAGES,
140 stack_flags,
141 VmaType::Stack,
142 VmaPageSize::Small,
143 )
144 .map_err(|_| SyscallError::OutOfMemory)?;
145
146 let sp = setup_user_stack(
147 &new_as_arc,
148 argv_ptr,
149 envp_ptr,
150 &load_info,
151 path_str.as_bytes(),
152 )?;
153
154 let mut new_fs_base = 0u64;
156 if load_info.tls_memsz > 0 {
157 let tls_align = core::cmp::max(load_info.tls_align, 8).next_power_of_two();
158 let aligned_memsz = (load_info.tls_memsz + tls_align - 1) & !(tls_align - 1);
159 let total_size = aligned_memsz + 8;
160 let n_pages = ((total_size + 4095) / 4096) as usize;
161 let tls_flags = VmaFlags {
162 readable: true,
163 writable: true,
164 executable: false,
165 user_accessible: true,
166 };
167 let tls_base = new_as_arc
168 .find_free_vma_range(0x7FFF_E000_0000, n_pages, VmaPageSize::Small)
169 .ok_or(SyscallError::OutOfMemory)?;
170 new_as_arc
171 .map_region(
172 tls_base,
173 n_pages,
174 tls_flags,
175 VmaType::Anonymous,
176 VmaPageSize::Small,
177 )
178 .map_err(|_| SyscallError::OutOfMemory)?;
179 if load_info.tls_filesz > 0 && load_info.tls_vaddr != 0 {
180 let src_vaddr = load_info.tls_vaddr;
181 let mut off = 0u64;
182 let mut tmp = [0u8; 256];
183 while off < load_info.tls_filesz {
184 let chunk = core::cmp::min(256, (load_info.tls_filesz - off) as usize);
185 crate::process::elf::read_user_mapped_bytes_pub(
186 &new_as_arc,
187 src_vaddr + off,
188 &mut tmp[..chunk],
189 )
190 .map_err(|_| SyscallError::Fault)?;
191 crate::process::elf::write_user_mapped_bytes_pub(
192 &new_as_arc,
193 tls_base + off,
194 &tmp[..chunk],
195 )
196 .map_err(|_| SyscallError::Fault)?;
197 off += chunk as u64;
198 }
199 }
200 let tp = tls_base + aligned_memsz;
201 crate::process::elf::write_user_u64_pub(&new_as_arc, tp, tp)
202 .map_err(|_| SyscallError::Fault)?;
203 new_fs_base = tp;
204 }
205
206 unsafe {
211 let fd_table = &mut *current.process.fd_table.get();
212 fd_table.close_cloexec();
213 }
214
215 current.reset_signals();
217
218 unsafe {
220 *current.signal_stack.get() = None;
221 }
222
223 current
225 .clear_child_tid
226 .store(0, core::sync::atomic::Ordering::Relaxed);
227 current
228 .user_fs_base
229 .store(new_fs_base, core::sync::atomic::Ordering::Relaxed);
230
231 current
233 .process
234 .brk
235 .store(0, core::sync::atomic::Ordering::Relaxed);
236 current
237 .process
238 .mmap_hint
239 .store(0x0000_0000_6000_0000, core::sync::atomic::Ordering::Relaxed);
240 unsafe {
242 let lo = new_fs_base as u32;
243 let hi = (new_fs_base >> 32) as u32;
244 core::arch::asm!(
245 "mov ecx, 0xC0000100", "wrmsr",
247 in("eax") lo,
248 in("edx") hi,
249 options(nostack, preserves_flags),
250 );
251 }
252
253 let old_as = current.process.replace_address_space(new_as_arc.clone());
254
255 unsafe {
256 current.process.address_space_arc().switch_to();
257 }
258
259 frame.iret_rip = load_info.runtime_entry;
260 frame.iret_rsp = sp;
261 frame.iret_rflags = 0x200; frame.rdi = 0;
264 frame.rsi = 0;
265 frame.rdx = 0;
266 frame.rcx = 0;
267 frame.r8 = 0;
268 frame.r9 = 0;
269 frame.r10 = 0;
270 frame.r11 = 0;
271 frame.rbx = 0;
272 frame.rbp = 0;
273 frame.r12 = 0;
274 frame.r13 = 0;
275 frame.r14 = 0;
276 frame.r15 = 0;
277 frame.rax = 0;
278
279 drop(old_as);
281
282 Ok(0)
283}
284
285fn setup_user_stack(
287 new_as: &AddressSpace,
288 argv_ptr: u64,
289 envp_ptr: u64,
290 elf_info: &LoadedElfInfo,
291 exec_path: &[u8],
292) -> Result<u64, SyscallError> {
293 let args = read_string_array(argv_ptr)?;
294 let envs = read_string_array(envp_ptr)?;
295
296 let mut sp = USER_STACK_TOP;
297 let mut str_ptrs: Vec<u64> = Vec::with_capacity(args.len()); let mut env_ptrs: Vec<u64> = Vec::with_capacity(envs.len()); for env in envs.iter().rev() {
307 let len = (env.len() + 1) as u64;
308 sp -= len;
309 write_bytes_to_as(new_as, sp, env)?;
310 write_bytes_to_as(new_as, sp + env.len() as u64, &[0])?;
311 env_ptrs.push(sp);
312 }
313 env_ptrs.reverse();
317
318 for arg in args.iter().rev() {
320 let len = (arg.len() + 1) as u64;
321 sp -= len;
322 write_bytes_to_as(new_as, sp, arg)?;
323 write_bytes_to_as(new_as, sp + arg.len() as u64, &[0])?;
324 str_ptrs.push(sp);
325 }
326 str_ptrs.reverse();
327
328 let mut execfn_ptr = 0u64;
330 if !exec_path.is_empty() {
331 let len = (exec_path.len() + 1) as u64;
332 sp -= len;
333 write_bytes_to_as(new_as, sp, exec_path)?;
334 write_bytes_to_as(new_as, sp + exec_path.len() as u64, &[0])?;
335 execfn_ptr = sp;
336 }
337
338 sp -= 16;
340 let rand_ptr = sp;
341 let seed = generate_aux_random_seed();
342 write_bytes_to_as(new_as, rand_ptr, &seed)?;
343
344 sp &= !0xF;
346
347 let size_ptr = 8u64;
349
350 let mut auxv: Vec<(u64, u64)> = Vec::with_capacity(10);
352 auxv.push((AT_PHDR, elf_info.phdr_vaddr));
353 auxv.push((AT_PHENT, elf_info.phent as u64));
354 auxv.push((AT_PHNUM, elf_info.phnum as u64));
355 auxv.push((AT_PAGESZ, 4096));
356 if let Some(base) = elf_info.interp_base {
357 auxv.push((AT_BASE, base));
358 }
359 auxv.push((AT_ENTRY, elf_info.program_entry));
360 auxv.push((AT_RANDOM, rand_ptr));
361 if execfn_ptr != 0 {
362 auxv.push((AT_EXECFN, execfn_ptr));
363 }
364
365 let stack_words = 1u64
368 + (str_ptrs.len() as u64 + 1)
369 + (env_ptrs.len() as u64 + 1)
370 + ((auxv.len() as u64 + 1) * 2);
371 let align_pad = (0u64.wrapping_sub(stack_words * size_ptr)) & 0xF;
372 sp -= align_pad;
373
374 sp -= size_ptr;
376 write_u64_to_as(new_as, sp, 0)?;
377 sp -= size_ptr;
378 write_u64_to_as(new_as, sp, AT_NULL)?;
379 for &(key, val) in auxv.iter().rev() {
380 sp -= size_ptr;
381 write_u64_to_as(new_as, sp, val)?;
382 sp -= size_ptr;
383 write_u64_to_as(new_as, sp, key)?;
384 }
385
386 sp -= size_ptr;
392 write_u64_to_as(new_as, sp, 0)?; for &ptr in env_ptrs.iter().rev() {
395 sp -= size_ptr;
396 write_u64_to_as(new_as, sp, ptr)?;
397 }
398 sp -= size_ptr;
406 write_u64_to_as(new_as, sp, 0)?; for &ptr in str_ptrs.iter().rev() {
409 sp -= size_ptr;
410 write_u64_to_as(new_as, sp, ptr)?;
411 }
412 sp -= size_ptr;
416 write_u64_to_as(new_as, sp, args.len() as u64)?;
417
418 debug_assert_eq!(sp & 0xF, 0);
419
420 Ok(sp)
421}
422
423fn read_string_array(ptr: u64) -> Result<Vec<Vec<u8>>, SyscallError> {
425 let mut res = Vec::new();
426 if ptr == 0 {
427 return Ok(res);
428 }
429
430 let mut arr_off = 0;
431 loop {
432 let str_ptr = match UserSliceRead::new(ptr + arr_off, 8) {
434 Ok(slice) => match slice.read_u64(0) {
435 Ok(p) => p,
436 Err(_) => return Err(SyscallError::Fault),
437 },
438 Err(_) => return Err(SyscallError::Fault),
439 };
440
441 if str_ptr == 0 {
442 break;
443 }
444 if res.len() > 1024 {
445 return Err(SyscallError::ArgumentListTooLong);
446 }
447
448 let mut s = Vec::new();
449 let mut i = 0;
450 loop {
451 if i > 4096 {
452 return Err(SyscallError::ArgumentListTooLong);
453 }
454 let b = match UserSliceRead::new(str_ptr + i, 1) {
455 Ok(slice) => match slice.read_u8(0) {
456 Ok(byte) => byte,
457 Err(_) => return Err(SyscallError::Fault),
458 },
459 Err(_) => return Err(SyscallError::Fault),
460 };
461 if b == 0 {
462 break;
463 }
464 s.push(b);
465 i += 1;
466 }
467 res.push(s);
468 arr_off += 8;
469 }
470 Ok(res)
471}
472
473fn write_bytes_to_as(as_ref: &AddressSpace, vaddr: u64, data: &[u8]) -> Result<(), SyscallError> {
475 use x86_64::VirtAddr;
476 let mut written = 0;
477 while written < data.len() {
488 let curr_vaddr = vaddr + written as u64;
489 let page_offset = (curr_vaddr & 0xFFF) as usize;
490 let chunk_size = core::cmp::min(data.len() - written, 4096 - page_offset);
491
492 let phys = as_ref
495 .translate(VirtAddr::new(curr_vaddr))
496 .ok_or(SyscallError::Fault)?;
497 let virt = crate::memory::phys_to_virt(phys.as_u64()) as *mut u8;
498
499 unsafe {
500 core::ptr::copy_nonoverlapping(data.as_ptr().add(written), virt, chunk_size);
501 }
502 written += chunk_size;
503 }
504 Ok(())
505}
506
507fn write_u64_to_as(as_ref: &AddressSpace, vaddr: u64, val: u64) -> Result<(), SyscallError> {
509 let bytes = val.to_ne_bytes();
510 write_bytes_to_as(as_ref, vaddr, &bytes)
511}
512
513fn generate_aux_random_seed() -> [u8; 16] {
515 let mut seed = [0u8; 16];
516 crate::entropy::fill_random(&mut seed);
517 seed
518}