1
0
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:
WangRunji 2019-04-28 15:55:45 +08:00
parent 894c411e4e
commit 58271c7c8a
7 changed files with 178 additions and 223 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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