Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
unsafe {
1#![allow(dead_code)]2#![allow(unused_variables)]3#![stable(feature = "rust1", since = "1.0.0")]45#[path = "../unix/ffi/os_str.rs"]6mod os_str;78#[stable(feature = "rust1", since = "1.0.0")]9pub use self::os_str::{OsStrExt, OsStringExt};1011mod definitions;12#[stable(feature = "rust1", since = "1.0.0")]13pub use definitions::*;1415fn lend_mut_impl(16 connection: Connection,17 opcode: usize,18 data: &mut [u8],19 arg1: usize,20 arg2: usize,21 blocking: bool,22) -> Result<(usize, usize), Error> {23 let mut a0 = if blocking { Syscall::SendMessage } else { Syscall::TrySendMessage } as usize;24 let mut a1: usize = connection.try_into().unwrap();25 let mut a2 = InvokeType::LendMut as usize;26 let a3 = opcode;27 let a4 = data.as_mut_ptr();28 let a5 = data.len();29 let a6 = arg1;30 let a7 = arg2;3132 unsafe {33 core::arch::asm!(34 "ecall",35 inlateout("a0") a0,36 inlateout("a1") a1,37 inlateout("a2") a2,38 inlateout("a3") a3 => _,39 inlateout("a4") a4 => _,40 inlateout("a5") a5 => _,41 inlateout("a6") a6 => _,42 inlateout("a7") a7 => _,43 )44 };4546 let result = a0;4748 if result == SyscallResult::MemoryReturned as usize {49 Ok((a1, a2))50 } else if result == SyscallResult::Error as usize {51 Err(a1.into())52 } else {53 Err(Error::InternalError)54 }55}5657pub(crate) fn lend_mut(58 connection: Connection,59 opcode: usize,60 data: &mut [u8],61 arg1: usize,62 arg2: usize,63) -> Result<(usize, usize), Error> {64 lend_mut_impl(connection, opcode, data, arg1, arg2, true)65}6667pub(crate) fn try_lend_mut(68 connection: Connection,69 opcode: usize,70 data: &mut [u8],71 arg1: usize,72 arg2: usize,73) -> Result<(usize, usize), Error> {74 lend_mut_impl(connection, opcode, data, arg1, arg2, false)75}7677fn lend_impl(78 connection: Connection,79 opcode: usize,80 data: &[u8],81 arg1: usize,82 arg2: usize,83 blocking: bool,84) -> Result<(usize, usize), Error> {85 let mut a0 = if blocking { Syscall::SendMessage } else { Syscall::TrySendMessage } as usize;86 let a1: usize = connection.try_into().unwrap();87 let a2 = InvokeType::Lend as usize;88 let a3 = opcode;89 let a4 = data.as_ptr();90 let a5 = data.len();91 let a6 = arg1;92 let a7 = arg2;93 let mut ret1;94 let mut ret2;9596 unsafe {97 core::arch::asm!(98 "ecall",99 inlateout("a0") a0,100 inlateout("a1") a1 => ret1,101 inlateout("a2") a2 => ret2,102 inlateout("a3") a3 => _,103 inlateout("a4") a4 => _,104 inlateout("a5") a5 => _,105 inlateout("a6") a6 => _,106 inlateout("a7") a7 => _,107 )108 };109110 let result = a0;111112 if result == SyscallResult::MemoryReturned as usize {113 Ok((ret1, ret2))114 } else if result == SyscallResult::Error as usize {115 Err(ret1.into())116 } else {117 Err(Error::InternalError)118 }119}120121pub(crate) fn lend(122 connection: Connection,123 opcode: usize,124 data: &[u8],125 arg1: usize,126 arg2: usize,127) -> Result<(usize, usize), Error> {128 lend_impl(connection, opcode, data, arg1, arg2, true)129}130131pub(crate) fn try_lend(132 connection: Connection,133 opcode: usize,134 data: &[u8],135 arg1: usize,136 arg2: usize,137) -> Result<(usize, usize), Error> {138 lend_impl(connection, opcode, data, arg1, arg2, false)139}140141fn scalar_impl(connection: Connection, args: [usize; 5], blocking: bool) -> Result<(), Error> {142 let mut a0 = if blocking { Syscall::SendMessage } else { Syscall::TrySendMessage } as usize;143 let mut a1: usize = connection.try_into().unwrap();144 let a2 = InvokeType::Scalar as usize;145 let a3 = args[0];146 let a4 = args[1];147 let a5 = args[2];148 let a6 = args[3];149 let a7 = args[4];150151 unsafe {152 core::arch::asm!(153 "ecall",154 inlateout("a0") a0,155 inlateout("a1") a1,156 inlateout("a2") a2 => _,157 inlateout("a3") a3 => _,158 inlateout("a4") a4 => _,159 inlateout("a5") a5 => _,160 inlateout("a6") a6 => _,161 inlateout("a7") a7 => _,162 )163 };164165 let result = a0;166167 if result == SyscallResult::Ok as usize {168 Ok(())169 } else if result == SyscallResult::Error as usize {170 Err(a1.into())171 } else {172 Err(Error::InternalError)173 }174}175176pub(crate) fn scalar(connection: Connection, args: [usize; 5]) -> Result<(), Error> {177 scalar_impl(connection, args, true)178}179180pub(crate) fn try_scalar(connection: Connection, args: [usize; 5]) -> Result<(), Error> {181 scalar_impl(connection, args, false)182}183184fn blocking_scalar_impl(185 connection: Connection,186 args: [usize; 5],187 blocking: bool,188) -> Result<[usize; 5], Error> {189 let mut a0 = if blocking { Syscall::SendMessage } else { Syscall::TrySendMessage } as usize;190 let mut a1: usize = connection.try_into().unwrap();191 let mut a2 = InvokeType::BlockingScalar as usize;192 let mut a3 = args[0];193 let mut a4 = args[1];194 let mut a5 = args[2];195 let a6 = args[3];196 let a7 = args[4];197198 unsafe {199 core::arch::asm!(200 "ecall",201 inlateout("a0") a0,202 inlateout("a1") a1,203 inlateout("a2") a2,204 inlateout("a3") a3,205 inlateout("a4") a4,206 inlateout("a5") a5,207 inlateout("a6") a6 => _,208 inlateout("a7") a7 => _,209 )210 };211212 let result = a0;213214 if result == SyscallResult::Scalar1 as usize {215 Ok([a1, 0, 0, 0, 0])216 } else if result == SyscallResult::Scalar2 as usize {217 Ok([a1, a2, 0, 0, 0])218 } else if result == SyscallResult::Scalar5 as usize {219 Ok([a1, a2, a3, a4, a5])220 } else if result == SyscallResult::Error as usize {221 Err(a1.into())222 } else {223 Err(Error::InternalError)224 }225}226227pub(crate) fn blocking_scalar(228 connection: Connection,229 args: [usize; 5],230) -> Result<[usize; 5], Error> {231 blocking_scalar_impl(connection, args, true)232}233234pub(crate) fn try_blocking_scalar(235 connection: Connection,236 args: [usize; 5],237) -> Result<[usize; 5], Error> {238 blocking_scalar_impl(connection, args, false)239}240241fn connect_impl(address: ServerAddress, blocking: bool) -> Result<Connection, Error> {242 let a0 = if blocking { Syscall::Connect } else { Syscall::TryConnect } as usize;243 let address: [u32; 4] = address.into();244 let a1: usize = address[0].try_into().unwrap();245 let a2: usize = address[1].try_into().unwrap();246 let a3: usize = address[2].try_into().unwrap();247 let a4: usize = address[3].try_into().unwrap();248 let a5 = 0;249 let a6 = 0;250 let a7 = 0;251252 let mut result: usize;253 let mut value: usize;254255 unsafe {256 core::arch::asm!(257 "ecall",258 inlateout("a0") a0 => result,259 inlateout("a1") a1 => value,260 inlateout("a2") a2 => _,261 inlateout("a3") a3 => _,262 inlateout("a4") a4 => _,263 inlateout("a5") a5 => _,264 inlateout("a6") a6 => _,265 inlateout("a7") a7 => _,266 )267 };268 if result == SyscallResult::ConnectionId as usize {269 Ok(value.try_into().unwrap())270 } else if result == SyscallResult::Error as usize {271 Err(value.into())272 } else {273 Err(Error::InternalError)274 }275}276277/// Connects to a Xous server represented by the specified `address`.278///279/// The current thread will block until the server is available. Returns280/// an error if the server cannot accept any more connections.281pub(crate) fn connect(address: ServerAddress) -> Result<Connection, Error> {282 connect_impl(address, true)283}284285/// Attempts to connect to a Xous server represented by the specified `address`.286///287/// If the server does not exist then None is returned.288pub(crate) fn try_connect(address: ServerAddress) -> Result<Option<Connection>, Error> {289 match connect_impl(address, false) {290 Ok(conn) => Ok(Some(conn)),291 Err(Error::ServerNotFound) => Ok(None),292 Err(e) => Err(e),293 }294}295296/// Terminates the current process and returns the specified code to the parent process.297pub(crate) fn exit(return_code: u32) -> ! {298 let a0 = Syscall::TerminateProcess as usize;299 let a1 = return_code as usize;300 let a2 = 0;301 let a3 = 0;302 let a4 = 0;303 let a5 = 0;304 let a6 = 0;305 let a7 = 0;306307 unsafe {308 core::arch::asm!(309 "ecall",310 in("a0") a0,311 in("a1") a1,312 in("a2") a2,313 in("a3") a3,314 in("a4") a4,315 in("a5") a5,316 in("a6") a6,317 in("a7") a7,318 )319 };320 unreachable!();321}322323/// Suspends the current thread and allow another thread to run. This thread may324/// continue executing again immediately if there are no other threads available325/// to run on the system.326pub(crate) fn do_yield() {327 let a0 = Syscall::Yield as usize;328 let a1 = 0;329 let a2 = 0;330 let a3 = 0;331 let a4 = 0;332 let a5 = 0;333 let a6 = 0;334 let a7 = 0;335336 unsafe {337 core::arch::asm!(338 "ecall",339 inlateout("a0") a0 => _,340 inlateout("a1") a1 => _,341 inlateout("a2") a2 => _,342 inlateout("a3") a3 => _,343 inlateout("a4") a4 => _,344 inlateout("a5") a5 => _,345 inlateout("a6") a6 => _,346 inlateout("a7") a7 => _,347 )348 };349}350351/// Allocates memory from the system.352///353/// An optional physical and/or virtual address may be specified in order to354/// ensure memory is allocated at specific offsets, otherwise the kernel will355/// select an address.356///357/// # Safety358///359/// This function is safe unless a virtual address is specified. In that case,360/// the kernel will return an alias to the existing range. This violates Rust's361/// pointer uniqueness guarantee.362// The phys argument uses an integer rather than pointer type as pointer363// provenance only covers virtual memory, not physical memory.364pub(crate) unsafe fn map_memory<T>(365 phys: Option<core::num::NonZeroUsize>,366 virt: Option<core::ptr::NonNull<T>>,367 count: usize,368 flags: MemoryFlags,369) -> Result<&'static mut [T], Error> {370 let mut a0 = Syscall::MapMemory as usize;371 let a1 = phys.map_or(0, |p| p.get());372 let a1_out: *mut T;373 let a2 = virt.map_or(core::ptr::null(), |p| p.as_ptr());374 let a2_out: usize;375 let a3 = count * size_of::<T>();376 let a4 = flags.bits();377 let a5 = 0;378 let a6 = 0;379 let a7 = 0;380381 unsafe {382 core::arch::asm!(383 "ecall",384 inlateout("a0") a0,385 inlateout("a1") a1 => a1_out,386 inlateout("a2") a2 => a2_out,387 inlateout("a3") a3 => _,388 inlateout("a4") a4 => _,389 inlateout("a5") a5 => _,390 inlateout("a6") a6 => _,391 inlateout("a7") a7 => _,392 )393 };394395 let result = a0;396397 if result == SyscallResult::MemoryRange as usize {398 let start = a1_out;399 let len = a2_out / size_of::<T>();400 let end = unsafe { start.add(len) };401 Ok(unsafe { core::slice::from_raw_parts_mut(start, len) })402 } else if result == SyscallResult::Error as usize {403 Err(a1_out.addr().into())404 } else {405 Err(Error::InternalError)406 }407}408409/// Destroys the given memory, returning it to the compiler.410///411/// Safety: The memory pointed to by `range` should not be used after this412/// function returns, even if this function returns Err().413pub(crate) unsafe fn unmap_memory<T>(range: *mut [T]) -> Result<(), Error> {414 let mut a0 = Syscall::UnmapMemory as usize;415 let mut a1 = range.as_mut_ptr();416 let a2 = range.len() * size_of::<T>();417 let a3 = 0;418 let a4 = 0;419 let a5 = 0;420 let a6 = 0;421 let a7 = 0;422423 unsafe {424 core::arch::asm!(425 "ecall",426 inlateout("a0") a0,427 inlateout("a1") a1,428 inlateout("a2") a2 => _,429 inlateout("a3") a3 => _,430 inlateout("a4") a4 => _,431 inlateout("a5") a5 => _,432 inlateout("a6") a6 => _,433 inlateout("a7") a7 => _,434 )435 };436437 let result = a0;438439 if result == SyscallResult::Ok as usize {440 Ok(())441 } else if result == SyscallResult::Error as usize {442 Err(a1.addr().into())443 } else {444 Err(Error::InternalError)445 }446}447448/// Adjusts the memory flags for the given range.449///450/// This can be used to remove flags from a given region in order to harden451/// memory access. Note that flags may only be removed and may never be added.452///453/// Safety: The memory pointed to by `range` may become inaccessible or have its454/// mutability removed. It is up to the caller to ensure that the flags specified455/// by `new_flags` are upheld, otherwise the program will crash.456pub(crate) unsafe fn update_memory_flags<T>(457 range: *mut [T],458 new_flags: MemoryFlags,459) -> Result<(), Error> {460 let mut a0 = Syscall::UpdateMemoryFlags as usize;461 let a1 = range.as_mut_ptr();462 let a1_out: usize;463 let a2 = range.len() * size_of::<T>();464 let a3 = new_flags.bits();465 let a4 = 0; // Process ID is currently None466 let a5 = 0;467 let a6 = 0;468 let a7 = 0;469470 unsafe {471 core::arch::asm!(472 "ecall",473 inlateout("a0") a0,474 inlateout("a1") a1 => a1_out,475 inlateout("a2") a2 => _,476 inlateout("a3") a3 => _,477 inlateout("a4") a4 => _,478 inlateout("a5") a5 => _,479 inlateout("a6") a6 => _,480 inlateout("a7") a7 => _,481 )482 };483484 let result = a0;485486 if result == SyscallResult::Ok as usize {487 Ok(())488 } else if result == SyscallResult::Error as usize {489 Err(a1_out.into())490 } else {491 Err(Error::InternalError)492 }493}494495/// Creates a thread with a given stack and up to four arguments.496pub(crate) unsafe fn create_thread<T>(497 start: unsafe extern "C" fn(*mut usize, usize, usize) -> !,498 stack: *mut [u8],499 arg0: *mut T,500 arg1: *const u8,501 arg2: usize,502 arg3: usize,503) -> Result<ThreadId, Error> {504 let mut a0 = Syscall::CreateThread as usize;505 let a1 = start;506 let a1_out: usize;507 let a2 = stack.as_mut_ptr();508 let a3 = stack.len();509 let a4 = arg0;510 let a5 = arg1;511 let a6 = arg2;512 let a7 = arg3;513514 unsafe {515 core::arch::asm!(516 "ecall",517 inlateout("a0") a0,518 inlateout("a1") a1 => a1_out,519 inlateout("a2") a2 => _,520 inlateout("a3") a3 => _,521 inlateout("a4") a4 => _,522 inlateout("a5") a5 => _,523 inlateout("a6") a6 => _,524 inlateout("a7") a7 => _,525 )526 };527528 let result = a0;529530 if result == SyscallResult::ThreadId as usize {531 Ok(a1_out.into())532 } else if result == SyscallResult::Error as usize {533 Err(a1_out.into())534 } else {535 Err(Error::InternalError)536 }537}538539/// Waits for the given thread to terminate and returns the exit code from that thread.540pub(crate) fn join_thread(thread_id: ThreadId) -> Result<usize, Error> {541 let mut a0 = Syscall::JoinThread as usize;542 let mut a1 = thread_id.into();543 let a2 = 0;544 let a3 = 0;545 let a4 = 0;546 let a5 = 0;547 let a6 = 0;548 let a7 = 0;549550 unsafe {551 core::arch::asm!(552 "ecall",553 inlateout("a0") a0,554 inlateout("a1") a1,555 inlateout("a2") a2 => _,556 inlateout("a3") a3 => _,557 inlateout("a4") a4 => _,558 inlateout("a5") a5 => _,559 inlateout("a6") a6 => _,560 inlateout("a7") a7 => _,561 )562 };563564 let result = a0;565566 if result == SyscallResult::Scalar1 as usize {567 Ok(a1)568 } else if result == SyscallResult::Scalar2 as usize {569 Ok(a1)570 } else if result == SyscallResult::Scalar5 as usize {571 Ok(a1)572 } else if result == SyscallResult::Error as usize {573 Err(a1.into())574 } else {575 Err(Error::InternalError)576 }577}578579/// Gets the current thread's ID.580pub(crate) fn thread_id() -> Result<ThreadId, Error> {581 let mut a0 = Syscall::GetThreadId as usize;582 let mut a1 = 0;583 let a2 = 0;584 let a3 = 0;585 let a4 = 0;586 let a5 = 0;587 let a6 = 0;588 let a7 = 0;589590 unsafe {591 core::arch::asm!(592 "ecall",593 inlateout("a0") a0,594 inlateout("a1") a1,595 inlateout("a2") a2 => _,596 inlateout("a3") a3 => _,597 inlateout("a4") a4 => _,598 inlateout("a5") a5 => _,599 inlateout("a6") a6 => _,600 inlateout("a7") a7 => _,601 )602 };603604 let result = a0;605606 if result == SyscallResult::ThreadId as usize {607 Ok(a1.into())608 } else if result == SyscallResult::Error as usize {609 Err(a1.into())610 } else {611 Err(Error::InternalError)612 }613}614615/// Adjusts the given `knob` limit to match the new value `new`. The current value must616/// match the `current` in order for this to take effect.617///618/// The new value is returned as a result of this call. If the call fails, then the old619/// value is returned. In either case, this function returns successfully.620///621/// An error is generated if the `knob` is not a valid limit, or if the call622/// would not succeed.623pub(crate) fn adjust_limit(knob: Limits, current: usize, new: usize) -> Result<usize, Error> {624 let mut a0 = Syscall::AdjustProcessLimit as usize;625 let mut a1 = knob as usize;626 let a2 = current;627 let a3 = new;628 let a4 = 0;629 let a5 = 0;630 let a6 = 0;631 let a7 = 0;632633 unsafe {634 core::arch::asm!(635 "ecall",636 inlateout("a0") a0,637 inlateout("a1") a1,638 inlateout("a2") a2 => _,639 inlateout("a3") a3 => _,640 inlateout("a4") a4 => _,641 inlateout("a5") a5 => _,642 inlateout("a6") a6 => _,643 inlateout("a7") a7 => _,644 )645 };646647 let result = a0;648649 if result == SyscallResult::Scalar2 as usize && a1 == knob as usize {650 Ok(a2)651 } else if result == SyscallResult::Scalar5 as usize && a1 == knob as usize {652 Ok(a1)653 } else if result == SyscallResult::Error as usize {654 Err(a1.into())655 } else {656 Err(Error::InternalError)657 }658}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.