mirror of
https://github.com/rcore-os/rCore.git
synced 2025-01-31 10:04:04 +04:00
Implement copy_to_user, use UserPtr in more places
This commit is contained in:
parent
3d9a1a7356
commit
990bb6a4a1
@ -213,3 +213,20 @@ pub fn copy_from_user<T>(addr: *const T) -> Option<T> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_to_user<T>(addr: *mut T, src: *const T) -> bool {
|
||||
#[naked]
|
||||
#[inline(never)]
|
||||
#[link_section = ".text.copy_user"]
|
||||
unsafe extern "C" fn write_user<T>(dst: *mut T, src: *const T) -> usize {
|
||||
dst.copy_from_nonoverlapping(src, 1);
|
||||
0
|
||||
}
|
||||
if !access_ok(addr as usize, size_of::<T>()) {
|
||||
return false;
|
||||
}
|
||||
match unsafe { write_user(addr, src) } {
|
||||
0 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ pub mod proc;
|
||||
pub mod structs;
|
||||
pub mod thread;
|
||||
|
||||
use crate::sync::SpinNoIrqLock as Mutex;
|
||||
use apic::{XApic, LAPIC_ADDR};
|
||||
use core::{
|
||||
future::Future,
|
||||
@ -22,7 +23,6 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
pub use proc::*;
|
||||
use spin::Mutex;
|
||||
pub use structs::*;
|
||||
pub use thread::*;
|
||||
use x86_64::{
|
||||
|
@ -92,7 +92,10 @@ impl Syscall<'_> {
|
||||
) -> SysResult {
|
||||
let proc = self.process();
|
||||
if !proc.pid.is_init() {
|
||||
info!("ppoll: nfds: {}", nfds);
|
||||
info!(
|
||||
"ppoll: ufds: {:?} nfds: {}, timeout: {:?}",
|
||||
ufds, nfds, timeout
|
||||
);
|
||||
}
|
||||
let timeout_msecs = if timeout.is_null() {
|
||||
1 << 31 // infinity
|
||||
|
@ -44,9 +44,9 @@ mod user;
|
||||
|
||||
use crate::signal::{Signal, SignalAction, SignalFrame, SignalStack, SignalUserContext, Sigset};
|
||||
#[cfg(feature = "profile")]
|
||||
use alloc::collections::BTreeMap;
|
||||
use crate::sync::SpinNoIrqLock as Mutex;
|
||||
#[cfg(feature = "profile")]
|
||||
use spin::Mutex;
|
||||
use alloc::collections::BTreeMap;
|
||||
use trapframe::{GeneralRegs, UserContext};
|
||||
|
||||
#[cfg(feature = "profile")]
|
||||
@ -333,9 +333,9 @@ impl Syscall<'_> {
|
||||
SYS_NANOSLEEP => self.sys_nanosleep(UserInPtr::from(args[0])).await,
|
||||
SYS_SETITIMER => self.unimplemented("setitimer", Ok(0)),
|
||||
SYS_GETTIMEOFDAY => {
|
||||
self.sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8)
|
||||
self.sys_gettimeofday(UserOutPtr::from(args[0]), UserInPtr::from(args[1]))
|
||||
}
|
||||
SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
|
||||
SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], UserOutPtr::from(args[1])),
|
||||
|
||||
// sem
|
||||
#[cfg(not(target_arch = "mips"))]
|
||||
|
@ -382,7 +382,7 @@ impl Syscall<'_> {
|
||||
|
||||
pub async fn sys_nanosleep(&mut self, req: UserInPtr<TimeSpec>) -> SysResult {
|
||||
let time = req.read()?;
|
||||
info!("nanosleep: time: {:#?}", time);
|
||||
info!("nanosleep: time: {:#?},", time);
|
||||
if !time.is_zero() {
|
||||
// TODO: handle wakeup
|
||||
sleep_for(time.to_duration()).await;
|
||||
|
@ -7,26 +7,27 @@ use lazy_static::lazy_static;
|
||||
use rcore_fs::vfs::Timespec;
|
||||
|
||||
impl Syscall<'_> {
|
||||
pub fn sys_gettimeofday(&mut self, tv: *mut TimeVal, tz: *const u8) -> SysResult {
|
||||
pub fn sys_gettimeofday(
|
||||
&mut self,
|
||||
mut tv: UserOutPtr<TimeVal>,
|
||||
tz: UserInPtr<u8>,
|
||||
) -> SysResult {
|
||||
info!("gettimeofday: tv: {:?}, tz: {:?}", tv, tz);
|
||||
if tz as usize != 0 {
|
||||
// don't support tz
|
||||
if !tz.is_null() {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
|
||||
let tv = unsafe { self.vm().check_write_ptr(tv)? };
|
||||
|
||||
let timeval = TimeVal::get_epoch();
|
||||
*tv = timeval;
|
||||
tv.write(timeval)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_clock_gettime(&mut self, clock: usize, ts: *mut TimeSpec) -> SysResult {
|
||||
pub fn sys_clock_gettime(&mut self, clock: usize, mut ts: UserOutPtr<TimeSpec>) -> SysResult {
|
||||
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
|
||||
|
||||
let ts = unsafe { self.vm().check_write_ptr(ts)? };
|
||||
|
||||
let timespec = TimeSpec::get_epoch();
|
||||
*ts = timespec;
|
||||
ts.write(timespec)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::SysError;
|
||||
use crate::memory::copy_from_user;
|
||||
use crate::memory::{copy_from_user, copy_to_user};
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt::{Debug, Formatter};
|
||||
@ -66,13 +66,6 @@ impl<T, P: Policy> UserPtr<T, P> {
|
||||
pub fn as_ptr(&self) -> *mut T {
|
||||
self.ptr
|
||||
}
|
||||
|
||||
pub fn check(&self) -> Result<()> {
|
||||
if self.ptr.is_null() {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P: Read> UserPtr<T, P> {
|
||||
@ -81,9 +74,11 @@ impl<T, P: Read> UserPtr<T, P> {
|
||||
}
|
||||
|
||||
pub fn read(&self) -> Result<T> {
|
||||
// TODO: check ptr and return err
|
||||
self.check()?;
|
||||
Ok(unsafe { self.ptr.read() })
|
||||
if let Some(res) = copy_from_user(self.ptr) {
|
||||
Ok(res)
|
||||
} else {
|
||||
Err(SysError::EFAULT)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_if_not_null(&self) -> Result<Option<T>> {
|
||||
@ -98,11 +93,14 @@ impl<T, P: Read> UserPtr<T, P> {
|
||||
if len == 0 {
|
||||
return Ok(Vec::default());
|
||||
}
|
||||
self.check()?;
|
||||
let mut ret = Vec::<T>::with_capacity(len);
|
||||
unsafe {
|
||||
ret.set_len(len);
|
||||
ret.as_mut_ptr().copy_from_nonoverlapping(self.ptr, len);
|
||||
for i in 0..len {
|
||||
let ptr = unsafe { self.ptr.add(i) };
|
||||
if let Some(res) = copy_from_user(ptr) {
|
||||
ret.push(res)
|
||||
} else {
|
||||
return Err(SysError::EFAULT);
|
||||
}
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
@ -110,41 +108,34 @@ impl<T, P: Read> UserPtr<T, P> {
|
||||
|
||||
impl<P: Read> UserPtr<u8, P> {
|
||||
pub fn read_string(&self, len: usize) -> Result<String> {
|
||||
self.check()?;
|
||||
let src = unsafe { core::slice::from_raw_parts(self.ptr, len) };
|
||||
let s = core::str::from_utf8(src).map_err(|_| SysError::EINVAL)?;
|
||||
let src = self.read_array(len)?;
|
||||
let s = core::str::from_utf8(&src).map_err(|_| SysError::EINVAL)?;
|
||||
Ok(String::from(s))
|
||||
}
|
||||
|
||||
pub fn read_cstring(&self) -> Result<String> {
|
||||
self.check()?;
|
||||
let len = unsafe { (0usize..).find(|&i| *self.ptr.add(i) == 0).unwrap() };
|
||||
self.read_string(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Read> UserPtr<UserPtr<u8, P>, P> {
|
||||
pub fn read_cstring_array(&self) -> Result<Vec<String>> {
|
||||
self.check()?;
|
||||
let len = unsafe {
|
||||
(0usize..)
|
||||
.find(|&i| self.ptr.add(i).read().is_null())
|
||||
.unwrap()
|
||||
};
|
||||
self.read_array(len)?
|
||||
.into_iter()
|
||||
.map(|ptr| ptr.read_cstring())
|
||||
.collect()
|
||||
for i in 0.. {
|
||||
let ptr = unsafe { self.ptr.add(i) };
|
||||
if let Some(res) = copy_from_user(ptr) {
|
||||
if res == 0 {
|
||||
// found
|
||||
return self.read_string(i);
|
||||
}
|
||||
} else {
|
||||
return Err(SysError::EFAULT);
|
||||
}
|
||||
}
|
||||
Err(SysError::EINVAL)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P: Write> UserPtr<T, P> {
|
||||
pub fn write(&mut self, value: T) -> Result<()> {
|
||||
self.check()?;
|
||||
unsafe {
|
||||
self.ptr.write(value);
|
||||
if copy_to_user(self.ptr, &value) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SysError::EFAULT)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_if_not_null(&mut self, value: T) -> Result<()> {
|
||||
@ -158,10 +149,11 @@ impl<T, P: Write> UserPtr<T, P> {
|
||||
if values.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
self.check()?;
|
||||
unsafe {
|
||||
self.ptr
|
||||
.copy_from_nonoverlapping(values.as_ptr(), values.len());
|
||||
for i in 0..values.len() {
|
||||
let ptr = unsafe { self.ptr.add(i) };
|
||||
if !copy_to_user(ptr, &values[i]) {
|
||||
return Err(SysError::EFAULT);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -171,8 +163,10 @@ impl<P: Write> UserPtr<u8, P> {
|
||||
pub fn write_cstring(&mut self, s: &str) -> Result<()> {
|
||||
let bytes = s.as_bytes();
|
||||
self.write_array(bytes)?;
|
||||
unsafe {
|
||||
self.ptr.add(bytes.len()).write(0);
|
||||
let ptr = unsafe { self.ptr.add(bytes.len()) };
|
||||
let null = 0u8;
|
||||
if !copy_to_user(ptr, &null) {
|
||||
return Err(SysError::EFAULT);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user