mirror of
https://github.com/rcore-os/rCore.git
synced 2025-01-19 01:07:05 +04:00
convert user ptr to reference on check
This commit is contained in:
parent
894c411e4e
commit
58271c7c8a
@ -205,29 +205,55 @@ impl<T: InactivePageTable> MemorySet<T> {
|
||||
}
|
||||
}
|
||||
/// Check the pointer is within the readable memory
|
||||
pub fn check_read_ptr<S>(&self, ptr: *const S) -> VMResult<()> {
|
||||
self.check_read_array(ptr, 1)
|
||||
pub unsafe fn check_read_ptr<S>(&self, ptr: *const S) -> VMResult<&'static S> {
|
||||
self.check_read_array(ptr, 1).map(|s| &s[0])
|
||||
}
|
||||
/// Check the pointer is within the writable memory
|
||||
pub fn check_write_ptr<S>(&self, ptr: *mut S) -> VMResult<()> {
|
||||
self.check_write_array(ptr, 1)
|
||||
pub unsafe fn check_write_ptr<S>(&self, ptr: *mut S) -> VMResult<&'static mut S> {
|
||||
self.check_write_array(ptr, 1).map(|s| &mut s[0])
|
||||
}
|
||||
/// 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
|
||||
.iter()
|
||||
.find(|area| area.check_read_array(ptr, count))
|
||||
.map(|_| ())
|
||||
.map(|_| core::slice::from_raw_parts(ptr, count))
|
||||
.ok_or(VMError::InvalidPtr)
|
||||
}
|
||||
/// 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
|
||||
.iter()
|
||||
.find(|area| area.check_write_array(ptr, count))
|
||||
.map(|_| ())
|
||||
.map(|_| core::slice::from_raw_parts_mut(ptr, count))
|
||||
.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.
|
||||
/// 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.
|
||||
pub fn sys_get_paddr(vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult {
|
||||
let mut proc = process();
|
||||
proc.vm.check_read_array(vaddrs, count)?;
|
||||
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) };
|
||||
let vaddrs = unsafe { proc.vm.check_read_array(vaddrs, count)? };
|
||||
let paddrs = unsafe { proc.vm.check_write_array(paddrs, count)? };
|
||||
for i in 0..count {
|
||||
let paddr = proc.vm.translate(vaddrs[i] as usize).unwrap_or(0);
|
||||
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
|
||||
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
|
||||
}
|
||||
proc.vm.check_write_array(base, len)?;
|
||||
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
||||
let slice = unsafe { proc.vm.check_write_array(base, len)? };
|
||||
let file_like = proc.get_file_like(fd)?;
|
||||
let len = file_like.read(slice)?;
|
||||
Ok(len)
|
||||
@ -34,8 +33,7 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
|
||||
// we trust pid 0 process
|
||||
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
|
||||
}
|
||||
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 file_like = proc.get_file_like(fd)?;
|
||||
let len = file_like.write(slice)?;
|
||||
Ok(len)
|
||||
@ -47,9 +45,7 @@ pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResu
|
||||
fd, base, len, offset
|
||||
);
|
||||
let mut proc = process();
|
||||
proc.vm.check_write_array(base, len)?;
|
||||
|
||||
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
||||
let slice = unsafe { proc.vm.check_write_array(base, len)? };
|
||||
let len = proc.get_file(fd)?.read_at(offset, slice)?;
|
||||
Ok(len)
|
||||
}
|
||||
@ -60,9 +56,7 @@ pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysR
|
||||
fd, base, len, offset
|
||||
);
|
||||
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 len = proc.get_file(fd)?.write_at(offset, slice)?;
|
||||
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() {
|
||||
1 << 31 // infinity
|
||||
} else {
|
||||
proc.vm.check_read_ptr(timeout)?;
|
||||
unsafe { (*timeout).to_msec() }
|
||||
let timeout = unsafe { proc.vm.check_read_ptr(timeout)? };
|
||||
timeout.to_msec()
|
||||
};
|
||||
drop(proc);
|
||||
|
||||
@ -89,9 +83,8 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu
|
||||
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() {
|
||||
if proc.files.get(&(poll.fd as usize)).is_none() {
|
||||
return Err(SysError::EINVAL);
|
||||
@ -156,9 +149,9 @@ pub fn sys_select(
|
||||
let mut read_fds = FdSet::new(&proc.vm, read, nfds)?;
|
||||
let mut write_fds = FdSet::new(&proc.vm, write, nfds)?;
|
||||
let mut err_fds = FdSet::new(&proc.vm, err, nfds)?;
|
||||
let timeout_msecs = if timeout as usize != 0 {
|
||||
proc.vm.check_read_ptr(timeout)?;
|
||||
unsafe { *timeout }.to_msec()
|
||||
let timeout_msecs = if !timeout.is_null() {
|
||||
let timeout = unsafe { proc.vm.check_read_ptr(timeout)? };
|
||||
timeout.to_msec()
|
||||
} else {
|
||||
// infinity
|
||||
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
|
||||
);
|
||||
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
|
||||
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
|
||||
);
|
||||
}
|
||||
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 len = buf.len();
|
||||
@ -315,12 +308,12 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
|
||||
// we trust pid 0 process
|
||||
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 {
|
||||
return Err(SysError::ERANGE);
|
||||
}
|
||||
unsafe { util::write_cstr(buf, &proc.cwd) }
|
||||
Ok(buf as usize)
|
||||
unsafe { util::write_cstr(buf.as_mut_ptr(), &proc.cwd) }
|
||||
Ok(buf.as_ptr() as usize)
|
||||
}
|
||||
|
||||
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 {
|
||||
info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr);
|
||||
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 stat = Stat::from(file.metadata()?);
|
||||
unsafe {
|
||||
stat_ptr.write(stat);
|
||||
}
|
||||
*stat_ref = stat;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult {
|
||||
let proc = process();
|
||||
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);
|
||||
info!(
|
||||
"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 stat = Stat::from(inode.metadata()?);
|
||||
unsafe {
|
||||
stat_ptr.write(stat);
|
||||
}
|
||||
*stat_ref = stat;
|
||||
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 {
|
||||
let proc = process();
|
||||
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);
|
||||
|
||||
let inode = proc.lookup_inode_at(dirfd, &path, false)?;
|
||||
if inode.metadata()?.type_ == FileType::SymLink {
|
||||
// TODO: recursive link resolution and loop detection
|
||||
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
||||
let len = inode.read_at(0, &mut slice)?;
|
||||
let len = inode.read_at(0, slice)?;
|
||||
Ok(len)
|
||||
} else {
|
||||
Err(SysError::EINVAL)
|
||||
@ -429,13 +417,13 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy
|
||||
fd, buf, buf_size
|
||||
);
|
||||
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 info = file.metadata()?;
|
||||
if info.type_ != FileType::Dir {
|
||||
return Err(SysError::ENOTDIR);
|
||||
}
|
||||
let mut writer = unsafe { DirentBufWriter::new(buf, buf_size) };
|
||||
let mut writer = DirentBufWriter::new(buf);
|
||||
loop {
|
||||
let name = match file.read_entry() {
|
||||
Err(FsError::EntryNotFound) => break,
|
||||
@ -631,7 +619,7 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
|
||||
info!("pipe: fds: {:?}", fds);
|
||||
|
||||
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_fd = proc.add_file(
|
||||
@ -656,10 +644,8 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
|
||||
)),
|
||||
);
|
||||
|
||||
unsafe {
|
||||
fds.write(read_fd as u32);
|
||||
fds.add(1).write(write_fd as u32);
|
||||
}
|
||||
fds[0] = read_fd as u32;
|
||||
fds[1] = write_fd as u32;
|
||||
|
||||
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() {
|
||||
unsafe {
|
||||
(*proc_cell.get()).vm.check_read_ptr(offset_ptr)?;
|
||||
offset_ptr.read()
|
||||
*(*proc_cell.get()).vm.check_read_ptr(offset_ptr)?
|
||||
}
|
||||
} else {
|
||||
in_file.seek(SeekFrom::Current(0))? as usize
|
||||
@ -880,18 +865,20 @@ pub struct LinuxDirent64 {
|
||||
name: [u8; 0],
|
||||
}
|
||||
|
||||
struct DirentBufWriter {
|
||||
struct DirentBufWriter<'a> {
|
||||
buf: &'a mut [u8],
|
||||
ptr: *mut LinuxDirent64,
|
||||
rest_size: usize,
|
||||
written_size: usize,
|
||||
}
|
||||
|
||||
impl DirentBufWriter {
|
||||
unsafe fn new(buf: *mut LinuxDirent64, size: usize) -> Self {
|
||||
impl<'a> DirentBufWriter<'a> {
|
||||
fn new(buf: &'a mut [u8]) -> Self {
|
||||
DirentBufWriter {
|
||||
ptr: buf,
|
||||
rest_size: size,
|
||||
ptr: buf.as_mut_ptr() as *mut LinuxDirent64,
|
||||
rest_size: buf.len(),
|
||||
written_size: 0,
|
||||
buf,
|
||||
}
|
||||
}
|
||||
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]>);
|
||||
|
||||
impl IoVecs {
|
||||
pub fn check_and_new(
|
||||
pub unsafe fn check_and_new(
|
||||
iov_ptr: *const IoVec,
|
||||
iov_count: usize,
|
||||
vm: &MemorySet,
|
||||
readv: bool,
|
||||
) -> Result<Self, SysError> {
|
||||
vm.check_read_array(iov_ptr, iov_count)?;
|
||||
let iovs = unsafe { slice::from_raw_parts(iov_ptr, iov_count) }.to_vec();
|
||||
let iovs = vm.check_read_array(iov_ptr, iov_count)?.to_vec();
|
||||
// check all bufs in iov
|
||||
for iov in iovs.iter() {
|
||||
if iov.len > 0 {
|
||||
// skip empty iov
|
||||
if readv {
|
||||
vm.check_write_array(iov.base, iov.len)?;
|
||||
} else {
|
||||
vm.check_read_array(iov.base, iov.len)?;
|
||||
}
|
||||
// skip empty iov
|
||||
if iov.len == 0 {
|
||||
continue;
|
||||
}
|
||||
if readv {
|
||||
vm.check_write_array(iov.base, iov.len)?;
|
||||
} else {
|
||||
vm.check_read_array(iov.base, iov.len)?;
|
||||
}
|
||||
}
|
||||
let slices = iovs
|
||||
.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();
|
||||
Ok(IoVecs(slices))
|
||||
}
|
||||
@ -1342,11 +1329,10 @@ impl FdSet {
|
||||
})
|
||||
} else {
|
||||
let len = (nfds + FD_PER_ITEM - 1) / FD_PER_ITEM;
|
||||
vm.check_write_array(addr, len)?;
|
||||
if len > MAX_FDSET_SIZE {
|
||||
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();
|
||||
|
||||
// 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 {
|
||||
info!("sched_uname: buf: {:?}", buf);
|
||||
info!("uname: buf: {:?}", buf);
|
||||
|
||||
let offset = 65;
|
||||
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
|
||||
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() {
|
||||
unsafe {
|
||||
util::write_cstr(buf.add(i * offset), &strings[i]);
|
||||
util::write_cstr(&mut buf[i * offset], &strings[i]);
|
||||
}
|
||||
}
|
||||
Ok(0)
|
||||
@ -39,22 +39,20 @@ pub fn sys_sched_getaffinity(pid: usize, size: usize, mask: *mut u32) -> SysResu
|
||||
pid, size, mask
|
||||
);
|
||||
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.
|
||||
// so just set it.
|
||||
unsafe {
|
||||
*mask = 0b1111;
|
||||
}
|
||||
mask[0] = 0b1111;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sys_sysinfo(sys_info: *mut SysInfo) -> SysResult {
|
||||
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();
|
||||
unsafe { *sys_info = sysinfo };
|
||||
*sys_info = sysinfo;
|
||||
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 {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
process().vm.check_write_ptr(uaddr as *mut AtomicI32)?;
|
||||
let atomic = unsafe { &mut *(uaddr as *mut AtomicI32) };
|
||||
let atomic = unsafe { process().vm.check_write_ptr(uaddr as *mut AtomicI32)? };
|
||||
let _timeout = if timeout.is_null() {
|
||||
None
|
||||
} else {
|
||||
process().vm.check_read_ptr(timeout)?;
|
||||
Some(unsafe { *timeout })
|
||||
Some(unsafe { *process().vm.check_read_ptr(timeout)? })
|
||||
};
|
||||
|
||||
const OP_WAIT: u32 = 0;
|
||||
@ -156,38 +152,32 @@ pub fn sys_prlimit64(
|
||||
match resource {
|
||||
RLIMIT_STACK => {
|
||||
if !old_limit.is_null() {
|
||||
proc.vm.check_write_ptr(old_limit)?;
|
||||
unsafe {
|
||||
*old_limit = RLimit {
|
||||
cur: USER_STACK_SIZE as u64,
|
||||
max: USER_STACK_SIZE as u64,
|
||||
};
|
||||
}
|
||||
let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? };
|
||||
*old_limit = RLimit {
|
||||
cur: USER_STACK_SIZE as u64,
|
||||
max: USER_STACK_SIZE as u64,
|
||||
};
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
RLIMIT_NOFILE => {
|
||||
if !old_limit.is_null() {
|
||||
proc.vm.check_write_ptr(old_limit)?;
|
||||
unsafe {
|
||||
*old_limit = RLimit {
|
||||
cur: 1024,
|
||||
max: 1024,
|
||||
};
|
||||
}
|
||||
let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? };
|
||||
*old_limit = RLimit {
|
||||
cur: 1024,
|
||||
max: 1024,
|
||||
};
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
RLIMIT_RSS | RLIMIT_AS => {
|
||||
if !old_limit.is_null() {
|
||||
proc.vm.check_write_ptr(old_limit)?;
|
||||
unsafe {
|
||||
// 1GB
|
||||
*old_limit = RLimit {
|
||||
cur: 1024 * 1024 * 1024,
|
||||
max: 1024 * 1024 * 1024,
|
||||
};
|
||||
}
|
||||
let old_limit = unsafe { proc.vm.check_write_ptr(old_limit)? };
|
||||
// 1GB
|
||||
*old_limit = RLimit {
|
||||
cur: 1024 * 1024 * 1024,
|
||||
max: 1024 * 1024 * 1024,
|
||||
};
|
||||
}
|
||||
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);
|
||||
let mut proc = process();
|
||||
proc.vm.check_write_array(buf, len)?;
|
||||
let slice = unsafe { slice::from_raw_parts_mut(buf, len) };
|
||||
let slice = unsafe { proc.vm.check_write_array(buf, len)? };
|
||||
let mut i=0;
|
||||
for elm in slice {
|
||||
unsafe{ *elm=i+ crate::trap::TICK as u8;}
|
||||
|
@ -55,8 +55,7 @@ pub fn sys_setsockopt(
|
||||
fd, level, optname
|
||||
);
|
||||
let mut proc = process();
|
||||
proc.vm.check_read_array(optval, optlen)?;
|
||||
let data = unsafe { slice::from_raw_parts(optval, optlen) };
|
||||
let data = unsafe { proc.vm.check_read_array(optval, optlen)? };
|
||||
let socket = proc.get_socket(fd)?;
|
||||
socket.setsockopt(level, optname, data)
|
||||
}
|
||||
@ -73,23 +72,19 @@ pub fn sys_getsockopt(
|
||||
fd, level, optname, optval, optlen
|
||||
);
|
||||
let proc = process();
|
||||
proc.vm.check_write_ptr(optlen)?;
|
||||
let optlen = unsafe { proc.vm.check_write_ptr(optlen)? };
|
||||
match level {
|
||||
SOL_SOCKET => match optname {
|
||||
SO_SNDBUF => {
|
||||
proc.vm.check_write_array(optval, 4)?;
|
||||
unsafe {
|
||||
*(optval as *mut u32) = crate::net::TCP_SENDBUF as u32;
|
||||
*optlen = 4;
|
||||
}
|
||||
let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? };
|
||||
*optval = crate::net::TCP_SENDBUF as u32;
|
||||
*optlen = 4;
|
||||
Ok(0)
|
||||
}
|
||||
SO_RCVBUF => {
|
||||
proc.vm.check_write_array(optval, 4)?;
|
||||
unsafe {
|
||||
*(optval as *mut u32) = crate::net::TCP_RECVBUF as u32;
|
||||
*optlen = 4;
|
||||
}
|
||||
let optval = unsafe { proc.vm.check_write_ptr(optval as *mut u32)? };
|
||||
*optval = crate::net::TCP_RECVBUF as u32;
|
||||
*optlen = 4;
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(SysError::ENOPROTOOPT),
|
||||
@ -129,9 +124,8 @@ pub fn sys_sendto(
|
||||
);
|
||||
|
||||
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() {
|
||||
None
|
||||
} else {
|
||||
@ -157,10 +151,9 @@ pub fn sys_recvfrom(
|
||||
);
|
||||
|
||||
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 mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
||||
let (result, endpoint) = socket.read(&mut slice);
|
||||
|
||||
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 {
|
||||
info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags);
|
||||
let mut proc = process();
|
||||
proc.vm.check_read_ptr(msg)?;
|
||||
let hdr = unsafe { &mut *msg };
|
||||
let mut iovs = IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)?;
|
||||
let hdr = unsafe { proc.vm.check_write_ptr(msg)? };
|
||||
let mut iovs = unsafe { IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)? };
|
||||
|
||||
let mut buf = iovs.new_buf(true);
|
||||
let socket = proc.get_socket(fd)?;
|
||||
@ -406,16 +398,16 @@ fn sockaddr_to_endpoint(
|
||||
if len < size_of::<u16>() {
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
proc.vm.check_read_array(addr as *const u8, len)?;
|
||||
let addr = unsafe { proc.vm.check_read_ptr(addr)? };
|
||||
unsafe {
|
||||
match AddressFamily::from((*addr).family) {
|
||||
match AddressFamily::from(addr.family) {
|
||||
AddressFamily::Internet => {
|
||||
if len < size_of::<SockAddrIn>() {
|
||||
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(
|
||||
&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()))
|
||||
}
|
||||
@ -425,7 +417,7 @@ fn sockaddr_to_endpoint(
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
|
||||
(*addr).addr_ll.sll_ifindex as usize,
|
||||
addr.addr_ll.sll_ifindex as usize,
|
||||
)))
|
||||
}
|
||||
AddressFamily::Netlink => {
|
||||
@ -433,8 +425,8 @@ fn sockaddr_to_endpoint(
|
||||
return Err(SysError::EINVAL);
|
||||
}
|
||||
Ok(Endpoint::Netlink(NetlinkEndpoint::new(
|
||||
(*addr).addr_nl.nl_pid,
|
||||
(*addr).addr_nl.nl_groups,
|
||||
addr.addr_nl.nl_pid,
|
||||
addr.addr_nl.nl_groups,
|
||||
)))
|
||||
}
|
||||
_ => Err(SysError::EINVAL),
|
||||
@ -456,7 +448,7 @@ impl SockAddr {
|
||||
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 full_len = match AddressFamily::from(self.family) {
|
||||
AddressFamily::Internet => size_of::<SockAddrIn>(),
|
||||
@ -468,12 +460,11 @@ impl SockAddr {
|
||||
|
||||
let written_len = min(max_addr_len, full_len);
|
||||
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 target = slice::from_raw_parts_mut(addr as *mut u8, written_len);
|
||||
target.copy_from_slice(source);
|
||||
}
|
||||
addr_len.write(full_len as u32);
|
||||
*addr_len = full_len as u32;
|
||||
return Ok(0);
|
||||
}
|
||||
}
|
||||
|
@ -43,19 +43,14 @@ pub fn sys_clone(
|
||||
);
|
||||
//return Err(SysError::ENOSYS);
|
||||
}
|
||||
{
|
||||
let proc = process();
|
||||
proc.vm.check_write_ptr(parent_tid)?;
|
||||
proc.vm.check_write_ptr(child_tid)?;
|
||||
}
|
||||
let parent_tid_ref = unsafe { process().vm.check_write_ptr(parent_tid)? };
|
||||
let child_tid_ref = unsafe { process().vm.check_write_ptr(child_tid)? };
|
||||
let new_thread = current_thread().clone(tf, newsp, newtls, child_tid as usize);
|
||||
// FIXME: parent pid
|
||||
let tid = processor().manager().add(new_thread);
|
||||
info!("clone: {} -> {}", thread::current().id(), tid);
|
||||
unsafe {
|
||||
parent_tid.write(tid as u32);
|
||||
child_tid.write(tid as u32);
|
||||
}
|
||||
*parent_tid_ref = tid as u32;
|
||||
*child_tid_ref = tid as u32;
|
||||
Ok(tid)
|
||||
}
|
||||
|
||||
@ -63,9 +58,11 @@ pub fn sys_clone(
|
||||
/// Return the PID. Store exit code to `wstatus` if it's not null.
|
||||
pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
|
||||
//info!("wait4: pid: {}, code: {:?}", pid, wstatus);
|
||||
if !wstatus.is_null() {
|
||||
process().vm.check_write_ptr(wstatus)?;
|
||||
}
|
||||
let wstatus = if !wstatus.is_null() {
|
||||
Some(unsafe { process().vm.check_write_ptr(wstatus)? })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
#[derive(Debug)]
|
||||
enum WaitFor {
|
||||
AnyChild,
|
||||
@ -90,10 +87,8 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
|
||||
// if found, return
|
||||
if let Some((pid, exit_code)) = find {
|
||||
proc.child_exit_code.remove(&pid);
|
||||
if !wstatus.is_null() {
|
||||
unsafe {
|
||||
wstatus.write(exit_code as i32);
|
||||
}
|
||||
if let Some(wstatus) = wstatus {
|
||||
*wstatus = exit_code as i32;
|
||||
}
|
||||
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(
|
||||
name: *const u8,
|
||||
path: *const u8,
|
||||
argv: *const *const u8,
|
||||
envp: *const *const u8,
|
||||
tf: &mut TrapFrame,
|
||||
) -> SysResult {
|
||||
info!("exec:BEG: name: {:?}, argv: {:?}, envp: {:?}", name, argv, envp);
|
||||
info!(
|
||||
"exec:BEG: path: {:?}, argv: {:?}, envp: {:?}",
|
||||
path, argv, envp
|
||||
);
|
||||
let proc = process();
|
||||
let exec_name = if name.is_null() {
|
||||
String::from("")
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
|
||||
let args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? };
|
||||
let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? };
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
info!(
|
||||
"exec:STEP2: exec_name: {:?}, name{:?}, args: {:?}, envp: {:?}",
|
||||
exec_name, name, args, envs
|
||||
"exec:STEP2: path: {:?}, args: {:?}, envs: {:?}",
|
||||
path, args, envs
|
||||
);
|
||||
|
||||
// Read program file
|
||||
//let path = args[0].as_str();
|
||||
let exec_path = exec_name.as_str();
|
||||
let inode = proc.lookup_inode(exec_path)?;
|
||||
let inode = proc.lookup_inode(&path)?;
|
||||
let buf = inode.read_as_vec()?;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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(current_thread(), &mut *thread);
|
||||
|
||||
info!(
|
||||
"exec:END: exec_name: {:?}",
|
||||
exec_name
|
||||
);
|
||||
info!("exec:END: path: {:?}", path);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -337,8 +309,7 @@ pub fn sys_exit_group(exit_code: usize) -> ! {
|
||||
}
|
||||
|
||||
pub fn sys_nanosleep(req: *const TimeSpec) -> SysResult {
|
||||
process().vm.check_read_ptr(req)?;
|
||||
let time = unsafe { req.read() };
|
||||
let time = unsafe { *process().vm.check_read_ptr(req)? };
|
||||
info!("nanosleep: time: {:#?}", time);
|
||||
// TODO: handle spurious wakeup
|
||||
thread::sleep(time.to_duration());
|
||||
|
@ -83,12 +83,10 @@ pub fn sys_gettimeofday(tv: *mut TimeVal, tz: *const u8) -> SysResult {
|
||||
}
|
||||
|
||||
let proc = process();
|
||||
proc.vm.check_write_ptr(tv)?;
|
||||
let tv = unsafe { proc.vm.check_write_ptr(tv)? };
|
||||
|
||||
let timeval = TimeVal::get_epoch();
|
||||
unsafe {
|
||||
*tv = timeval;
|
||||
}
|
||||
*tv = timeval;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -96,12 +94,10 @@ pub fn sys_clock_gettime(clock: usize, ts: *mut TimeSpec) -> SysResult {
|
||||
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
|
||||
|
||||
let proc = process();
|
||||
proc.vm.check_write_ptr(ts)?;
|
||||
let ts = unsafe { proc.vm.check_write_ptr(ts)? };
|
||||
|
||||
let timespec = TimeSpec::get_epoch();
|
||||
unsafe {
|
||||
*ts = timespec;
|
||||
}
|
||||
*ts = timespec;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -109,10 +105,8 @@ pub fn sys_time(time: *mut u64) -> SysResult {
|
||||
let sec = get_epoch_usec() / USEC_PER_SEC;
|
||||
if time as usize != 0 {
|
||||
let proc = process();
|
||||
proc.vm.check_write_ptr(time)?;
|
||||
unsafe {
|
||||
time.write(sec as u64);
|
||||
}
|
||||
let time = unsafe { proc.vm.check_write_ptr(time)? };
|
||||
*time = sec as u64;
|
||||
}
|
||||
Ok(sec as usize)
|
||||
}
|
||||
@ -127,7 +121,7 @@ pub struct RUsage {
|
||||
pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
|
||||
info!("getrusage: who: {}, rusage: {:?}", who, rusage);
|
||||
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 = 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,
|
||||
},
|
||||
};
|
||||
unsafe { *rusage = new_rusage };
|
||||
*rusage = new_rusage;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -159,7 +153,7 @@ pub struct Tms {
|
||||
pub fn sys_times(buf: *mut Tms) -> SysResult {
|
||||
info!("times: buf: {:?}", buf);
|
||||
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 = unsafe { crate::trap::TICK as u64 };
|
||||
@ -171,6 +165,6 @@ pub fn sys_times(buf: *mut Tms) -> SysResult {
|
||||
tms_cstime: 0,
|
||||
};
|
||||
|
||||
unsafe { *buf = new_buf };
|
||||
*buf = new_buf;
|
||||
Ok(tick as usize)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user