convert user ptr to reference on check

toolchain_update
WangRunji 6 years ago
parent 894c411e4e
commit 58271c7c8a

@ -205,29 +205,55 @@ impl<T: InactivePageTable> MemorySet<T> {
} }
} }
/// Check the pointer is within the readable memory /// Check the pointer is within the readable memory
pub fn check_read_ptr<S>(&self, ptr: *const S) -> VMResult<()> { pub unsafe fn check_read_ptr<S>(&self, ptr: *const S) -> VMResult<&'static S> {
self.check_read_array(ptr, 1) self.check_read_array(ptr, 1).map(|s| &s[0])
} }
/// Check the pointer is within the writable memory /// Check the pointer is within the writable memory
pub fn check_write_ptr<S>(&self, ptr: *mut S) -> VMResult<()> { pub unsafe fn check_write_ptr<S>(&self, ptr: *mut S) -> VMResult<&'static mut S> {
self.check_write_array(ptr, 1) self.check_write_array(ptr, 1).map(|s| &mut s[0])
} }
/// Check the array is within the readable memory /// Check the array is within the readable memory
pub fn check_read_array<S>(&self, ptr: *const S, count: usize) -> VMResult<()> { pub unsafe fn check_read_array<S>(
&self,
ptr: *const S,
count: usize,
) -> VMResult<&'static [S]> {
self.areas self.areas
.iter() .iter()
.find(|area| area.check_read_array(ptr, count)) .find(|area| area.check_read_array(ptr, count))
.map(|_| ()) .map(|_| core::slice::from_raw_parts(ptr, count))
.ok_or(VMError::InvalidPtr) .ok_or(VMError::InvalidPtr)
} }
/// Check the array is within the writable memory /// Check the array is within the writable memory
pub fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> VMResult<()> { pub unsafe fn check_write_array<S>(
&self,
ptr: *mut S,
count: usize,
) -> VMResult<&'static mut [S]> {
self.areas self.areas
.iter() .iter()
.find(|area| area.check_write_array(ptr, count)) .find(|area| area.check_write_array(ptr, count))
.map(|_| ()) .map(|_| core::slice::from_raw_parts_mut(ptr, count))
.ok_or(VMError::InvalidPtr) .ok_or(VMError::InvalidPtr)
} }
/// Check the null-end C string pointer array
/// Used for getting argv & envp
pub unsafe fn check_and_clone_cstr_array(
&self,
mut argv: *const *const u8,
) -> VMResult<Vec<String>> {
let mut args = Vec::new();
loop {
let cstr = *self.check_read_ptr(argv)?;
if cstr.is_null() {
break;
}
let arg = self.check_and_clone_cstr(cstr)?;
args.push(arg);
argv = argv.add(1);
}
Ok(args)
}
/// Check the null-end C string is within the readable memory, and is valid. /// Check the null-end C string is within the readable memory, and is valid.
/// If so, clone it to a String. /// If so, clone it to a String.
/// ///

