1use crate::mm::PAGE_SIZE;
6use crate::vfs::{FsStr, FsString};
7use smallvec::SmallVec;
8use starnix_types::user_buffer::{UserBuffer, UserBuffers, UserBuffers32};
9use starnix_uapi::errors::Errno;
10use starnix_uapi::user_address::{
11 ArchSpecific, MappingMultiArchUserRef, MultiArchUserRef, UserAddress, UserAddress32,
12 UserCString, UserRef,
13};
14use starnix_uapi::user_value::UserValue;
15use starnix_uapi::{PATH_MAX, UIO_MAXIOV, errno, error, uapi};
16use std::ffi::CStr;
17use std::mem::MaybeUninit;
18use usercopy::slice_to_maybe_uninit_mut;
19use zerocopy::{FromBytes, Immutable, IntoBytes};
20
21pub type IOVecPtr = MultiArchUserRef<uapi::iovec, uapi::arch32::iovec>;
22
23pub trait MemoryAccessor {
24 fn read_memory<'a>(
31 &self,
32 addr: UserAddress,
33 bytes: &'a mut [MaybeUninit<u8>],
34 ) -> Result<&'a mut [u8], Errno>;
35
36 fn read_memory_partial_until_null_byte<'a>(
44 &self,
45 addr: UserAddress,
46 bytes: &'a mut [MaybeUninit<u8>],
47 ) -> Result<&'a mut [u8], Errno>;
48
49 fn read_memory_partial<'a>(
58 &self,
59 addr: UserAddress,
60 bytes: &'a mut [MaybeUninit<u8>],
61 ) -> Result<&'a mut [u8], Errno>;
62
63 fn write_memory(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno>;
71
72 fn write_memory_partial(&self, addr: UserAddress, bytes: &[u8]) -> Result<usize, Errno>;
79
80 fn zero(&self, addr: UserAddress, length: usize) -> Result<usize, Errno>;
84}
85
86#[derive(Clone, Copy, Debug, PartialEq, Eq)]
88pub enum MappingAccess {
89 ForReading,
90 ForWriting,
91}
92
93pub trait TaskMemoryAccessor: MemoryAccessor {
94 fn maximum_valid_address(&self) -> Option<UserAddress>;
96
97 fn ensure_buffers_mapped_in_user_vmar(
100 &self,
101 buffers: &[UserBuffer],
102 access: MappingAccess,
103 ) -> Result<(), Errno>;
104}
105
106#[inline]
108fn object_as_mut_bytes<T: FromBytes + Sized>(
109 object: &mut MaybeUninit<T>,
110) -> &mut [MaybeUninit<u8>] {
111 unsafe {
115 std::slice::from_raw_parts_mut(
116 object.as_mut_ptr() as *mut MaybeUninit<u8>,
117 std::mem::size_of::<T>(),
118 )
119 }
120}
121
122#[inline]
124fn slice_as_mut_bytes<T: FromBytes + Sized>(
125 slice: &mut [MaybeUninit<T>],
126) -> &mut [MaybeUninit<u8>] {
127 unsafe {
130 std::slice::from_raw_parts_mut(
131 slice.as_mut_ptr() as *mut MaybeUninit<u8>,
132 slice.len() * std::mem::size_of::<T>(),
133 )
134 }
135}
136
137pub struct NumberOfElementsRead(pub usize);
142
143#[inline]
152pub unsafe fn read_to_vec<T: FromBytes, E>(
153 max_len: usize,
154 read_fn: impl FnOnce(&mut [MaybeUninit<T>]) -> Result<NumberOfElementsRead, E>,
155) -> Result<Vec<T>, E> {
156 let mut buffer = Vec::with_capacity(max_len);
157 let NumberOfElementsRead(read_elements) = read_fn(&mut buffer.spare_capacity_mut()[..max_len])?;
160 debug_assert!(read_elements <= max_len, "read_elements={read_elements}, max_len={max_len}");
161 unsafe { buffer.set_len(read_elements) }
164 Ok(buffer)
165}
166
167#[inline]
176pub unsafe fn read_to_array<T: FromBytes, E, const N: usize>(
177 read_fn: impl FnOnce(&mut [MaybeUninit<T>]) -> Result<(), E>,
178) -> Result<[T; N], E> {
179 let buffer: MaybeUninit<[MaybeUninit<T>; N]> = MaybeUninit::uninit();
181 let mut buffer = unsafe { buffer.assume_init() };
185 read_fn(&mut buffer)?;
186 let buffer = buffer.map(|a| unsafe { a.assume_init() });
191 Ok(buffer)
192}
193
194#[inline]
202pub unsafe fn read_to_object_as_bytes<T: FromBytes, E>(
203 read_fn: impl FnOnce(&mut [MaybeUninit<u8>]) -> Result<(), E>,
204) -> Result<T, E> {
205 #[repr(C, align(8))]
213 struct Aligned<T>(MaybeUninit<T>);
214 let mut object = Aligned(MaybeUninit::uninit());
215 read_fn(object_as_mut_bytes(&mut object.0))?;
216 let object = unsafe { object.0.assume_init() };
219 Ok(object)
220}
221
222pub trait MemoryAccessorExt: MemoryAccessor {
223 fn read_memory_to_slice(&self, addr: UserAddress, bytes: &mut [u8]) -> Result<(), Errno> {
230 let bytes_len = bytes.len();
231 self.read_memory(addr, slice_to_maybe_uninit_mut(bytes))
232 .map(|bytes_read| debug_assert_eq!(bytes_read.len(), bytes_len))
233 }
234
235 fn read_memory_to_vec(&self, addr: UserAddress, len: usize) -> Result<Vec<u8>, Errno> {
237 unsafe {
239 read_to_vec::<u8, _>(len, |buf| {
240 self.read_memory(addr, buf).map(|bytes_read| {
241 debug_assert_eq!(bytes_read.len(), len);
242 NumberOfElementsRead(len)
243 })
244 })
245 }
246 }
247
248 fn read_memory_partial_to_vec(
250 &self,
251 addr: UserAddress,
252 max_len: usize,
253 ) -> Result<Vec<u8>, Errno> {
254 unsafe {
256 read_to_vec::<u8, _>(max_len, |buf| {
257 self.read_memory_partial(addr, buf)
258 .map(|bytes_read| NumberOfElementsRead(bytes_read.len()))
259 })
260 }
261 }
262
263 fn read_memory_to_array<const N: usize>(&self, addr: UserAddress) -> Result<[u8; N], Errno> {
265 unsafe {
267 read_to_array(|buf| {
268 self.read_memory(addr, buf).map(|bytes_read| debug_assert_eq!(bytes_read.len(), N))
269 })
270 }
271 }
272
273 fn read_buffer(&self, buffer: &UserBuffer) -> Result<Vec<u8>, Errno> {
275 self.read_memory_to_vec(buffer.address, buffer.length)
276 }
277
278 fn read_object<T: FromBytes>(&self, user: UserRef<T>) -> Result<T, Errno> {
280 unsafe {
282 read_to_object_as_bytes(|buf| {
283 self.read_memory(user.addr(), buf)
284 .map(|bytes_read| debug_assert_eq!(bytes_read.len(), std::mem::size_of::<T>()))
285 })
286 }
287 }
288
289 fn read_multi_arch_ptr<T64, T32>(
290 &self,
291 user: MultiArchUserRef<MultiArchUserRef<T64, T32>, MultiArchUserRef<T64, T32>>,
292 ) -> Result<MultiArchUserRef<T64, T32>, Errno> {
293 let address = if user.is_arch32() {
294 self.read_object::<UserAddress32>(user.addr().into())?.into()
295 } else {
296 self.read_object::<UserAddress>(user.addr().into())?
297 };
298 Ok(MultiArchUserRef::<T64, T32>::new(&user, address))
299 }
300
301 fn read_multi_arch_object<T, T64: FromBytes + TryInto<T>, T32: FromBytes + TryInto<T>>(
304 &self,
305 user: MappingMultiArchUserRef<T, T64, T32>,
306 ) -> Result<T, Errno> {
307 match user {
308 MappingMultiArchUserRef::<T, T64, T32>::Arch64(user, _) => {
309 self.read_object(user)?.try_into().map_err(|_| errno!(EINVAL))
310 }
311 MappingMultiArchUserRef::<T, T64, T32>::Arch32(user) => {
312 self.read_object(user)?.try_into().map_err(|_| errno!(EINVAL))
313 }
314 }
315 }
316
317 fn read_multi_arch_objects_to_vec<
319 T,
320 T64: FromBytes + TryInto<T>,
321 T32: FromBytes + TryInto<T>,
322 >(
323 &self,
324 user: MappingMultiArchUserRef<T, T64, T32>,
325 len: usize,
326 ) -> Result<Vec<T>, Errno> {
327 match user {
328 MappingMultiArchUserRef::<T, T64, T32>::Arch64(user, _) => self
329 .read_objects_to_vec(user, len)?
330 .into_iter()
331 .map(TryInto::<T>::try_into)
332 .collect::<Result<Vec<T>, _>>()
333 .map_err(|_| errno!(EINVAL)),
334 MappingMultiArchUserRef::<T, T64, T32>::Arch32(user) => self
335 .read_objects_to_vec(user, len)?
336 .into_iter()
337 .map(TryInto::<T>::try_into)
338 .collect::<Result<Vec<T>, _>>()
339 .map_err(|_| errno!(EINVAL)),
340 }
341 }
342
343 fn read_object_partial<T: FromBytes>(
351 &self,
352 user: UserRef<T>,
353 partial_size: usize,
354 ) -> Result<T, Errno> {
355 let full_size = std::mem::size_of::<T>();
356 if partial_size > full_size {
357 return error!(EINVAL);
358 }
359
360 let mut object = MaybeUninit::uninit();
363 let (to_read, to_zero) = object_as_mut_bytes(&mut object).split_at_mut(partial_size);
364 self.read_memory(user.addr(), to_read)?;
365
366 to_zero.fill(MaybeUninit::new(0));
368
369 Ok(unsafe { object.assume_init() })
372 }
373
374 fn read_objects<'a, T: FromBytes>(
376 &self,
377 user: UserRef<T>,
378 objects: &'a mut [MaybeUninit<T>],
379 ) -> Result<&'a mut [T], Errno> {
380 let objects_len = objects.len();
381 self.read_memory(user.addr(), slice_as_mut_bytes(objects)).map(|bytes_read| {
382 debug_assert_eq!(bytes_read.len(), objects_len * std::mem::size_of::<T>());
383 unsafe {
385 std::slice::from_raw_parts_mut(bytes_read.as_mut_ptr() as *mut T, objects_len)
386 }
387 })
388 }
389
390 fn read_objects_to_slice<T: FromBytes>(
392 &self,
393 user: UserRef<T>,
394 objects: &mut [T],
395 ) -> Result<(), Errno> {
396 let objects_len = objects.len();
397 self.read_objects(user, slice_to_maybe_uninit_mut(objects))
398 .map(|objects_read| debug_assert_eq!(objects_read.len(), objects_len))
399 }
400
401 fn read_objects_to_vec<T: FromBytes>(
403 &self,
404 user: UserRef<T>,
405 len: usize,
406 ) -> Result<Vec<T>, Errno> {
407 unsafe {
409 read_to_vec::<T, _>(len, |buf| {
410 self.read_objects(user, buf).map(|objects_read| {
411 debug_assert_eq!(objects_read.len(), len);
412 NumberOfElementsRead(len)
413 })
414 })
415 }
416 }
417
418 fn read_objects_to_smallvec<T: Clone + FromBytes, const N: usize>(
420 &self,
421 user: UserRef<T>,
422 len: usize,
423 ) -> Result<SmallVec<[T; N]>, Errno> {
424 if len > N {
425 Ok(SmallVec::<[T; N]>::from_vec(self.read_objects_to_vec(user, len)?))
426 } else {
427 let mut buffer: [MaybeUninit<T>; N] = [const { MaybeUninit::uninit() }; N];
428
429 self.read_objects(user, &mut buffer[..len])?;
430
431 let buffer: MaybeUninit<[T; N]> = unsafe { std::mem::transmute_copy(&buffer) };
434
435 Ok(unsafe { SmallVec::from_buf_and_len_unchecked(buffer, len) })
437 }
438 }
439
440 fn read_objects_to_array<T: Copy + FromBytes, const N: usize>(
442 &self,
443 user: UserRef<T>,
444 ) -> Result<[T; N], Errno> {
445 unsafe {
447 read_to_array(|buf| {
448 self.read_objects(user, buf).map(|objects_read| {
449 debug_assert_eq!(objects_read.len(), N);
450 })
451 })
452 }
453 }
454
455 fn read_iovec<T: Copy + Eq + IntoBytes + FromBytes + Immutable + TryInto<usize>>(
459 &self,
460 iovec_addr: IOVecPtr,
461 iovec_count: UserValue<T>,
462 ) -> Result<UserBuffers, Errno> {
463 let iovec_count = iovec_count.raw().try_into().map_err(|_| errno!(EINVAL))?;
464 if iovec_count > UIO_MAXIOV as usize {
465 return error!(EINVAL);
466 }
467
468 if iovec_addr.is_arch32() {
469 let ub32s: UserBuffers32 =
470 self.read_objects_to_smallvec(iovec_addr.addr().into(), iovec_count)?;
471 Ok(ub32s.iter().map(|&ub32| ub32.into()).collect())
472 } else {
473 self.read_objects_to_smallvec(iovec_addr.addr().into(), iovec_count)
474 }
475 }
476
477 fn read_c_string_to_vec(
480 &self,
481 string: UserCString,
482 max_size: usize,
483 ) -> Result<FsString, Errno> {
484 let chunk_size = std::cmp::min(*PAGE_SIZE as usize, max_size);
485
486 let mut buf = Vec::with_capacity(chunk_size);
487 let mut index = 0;
488 loop {
489 let addr = string.addr().checked_add(index).ok_or_else(|| errno!(EFAULT))?;
491 let read = self.read_memory_partial_until_null_byte(
492 addr,
493 &mut buf.spare_capacity_mut()[index..][..chunk_size],
494 )?;
495 let read_len = read.len();
496
497 if read.last() == Some(&0) {
499 let null_index = index + read_len - 1;
500 unsafe { buf.set_len(null_index) }
502 if buf.len() > max_size {
503 return error!(ENAMETOOLONG);
504 }
505
506 return Ok(buf.into());
507 }
508 index += read_len;
509
510 if read_len < chunk_size || index >= max_size {
511 return error!(ENAMETOOLONG);
513 }
514
515 buf.reserve(index + chunk_size);
517 }
518 }
519
520 fn read_path(&self, path: UserCString) -> Result<FsString, Errno> {
524 self.read_c_string_to_vec(path, PATH_MAX as usize)
525 }
526
527 fn read_path_if_non_null(&self, path: UserCString) -> Result<FsString, Errno> {
531 if path.is_null() {
532 Ok(Default::default())
533 } else {
534 self.read_c_string_to_vec(path, PATH_MAX as usize)
535 }
536 }
537
538 fn read_nul_delimited_c_string_list(
543 &self,
544 start: UserAddress,
545 len: usize,
546 ) -> Result<Vec<FsString>, Errno> {
547 let buf = self.read_memory_to_vec(start, len)?;
548 let mut buf = &buf[..];
549
550 let mut list = vec![];
551 while !buf.is_empty() {
552 let len_consumed = match CStr::from_bytes_until_nul(buf) {
553 Ok(segment) => {
554 list.push(segment.to_bytes().into());
557 segment.to_bytes_with_nul().len()
558 }
559 Err(_) => {
560 list.push(buf.into());
563 buf.len()
564 }
565 };
566 buf = &buf[len_consumed..];
567 }
568
569 Ok(list)
570 }
571
572 fn read_c_string<'a>(
577 &self,
578 string: UserCString,
579 buffer: &'a mut [MaybeUninit<u8>],
580 ) -> Result<&'a FsStr, Errno> {
581 let buffer = self.read_memory_partial_until_null_byte(string.addr(), buffer)?;
582 if let Some((null_byte, buffer)) = buffer.split_last() {
584 if null_byte == &0 {
585 return Ok(buffer.into());
586 }
587 }
588
589 error!(ENAMETOOLONG)
590 }
591
592 fn read_c_string_if_non_null<'a>(
595 &self,
596 addr: UserCString,
597 buffer: &'a mut [MaybeUninit<u8>],
598 ) -> Result<&'a FsStr, Errno> {
599 if addr.is_null() { Ok(Default::default()) } else { self.read_c_string(addr, buffer) }
600 }
601
602 fn write_object<T: IntoBytes + Immutable>(
603 &self,
604 user: UserRef<T>,
605 object: &T,
606 ) -> Result<usize, Errno> {
607 self.write_memory(user.addr(), object.as_bytes())
608 }
609
610 fn write_objects<T: IntoBytes + Immutable>(
611 &self,
612 user: UserRef<T>,
613 objects: &[T],
614 ) -> Result<usize, Errno> {
615 self.write_memory(user.addr(), objects.as_bytes())
616 }
617
618 fn write_multi_arch_ptr<Addr, T64, T32>(
619 &self,
620 user: Addr,
621 object: MultiArchUserRef<T64, T32>,
622 ) -> Result<usize, Errno>
623 where
624 Addr: Into<UserAddress>,
625 {
626 if object.is_arch32() {
627 let value = u32::try_from(object.ptr()).map_err(|_| errno!(EINVAL))?;
628 self.write_memory(user.into(), value.as_bytes())
629 } else {
630 self.write_memory(user.into(), object.ptr().as_bytes())
631 }
632 }
633
634 fn write_multi_arch_object<
635 T,
636 T64: IntoBytes + Immutable + TryFrom<T>,
637 T32: IntoBytes + Immutable + TryFrom<T>,
638 >(
639 &self,
640 user: MappingMultiArchUserRef<T, T64, T32>,
641 object: T,
642 ) -> Result<usize, Errno> {
643 match user {
644 MappingMultiArchUserRef::<T, T64, T32>::Arch64(user, _) => {
645 self.write_object(user, &T64::try_from(object).map_err(|_| errno!(EINVAL))?)
646 }
647 MappingMultiArchUserRef::<T, T64, T32>::Arch32(user) => {
648 self.write_object(user, &T32::try_from(object).map_err(|_| errno!(EINVAL))?)
649 }
650 }
651 }
652}
653
654impl MemoryAccessorExt for dyn MemoryAccessor + '_ {}
655impl<T: MemoryAccessor> MemoryAccessorExt for T {}