Skip to content

Commit

Permalink
Add the writev() syscall handler
Browse files Browse the repository at this point in the history
  • Loading branch information
lkatalin committed Mar 31, 2020
1 parent 5f1c7d5 commit dcecb58
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions enarx-keep-sgx-shim/src/event.rs
Expand Up @@ -26,6 +26,7 @@ pub extern "C" fn event(
SysCall::READ => h.read(),
SysCall::READV => h.readv(),
SysCall::WRITE => h.write(),
SysCall::WRITEV => h.writev(),
SysCall::GETUID => h.getuid(),
SysCall::EXIT => h.exit(None),
_ => h.exit(254),
Expand Down
72 changes: 72 additions & 0 deletions enarx-keep-sgx-shim/src/handler.rs
Expand Up @@ -257,4 +257,76 @@ impl<'a> Handler<'a> {
unsafe { self.ufree(map.as_ptr() as *mut u8, size as u64) };
ret
}

/// Do a writev() syscall
pub fn writev(&mut self) -> u64 {
let fd = self.aex.gpr.rdi;
let trusted = unsafe {
from_raw_parts_mut(
self.aex.gpr.rsi as *mut Iovec<u8>,
self.aex.gpr.rdx as usize,
)
};

// Add up total size of buffers and size of iovec array.
let bufsize = trusted.iter().fold(0, |a, e| a + e.size);
let iovecsize = size_of::<Iovec<u8>>() * trusted.len();
let size = bufsize + iovecsize;

// Allocate some unencrypted memory.
let map = match self.ualloc(size as u64) {
Err(errno) => return errno.into_syscall(),
Ok(map) => unsafe { from_raw_parts_mut(map, size as usize) },
};

// Split allocated memory into that used by the iovec struct array and that used by its buffers.
let (uiovec, ubuffer) = map.split_at_mut(iovecsize);

// Convert the prefix from a byte slice into an iovec slice.
let (_, untrusted, _) = unsafe { uiovec.align_to_mut::<Iovec<u8>>() };
if untrusted.len() != trusted.len() {
self.attacked();
}

// Set pointers in unencrypted iovec slice to use the rest of the allocated memory.
// The offset is into the buffer area allocated immediately after the iovec struct
// array, measured in bytes.
let mut offset = 0;
for (t, mut u) in trusted.iter_mut().zip(untrusted.iter_mut()) {
u.base = ubuffer[offset..].as_mut_ptr();
u.size = t.size;
offset += t.size;
}

// Copy the encrypted input into unencrypted memory.
let mut offset = 0;
for (t, u) in trusted.iter_mut().zip(untrusted.iter_mut()) {
if u.base != ubuffer[offset..].as_mut_ptr() || u.size != t.size {
self.attacked();
}

u.as_mut_slice().copy_from_slice(t.as_mut_slice());
offset += t.size;
}

// Do the syscall; replace encrypted memory with unencrypted memory.
let ret = unsafe {
self.syscall(
SysCall::WRITEV,
fd,
untrusted.as_ptr() as _,
untrusted.len() as u64,
0,
0,
0,
)
};

if ErrNo::from_syscall(ret).is_none() && ret > size as u64 {
self.attacked()
}

unsafe { self.ufree(map.as_ptr() as *mut u8, size as u64) };
ret
}
}

0 comments on commit dcecb58

Please sign in to comment.