@ -43,10 +43,8 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
/// mapped to a list of virtual addresses. /// mapped to a list of virtual addresses.
pub fn sys_get_paddr(vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult { pub fn sys_get_paddr(vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult {
let mut proc = process(); let mut proc = process();
proc.vm.check_read_array(vaddrs, count)?; let vaddrs = unsafe { proc.vm.check_read_array(vaddrs, count)? };
proc.vm.check_write_array(paddrs, count)?; let paddrs = unsafe { proc.vm.check_write_array(paddrs, count)? };
let vaddrs = unsafe { slice::from_raw_parts(vaddrs, count) };
let paddrs = unsafe { slice::from_raw_parts_mut(paddrs, count) };
for i in 0..count { for i in 0..count {
let paddr = proc.vm.translate(vaddrs[i] as usize).unwrap_or(0); let paddr = proc.vm.translate(vaddrs[i] as usize).unwrap_or(0);
paddrs[i] = paddr as u64; paddrs[i] = paddr as u64;

@ -21,8 +21,7 @@ pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult {
// we trust pid 0 process // we trust pid 0 process
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len); info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
} }
proc.vm.check_write_array(base, len)?; let slice = unsafe { proc.vm.check_write_array(base, len)? };
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
let file_like = proc.get_file_like(fd)?; let file_like = proc.get_file_like(fd)?;
let len = file_like.read(slice)?; let len = file_like.read(slice)?;
Ok(len) Ok(len)
@ -34,8 +33,7 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
// we trust pid 0 process // we trust pid 0 process
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
} }
proc.vm.check_read_array(base, len)?; let slice = unsafe { proc.vm.check_read_array(base, len)? };
let slice = unsafe { slice::from_raw_parts(base, len) };
let file_like = proc.get_file_like(fd)?; let file_like = proc.get_file_like(fd)?;
let len = file_like.write(slice)?; let len = file_like.write(slice)?;
Ok(len) Ok(len)
@ -47,9 +45,7 @@ pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResu
fd, base, len, offset fd, base, len, offset
); );
let mut proc = process(); let mut proc = process();
proc.vm.check_write_array(base, len)?; let slice = unsafe { proc.vm.check_write_array(base, len)? };
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
let len = proc.get_file(fd)?.read_at(offset, slice)?; let len = proc.get_file(fd)?.read_at(offset, slice)?;
Ok(len) Ok(len)
} }
@ -60,9 +56,7 @@ pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysR
fd, base, len, offset fd, base, len, offset
); );
let mut proc = process(); let mut proc = process();
proc.vm.check_read_array(base, len)?; let slice = unsafe { proc.vm.check_read_array(base, len)? };
let slice = unsafe { slice::from_raw_parts(base, len) };
let len = proc.get_file(fd)?.write_at(offset, slice)?; let len = proc.get_file(fd)?.write_at(offset, slice)?;
Ok(len) Ok(len)
} }
@ -72,8 +66,8 @@ pub fn sys_ppoll(ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> Sy
let timeout_msecs = if timeout.is_null() { let timeout_msecs = if timeout.is_null() {
1 << 31 // infinity 1 << 31 // infinity
} else { } else {
proc.vm.check_read_ptr(timeout)?; let timeout = unsafe { proc.vm.check_read_ptr(timeout)? };
unsafe { (*timeout).to_msec() } timeout.to_msec()
}; };
drop(proc); drop(proc);
@ -89,9 +83,8 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu
ufds, nfds, timeout_msecs ufds, nfds, timeout_msecs
); );
} }
proc.vm.check_write_array(ufds, nfds)?;
let polls = unsafe { slice::from_raw_parts_mut(ufds, nfds) }; let polls = unsafe { proc.vm.check_write_array(ufds, nfds)? };
for poll in polls.iter() { for poll in polls.iter() {
if proc.files.get(&(poll.fd as usize)).is_none() { if proc.files.get(&(poll.fd as usize)).is_none() {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
@ -156,9 +149,9 @@ pub fn sys_select(
let mut read_fds = FdSet::new(&proc.vm, read, nfds)?; let mut read_fds = FdSet::new(&proc.vm, read, nfds)?;
let mut write_fds = FdSet::new(&proc.vm, write, nfds)?; let mut write_fds = FdSet::new(&proc.vm, write, nfds)?;
let mut err_fds = FdSet::new(&proc.vm, err, nfds)?; let mut err_fds = FdSet::new(&proc.vm, err, nfds)?;
let timeout_msecs = if timeout as usize != 0 { let timeout_msecs = if !timeout.is_null() {
proc.vm.check_read_ptr(timeout)?; let timeout = unsafe { proc.vm.check_read_ptr(timeout)? };
unsafe { *timeout }.to_msec() timeout.to_msec()
} else { } else {
// infinity // infinity
1 << 31 1 << 31
@ -214,7 +207,7 @@ pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResul
fd, iov_ptr, iov_count fd, iov_ptr, iov_count
); );
let mut proc = process(); let mut proc = process();
let mut iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)?; let mut iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)? };
// read all data to a buf // read all data to a buf
let file_like = proc.get_file_like(fd)?; let file_like = proc.get_file_like(fd)?;
@ -234,7 +227,7 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu
fd, iov_ptr, iov_count fd, iov_ptr, iov_count
); );
} }
let iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)?; let iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)? };
let buf = iovs.read_all_to_vec(); let buf = iovs.read_all_to_vec();
let len = buf.len(); let len = buf.len();
@ -315,12 +308,12 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
// we trust pid 0 process // we trust pid 0 process
info!("getcwd: buf: {:?}, len: {:#x}", buf, len); info!("getcwd: buf: {:?}, len: {:#x}", buf, len);
} }
proc.vm.check_write_array(buf, len)?; let buf = unsafe { proc.vm.check_write_array(buf, len)? };
if proc.cwd.len() + 1 > len { if proc.cwd.len() + 1 > len {
return Err(SysError::ERANGE); return Err(SysError::ERANGE);
} }
unsafe { util::write_cstr(buf, &proc.cwd) } unsafe { util::write_cstr(buf.as_mut_ptr(), &proc.cwd) }
Ok(buf as usize) Ok(buf.as_ptr() as usize)
} }
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult { pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
@ -330,19 +323,17 @@ pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult { pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr); info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr);
let mut proc = process(); let mut proc = process();
proc.vm.check_write_ptr(stat_ptr)?; let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? };
let file = proc.get_file(fd)?; let file = proc.get_file(fd)?;
let stat = Stat::from(file.metadata()?); let stat = Stat::from(file.metadata()?);
unsafe { *stat_ref = stat;
stat_ptr.write(stat);
}
Ok(0) Ok(0)
} }
pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult { pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult {
let proc = process(); let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
proc.vm.check_write_ptr(stat_ptr)?; let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? };
let flags = AtFlags::from_bits_truncate(flags); let flags = AtFlags::from_bits_truncate(flags);
info!( info!(
"fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}", "fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}",
@ -351,9 +342,7 @@ pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: us
let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?; let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?;
let stat = Stat::from(inode.metadata()?); let stat = Stat::from(inode.metadata()?);
unsafe { *stat_ref = stat;
stat_ptr.write(stat);
}
Ok(0) Ok(0)
} }
@ -368,14 +357,13 @@ pub fn sys_readlink(path: *const u8, base: *mut u8, len: usize) -> SysResult {
pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult { pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult {
let proc = process(); let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
proc.vm.check_write_array(base, len)?; let slice = unsafe { proc.vm.check_write_array(base, len)? };
info!("readlink: path: {:?}, base: {:?}, len: {}", path, base, len); info!("readlink: path: {:?}, base: {:?}, len: {}", path, base, len);
let inode = proc.lookup_inode_at(dirfd, &path, false)?; let inode = proc.lookup_inode_at(dirfd, &path, false)?;
if inode.metadata()?.type_ == FileType::SymLink { if inode.metadata()?.type_ == FileType::SymLink {
// TODO: recursive link resolution and loop detection // TODO: recursive link resolution and loop detection
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) }; let len = inode.read_at(0, slice)?;
let len = inode.read_at(0, &mut slice)?;
Ok(len) Ok(len)
} else { } else {
Err(SysError::EINVAL) Err(SysError::EINVAL)
@ -429,13 +417,13 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy
fd, buf, buf_size fd, buf, buf_size
); );
let mut proc = process(); let mut proc = process();
proc.vm.check_write_array(buf as *mut u8, buf_size)?; let buf = unsafe { proc.vm.check_write_array(buf as *mut u8, buf_size)? };
let file = proc.get_file(fd)?; let file = proc.get_file(fd)?;
let info = file.metadata()?; let info = file.metadata()?;
if info.type_ != FileType::Dir { if info.type_ != FileType::Dir {
return Err(SysError::ENOTDIR); return Err(SysError::ENOTDIR);
} }
let mut writer = unsafe { DirentBufWriter::new(buf, buf_size) }; let mut writer = DirentBufWriter::new(buf);
loop { loop {
let name = match file.read_entry() { let name = match file.read_entry() {
Err(FsError::EntryNotFound) => break, Err(FsError::EntryNotFound) => break,
@ -631,7 +619,7 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
info!("pipe: fds: {:?}", fds); info!("pipe: fds: {:?}", fds);
let mut proc = process(); let mut proc = process();
proc.vm.check_write_array(fds, 2)?; let fds = unsafe { proc.vm.check_write_array(fds, 2)? };
let (read, write) = Pipe::create_pair(); let (read, write) = Pipe::create_pair();
let read_fd = proc.add_file( let read_fd = proc.add_file(
@ -656,10 +644,8 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
)), )),
); );
unsafe { fds[0] = read_fd as u32;
fds.write(read_fd as u32); fds[1] = write_fd as u32;
fds.add(1).write(write_fd as u32);
}
info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd); info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd);
@ -690,8 +676,7 @@ pub fn sys_sendfile(
let mut read_offset = if !offset_ptr.is_null() { let mut read_offset = if !offset_ptr.is_null() {
unsafe { unsafe {
(*proc_cell.get()).vm.check_read_ptr(offset_ptr)?; *(*proc_cell.get()).vm.check_read_ptr(offset_ptr)?
offset_ptr.read()
} }
} else { } else {
in_file.seek(SeekFrom::Current(0))? as usize in_file.seek(SeekFrom::Current(0))? as usize
@ -880,18 +865,20 @@ pub struct LinuxDirent64 {
name: [u8; 0], name: [u8; 0],
} }
struct DirentBufWriter { struct DirentBufWriter<'a> {
buf: &'a mut [u8],
ptr: *mut LinuxDirent64, ptr: *mut LinuxDirent64,
rest_size: usize, rest_size: usize,
written_size: usize, written_size: usize,
} }
impl DirentBufWriter { impl<'a> DirentBufWriter<'a> {
unsafe fn new(buf: *mut LinuxDirent64, size: usize) -> Self { fn new(buf: &'a mut [u8]) -> Self {
DirentBufWriter { DirentBufWriter {
ptr: buf, ptr: buf.as_mut_ptr() as *mut LinuxDirent64,
rest_size: size, rest_size: buf.len(),
written_size: 0, written_size: 0,
buf,
} }
} }
fn try_write(&mut self, inode: u64, type_: u8, name: &str) -> bool { fn try_write(&mut self, inode: u64, type_: u8, name: &str) -> bool {
@ -1239,28 +1226,28 @@ pub struct IoVec {
pub struct IoVecs(Vec<&'static mut [u8]>); pub struct IoVecs(Vec<&'static mut [u8]>);
impl IoVecs { impl IoVecs {
pub fn check_and_new( pub unsafe fn check_and_new(
iov_ptr: *const IoVec, iov_ptr: *const IoVec,
iov_count: usize, iov_count: usize,
vm: &MemorySet, vm: &MemorySet,
readv: bool, readv: bool,
) -> Result<Self, SysError> { ) -> Result<Self, SysError> {
vm.check_read_array(iov_ptr, iov_count)?; let iovs = vm.check_read_array(iov_ptr, iov_count)?.to_vec();
let iovs = unsafe { slice::from_raw_parts(iov_ptr, iov_count) }.to_vec();
// check all bufs in iov // check all bufs in iov
for iov in iovs.iter() { for iov in iovs.iter() {
if iov.len > 0 { // skip empty iov
// skip empty iov if iov.len == 0 {
if readv { continue;
vm.check_write_array(iov.base, iov.len)?; }
} else { if readv {
vm.check_read_array(iov.base, iov.len)?; vm.check_write_array(iov.base, iov.len)?;
} } else {
vm.check_read_array(iov.base, iov.len)?;
} }
} }
let slices = iovs let slices = iovs
.iter() .iter()
.map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len) }) .map(|iov| slice::from_raw_parts_mut(iov.base, iov.len))
.collect(); .collect();
Ok(IoVecs(slices)) Ok(IoVecs(slices))
} }
@ -1342,11 +1329,10 @@ impl FdSet {
}) })
} else { } else {
let len = (nfds + FD_PER_ITEM - 1) / FD_PER_ITEM; let len = (nfds + FD_PER_ITEM - 1) / FD_PER_ITEM;
vm.check_write_array(addr, len)?;
if len > MAX_FDSET_SIZE { if len > MAX_FDSET_SIZE {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
let slice = unsafe { slice::from_raw_parts_mut(addr, len) }; let slice = unsafe { vm.check_write_array(addr, len)? };
let bitset: &'static mut BitSlice<LittleEndian, u32> = slice.into(); let bitset: &'static mut BitSlice<LittleEndian, u32> = slice.into();
// save the fdset, and clear it // save the fdset, and clear it

@ -18,16 +18,16 @@ pub fn sys_arch_prctl(code: i32, addr: usize, tf: &mut TrapFrame) -> SysResult {
} }
pub fn sys_uname(buf: *mut u8) -> SysResult { pub fn sys_uname(buf: *mut u8) -> SysResult {
info!("sched_uname: buf: {:?}", buf); info!("uname: buf: {:?}", buf);
let offset = 65; let offset = 65;
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"]; let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
let proc = process(); let proc = process();
proc.vm.check_write_array(buf, strings.len() * offset)?; let buf = unsafe { proc.vm.check_write_array(buf, strings.len() * offset)? };
for i in 0..strings.len() { for i in 0..strings.len() {
unsafe { unsafe {
util::write_cstr(buf.add(i * offset), &strings[i]); util::write_cstr(&mut buf[i * offset], &strings[i]);
} }
} }
Ok(0) Ok(0)
@ -39,22 +39,20 @@ pub fn sys_sched_getaffinity(pid: usize, size: usize, mask: *mut u32) -> SysResu
pid, size, mask pid, size, mask
); );
let proc = process(); let proc = process();
proc.vm.check_write_array(mask, size / size_of::<u32>())?; let mask = unsafe { proc.vm.check_write_array(mask, size / size_of::<u32>())? };
// we only have 4 cpu at most. // we only have 4 cpu at most.
// so just set it. // so just set it.
unsafe { mask[0] = 0b1111;
*mask = 0b1111;
}
Ok(0) Ok(0)
} }
pub fn sys_sysinfo(sys_info: *mut SysInfo) -> SysResult { pub fn sys_sysinfo(sys_info: *mut SysInfo) -> SysResult {
let proc = process(); let proc = process();
proc.vm.check_write_ptr(sys_info)?; let sys_info = unsafe { proc.vm.check_write_ptr(sys_info)? };
let sysinfo = SysInfo::default(); let sysinfo = SysInfo::default();
unsafe { *sys_info = sysinfo }; *sys_info = sysinfo;
Ok(0) Ok(0)
} }
@ -74,13 +72,11 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
if uaddr % size_of::<u32>() != 0 { if uaddr % size_of::<u32>() != 0 {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
process().vm.check_write_ptr(uaddr as *mut AtomicI32)?; let atomic = unsafe { process().vm.check_write_ptr(uaddr as *mut AtomicI32)? };
let atomic = unsafe { &mut *(uaddr as *mut AtomicI32) };
let _timeout = if timeout.is_null() { let _timeout = if timeout.is_null() {
None None
} else { } else {
process().vm.check_read_ptr(timeout)?; Some(unsafe { *process().vm.check_read_ptr(timeout)? })
Some(unsafe { *timeout })
}; };
const OP_WAIT: u32 = 0; const OP_WAIT: u32 = 0;
@ -156,38 +152,32 @@ pub fn sys_prlimit64(
match resource { match resource {
RLIMIT_STACK => { RLIMIT_STACK => {
if !old_limit.is_null() { if !old_limit.is_null() {
proc.vm.check_write_ptr(old_limit)?; let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? };
unsafe { *old_limit = RLimit {
*old_limit = RLimit { cur: USER_STACK_SIZE as u64,
cur: USER_STACK_SIZE as u64, max: USER_STACK_SIZE as u64,
max: USER_STACK_SIZE as u64, };
};
}
} }
Ok(0) Ok(0)
} }
RLIMIT_NOFILE => { RLIMIT_NOFILE => {
if !old_limit.is_null() { if !old_limit.is_null() {
proc.vm.check_write_ptr(old_limit)?; let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? };
unsafe { *old_limit = RLimit {
*old_limit = RLimit { cur: 1024,
cur: 1024, max: 1024,
max: 1024, };
};
}
} }
Ok(0) Ok(0)
} }
RLIMIT_RSS | RLIMIT_AS => { RLIMIT_RSS | RLIMIT_AS => {
if !old_limit.is_null() { if !old_limit.is_null() {
proc.vm.check_write_ptr(old_limit)?; let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? };
unsafe { // 1GB
// 1GB *old_limit = RLimit {
*old_limit = RLimit { cur: 1024 * 1024 * 1024,
cur: 1024 * 1024 * 1024, max: 1024 * 1024 * 1024,
max: 1024 * 1024 * 1024, };
};
}
} }
Ok(0) Ok(0)
} }
@ -206,8 +196,7 @@ pub fn sys_getrandom( buf: *mut u8, len: usize, flag: u32) -> SysResult {
//info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag); //info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag);
let mut proc = process(); let mut proc = process();
proc.vm.check_write_array(buf, len)?; let slice = unsafe { proc.vm.check_write_array(buf, len)? };
let slice = unsafe { slice::from_raw_parts_mut(buf, len) };
let mut i=0; let mut i=0;
for elm in slice { for elm in slice {
unsafe{ *elm=i+ crate::trap::TICK as u8;} unsafe{ *elm=i+ crate::trap::TICK as u8;}

@ -55,8 +55,7 @@ pub fn sys_setsockopt(
fd, level, optname fd, level, optname
); );
let mut proc = process(); let mut proc = process();
proc.vm.check_read_array(optval, optlen)?; let data = unsafe { proc.vm.check_read_array(optval, optlen)? };
let data = unsafe { slice::from_raw_parts(optval, optlen) };
let socket = proc.get_socket(fd)?; let socket = proc.get_socket(fd)?;
socket.setsockopt(level, optname, data) socket.setsockopt(level, optname, data)
} }
@ -73,23 +72,19 @@ pub fn sys_getsockopt(
fd, level, optname, optval, optlen fd, level, optname, optval, optlen
); );
let proc = process(); let proc = process();
proc.vm.check_write_ptr(optlen)?; let optlen = unsafe { proc.vm.check_write_ptr(optlen)? };
match level { match level {
SOL_SOCKET => match optname { SOL_SOCKET => match optname {
SO_SNDBUF => { SO_SNDBUF => {
proc.vm.check_write_array(optval, 4)?; let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? };
unsafe { *optval = crate::net::TCP_SENDBUF as u32;
*(optval as *mut u32) = crate::net::TCP_SENDBUF as u32; *optlen = 4;
*optlen = 4;
}
Ok(0) Ok(0)
} }
SO_RCVBUF => { SO_RCVBUF => {
proc.vm.check_write_array(optval, 4)?; let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? };
unsafe { *optval = crate::net::TCP_RECVBUF as u32;
*(optval as *mut u32) = crate::net::TCP_RECVBUF as u32; *optlen = 4;
*optlen = 4;
}
Ok(0) Ok(0)
} }
_ => Err(SysError::ENOPROTOOPT), _ => Err(SysError::ENOPROTOOPT),
@ -129,9 +124,8 @@ pub fn sys_sendto(
); );
let mut proc = process(); let mut proc = process();
proc.vm.check_read_array(base, len)?;
let slice = unsafe { slice::from_raw_parts(base, len) }; let slice = unsafe { proc.vm.check_read_array(base, len)? };
let endpoint = if addr.is_null() { let endpoint = if addr.is_null() {
None None
} else { } else {
@ -157,10 +151,9 @@ pub fn sys_recvfrom(
); );
let mut proc = process(); let mut proc = process();
proc.vm.check_write_array(base, len)?;
let mut slice = unsafe { proc.vm.check_write_array(base, len)? };
let socket = proc.get_socket(fd)?; let socket = proc.get_socket(fd)?;
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
let (result, endpoint) = socket.read(&mut slice); let (result, endpoint) = socket.read(&mut slice);
if result.is_ok() && !addr.is_null() { if result.is_ok() && !addr.is_null() {
@ -176,9 +169,8 @@ pub fn sys_recvfrom(
pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult { pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult {
info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags); info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags);
let mut proc = process(); let mut proc = process();
proc.vm.check_read_ptr(msg)?; let hdr = unsafe { proc.vm.check_write_ptr(msg)? };
let hdr = unsafe { &mut *msg }; let mut iovs = unsafe { IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)? };
let mut iovs = IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)?;
let mut buf = iovs.new_buf(true); let mut buf = iovs.new_buf(true);
let socket = proc.get_socket(fd)?; let socket = proc.get_socket(fd)?;
@ -406,16 +398,16 @@ fn sockaddr_to_endpoint(
if len < size_of::<u16>() { if len < size_of::<u16>() {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
proc.vm.check_read_array(addr as *const u8, len)?; let addr = unsafe { proc.vm.check_read_ptr(addr)? };
unsafe { unsafe {
match AddressFamily::from((*addr).family) { match AddressFamily::from(addr.family) {
AddressFamily::Internet => { AddressFamily::Internet => {
if len < size_of::<SockAddrIn>() { if len < size_of::<SockAddrIn>() {
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
let port = u16::from_be((*addr).addr_in.sin_port); let port = u16::from_be(addr.addr_in.sin_port);
let addr = IpAddress::from(Ipv4Address::from_bytes( let addr = IpAddress::from(Ipv4Address::from_bytes(
&u32::from_be((*addr).addr_in.sin_addr).to_be_bytes()[..], &u32::from_be(addr.addr_in.sin_addr).to_be_bytes()[..],
)); ));
Ok(Endpoint::Ip((addr, port).into())) Ok(Endpoint::Ip((addr, port).into()))
} }
@ -425,7 +417,7 @@ fn sockaddr_to_endpoint(
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new( Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
(*addr).addr_ll.sll_ifindex as usize, addr.addr_ll.sll_ifindex as usize,
))) )))
} }
AddressFamily::Netlink => { AddressFamily::Netlink => {
@ -433,8 +425,8 @@ fn sockaddr_to_endpoint(
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
Ok(Endpoint::Netlink(NetlinkEndpoint::new( Ok(Endpoint::Netlink(NetlinkEndpoint::new(
(*addr).addr_nl.nl_pid, addr.addr_nl.nl_pid,
(*addr).addr_nl.nl_groups, addr.addr_nl.nl_groups,
))) )))
} }
_ => Err(SysError::EINVAL), _ => Err(SysError::EINVAL),
@ -456,7 +448,7 @@ impl SockAddr {
return Ok(0); return Ok(0);
} }
proc.vm.check_write_ptr(addr_len)?; let addr_len = unsafe { proc.vm.check_write_ptr(addr_len)? };
let max_addr_len = *addr_len as usize; let max_addr_len = *addr_len as usize;
let full_len = match AddressFamily::from(self.family) { let full_len = match AddressFamily::from(self.family) {
AddressFamily::Internet => size_of::<SockAddrIn>(), AddressFamily::Internet => size_of::<SockAddrIn>(),
@ -468,12 +460,11 @@ impl SockAddr {
let written_len = min(max_addr_len, full_len); let written_len = min(max_addr_len, full_len);
if written_len > 0 { if written_len > 0 {
proc.vm.check_write_array(addr as *mut u8, written_len)?; let target = unsafe { proc.vm.check_write_array(addr as *mut u8, written_len)? };
let source = slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len); let source = slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len);
let target = slice::from_raw_parts_mut(addr as *mut u8, written_len);
target.copy_from_slice(source); target.copy_from_slice(source);
} }
addr_len.write(full_len as u32); *addr_len = full_len as u32;
return Ok(0); return Ok(0);
} }
} }

@ -43,19 +43,14 @@ pub fn sys_clone(
); );
//return Err(SysError::ENOSYS); //return Err(SysError::ENOSYS);
} }
{ let parent_tid_ref = unsafe { process().vm.check_write_ptr(parent_tid)? };
let proc = process(); let child_tid_ref = unsafe { process().vm.check_write_ptr(child_tid)? };
proc.vm.check_write_ptr(parent_tid)?;
proc.vm.check_write_ptr(child_tid)?;
}
let new_thread = current_thread().clone(tf, newsp, newtls, child_tid as usize); let new_thread = current_thread().clone(tf, newsp, newtls, child_tid as usize);
// FIXME: parent pid // FIXME: parent pid
let tid = processor().manager().add(new_thread); let tid = processor().manager().add(new_thread);
info!("clone: {} -> {}", thread::current().id(), tid); info!("clone: {} -> {}", thread::current().id(), tid);
unsafe { *parent_tid_ref = tid as u32;
parent_tid.write(tid as u32); *child_tid_ref = tid as u32;
child_tid.write(tid as u32);
}
Ok(tid) Ok(tid)
} }
@ -63,9 +58,11 @@ pub fn sys_clone(
/// Return the PID. Store exit code to `wstatus` if it's not null. /// Return the PID. Store exit code to `wstatus` if it's not null.
pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult { pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
//info!("wait4: pid: {}, code: {:?}", pid, wstatus); //info!("wait4: pid: {}, code: {:?}", pid, wstatus);
if !wstatus.is_null() { let wstatus = if !wstatus.is_null() {
process().vm.check_write_ptr(wstatus)?; Some(unsafe { process().vm.check_write_ptr(wstatus)? })
} } else {
None
};
#[derive(Debug)] #[derive(Debug)]
enum WaitFor { enum WaitFor {
AnyChild, AnyChild,
@ -90,10 +87,8 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
// if found, return // if found, return
if let Some((pid, exit_code)) = find { if let Some((pid, exit_code)) = find {
proc.child_exit_code.remove(&pid); proc.child_exit_code.remove(&pid);
if !wstatus.is_null() { if let Some(wstatus) = wstatus {
unsafe { *wstatus = exit_code as i32;
wstatus.write(exit_code as i32);
}
} }
return Ok(pid); return Ok(pid);
} }
@ -124,69 +119,49 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
} }
} }
/// Replaces the current ** process ** with a new process image
///
/// `argv` is an array of argument strings passed to the new program.
/// `envp` is an array of strings, conventionally of the form `key=value`,
/// which are passed as environment to the new program.
///
/// NOTICE: `argv` & `envp` can not be NULL (different from Linux)
///
/// NOTICE: for multi-thread programs
/// A call to any exec function from a process with more than one thread
/// shall result in all threads being terminated and the new executable image
/// being loaded and executed.
pub fn sys_exec( pub fn sys_exec(
name: *const u8, path: *const u8,
argv: *const *const u8, argv: *const *const u8,
envp: *const *const u8, envp: *const *const u8,
tf: &mut TrapFrame, tf: &mut TrapFrame,
) -> SysResult { ) -> SysResult {
info!("exec:BEG: name: {:?}, argv: {:?}, envp: {:?}", name, argv, envp); info!(
"exec:BEG: path: {:?}, argv: {:?}, envp: {:?}",
path, argv, envp
);
let proc = process(); let proc = process();
let exec_name = if name.is_null() { let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
String::from("") let args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? };
} else { let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? };
unsafe { proc.vm.check_and_clone_cstr(name)? }
};
if argv.is_null() {
info!("exec:END:ERR1: exec_name: {:?}, name: {:?}, argv: is NULL", exec_name, name);
return Err(SysError::EINVAL);
}
// Check and copy args to kernel
let mut args = Vec::new();
unsafe {
let mut current_argv = argv as *const *const u8;
proc.vm.check_read_ptr(current_argv)?;
while !(*current_argv).is_null() {
let arg = proc.vm.check_and_clone_cstr(*current_argv)?;
info!(" arg: {}",arg);
args.push(arg);
current_argv = current_argv.add(1);
}
}
// Check and copy envs to kernel
let mut envs = Vec::new();
unsafe {
let mut current_env = envp as *const *const u8;
if !current_env.is_null() {
proc.vm.check_read_ptr(current_env)?;
while !(*current_env).is_null() {
let env = proc.vm.check_and_clone_cstr(*current_env)?;
info!(" env: {}",env);
envs.push(env);
current_env = current_env.add(1);
}
}
}
if args.is_empty() { if args.is_empty() {
info!("exec:END:ERR2: exec_name: {:?}, name: {:?}, args is empty", exec_name, name); error!("exec: args is null");
return Err(SysError::EINVAL); return Err(SysError::EINVAL);
} }
info!( info!(
"exec:STEP2: exec_name: {:?}, name{:?}, args: {:?}, envp: {:?}", "exec:STEP2: path: {:?}, args: {:?}, envs: {:?}",
exec_name, name, args, envs path, args, envs
); );
// Read program file // Read program file
//let path = args[0].as_str(); let inode = proc.lookup_inode(&path)?;
let exec_path = exec_name.as_str();
let inode = proc.lookup_inode(exec_path)?;
let buf = inode.read_as_vec()?; let buf = inode.read_as_vec()?;
// Make new Thread // Make new Thread
let mut thread = Thread::new_user(buf.as_slice(), exec_path, args, envs); let mut thread = Thread::new_user(buf.as_slice(), &path, args, envs);
thread.proc.lock().clone_for_exec(&proc); thread.proc.lock().clone_for_exec(&proc);
// Activate new page table // Activate new page table
@ -201,10 +176,7 @@ pub fn sys_exec(
::core::mem::swap(&mut current_thread().kstack, &mut thread.kstack); ::core::mem::swap(&mut current_thread().kstack, &mut thread.kstack);
::core::mem::swap(current_thread(), &mut *thread); ::core::mem::swap(current_thread(), &mut *thread);
info!( info!("exec:END: path: {:?}", path);
"exec:END: exec_name: {:?}",
exec_name
);
Ok(0) Ok(0)
} }
@ -337,8 +309,7 @@ pub fn sys_exit_group(exit_code: usize) -> ! {
} }
pub fn sys_nanosleep(req: *const TimeSpec) -> SysResult { pub fn sys_nanosleep(req: *const TimeSpec) -> SysResult {
process().vm.check_read_ptr(req)?; let time = unsafe { *process().vm.check_read_ptr(req)? };
let time = unsafe { req.read() };
info!("nanosleep: time: {:#?}", time); info!("nanosleep: time: {:#?}", time);
// TODO: handle spurious wakeup // TODO: handle spurious wakeup
thread::sleep(time.to_duration()); thread::sleep(time.to_duration());

@ -83,12 +83,10 @@ pub fn sys_gettimeofday(tv: *mut TimeVal, tz: *const u8) -> SysResult {
} }
let proc = process(); let proc = process();
proc.vm.check_write_ptr(tv)?; let tv = unsafe { proc.vm.check_write_ptr(tv)? };
let timeval = TimeVal::get_epoch(); let timeval = TimeVal::get_epoch();
unsafe { *tv = timeval;
*tv = timeval;
}
Ok(0) Ok(0)
} }
@ -96,12 +94,10 @@ pub fn sys_clock_gettime(clock: usize, ts: *mut TimeSpec) -> SysResult {
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts); info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
let proc = process(); let proc = process();
proc.vm.check_write_ptr(ts)?; let ts = unsafe { proc.vm.check_write_ptr(ts)? };
let timespec = TimeSpec::get_epoch(); let timespec = TimeSpec::get_epoch();
unsafe { *ts = timespec;
*ts = timespec;
}
Ok(0) Ok(0)
} }
@ -109,10 +105,8 @@ pub fn sys_time(time: *mut u64) -> SysResult {
let sec = get_epoch_usec() / USEC_PER_SEC; let sec = get_epoch_usec() / USEC_PER_SEC;
if time as usize != 0 { if time as usize != 0 {
let proc = process(); let proc = process();
proc.vm.check_write_ptr(time)?; let time = unsafe { proc.vm.check_write_ptr(time)? };
unsafe { *time = sec as u64;
time.write(sec as u64);
}
} }
Ok(sec as usize) Ok(sec as usize)
} }
@ -127,7 +121,7 @@ pub struct RUsage {
pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult { pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
info!("getrusage: who: {}, rusage: {:?}", who, rusage); info!("getrusage: who: {}, rusage: {:?}", who, rusage);
let proc = process(); let proc = process();
proc.vm.check_write_ptr(rusage)?; let rusage = unsafe { proc.vm.check_write_ptr(rusage)? };
let tick_base = *TICK_BASE; let tick_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 }; let tick = unsafe { crate::trap::TICK as u64 };
@ -143,7 +137,7 @@ pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
usec: (usec % USEC_PER_SEC) as usize, usec: (usec % USEC_PER_SEC) as usize,
}, },
}; };
unsafe { *rusage = new_rusage }; *rusage = new_rusage;
Ok(0) Ok(0)
} }
@ -159,7 +153,7 @@ pub struct Tms {
pub fn sys_times(buf: *mut Tms) -> SysResult { pub fn sys_times(buf: *mut Tms) -> SysResult {
info!("times: buf: {:?}", buf); info!("times: buf: {:?}", buf);
let proc = process(); let proc = process();
proc.vm.check_write_ptr(buf)?; let buf = unsafe { proc.vm.check_write_ptr(buf)? };
let tick_base = *TICK_BASE; let tick_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 }; let tick = unsafe { crate::trap::TICK as u64 };
@ -171,6 +165,6 @@ pub fn sys_times(buf: *mut Tms) -> SysResult {
tms_cstime: 0, tms_cstime: 0,
}; };
unsafe { *buf = new_buf }; *buf = new_buf;
Ok(tick as usize) Ok(tick as usize)
} }

Loading…
Cancel
Save