1
0
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:
Jiajie Chen 2020-06-19 09:09:38 +08:00
parent 3d9a1a7356
commit 990bb6a4a1
7 changed files with 77 additions and 62 deletions

View File

@ -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,
}
}

View File

@ -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::{

View File

@ -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

View File

@ -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"))]

View File

@ -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;

View File

@ -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)
}

View File

@ -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(())
}