Fix two bugs of ioctl
1. Add length of the argument to the ioctl ocall to guard sgx sdk to do the copy. 2. Handle non-zero return value of ioctl.
This commit is contained in:
parent
6d72e10fc1
commit
9252a1a993
@ -162,5 +162,12 @@ enclave {
|
|||||||
|
|
||||||
void occlum_ocall_print_log(uint32_t level, [in, string] const char* msg);
|
void occlum_ocall_print_log(uint32_t level, [in, string] const char* msg);
|
||||||
void occlum_ocall_flush_log(void);
|
void occlum_ocall_flush_log(void);
|
||||||
|
|
||||||
|
int occlum_ocall_ioctl(
|
||||||
|
int fd,
|
||||||
|
int request,
|
||||||
|
[in, out, size=len] void *arg,
|
||||||
|
size_t len
|
||||||
|
) propagate_errno;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ use util::sgx::*;
|
|||||||
pub struct DevSgx;
|
pub struct DevSgx;
|
||||||
|
|
||||||
impl File for DevSgx {
|
impl File for DevSgx {
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
let nonbuiltin_cmd = match cmd {
|
let nonbuiltin_cmd = match cmd {
|
||||||
IoctlCmd::NonBuiltin(nonbuiltin_cmd) => nonbuiltin_cmd,
|
IoctlCmd::NonBuiltin(nonbuiltin_cmd) => nonbuiltin_cmd,
|
||||||
_ => return_errno!(EINVAL, "unknown ioctl cmd for /dev/sgx"),
|
_ => return_errno!(EINVAL, "unknown ioctl cmd for /dev/sgx"),
|
||||||
@ -92,7 +92,7 @@ impl File for DevSgx {
|
|||||||
return_errno!(ENOSYS, "unknown ioctl cmd for /dev/sgx");
|
return_errno!(ENOSYS, "unknown ioctl cmd for /dev/sgx");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -67,7 +67,7 @@ pub trait File: Debug + Sync + Send + Any {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
return_op_unsupported_error!("ioctl")
|
return_op_unsupported_error!("ioctl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,15 @@ macro_rules! impl_ioctl_cmds {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn arg_len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
IoctlCmd::$ioctl_name(_) => get_arg_len!($($ioctl_type_tt)*),
|
||||||
|
)*
|
||||||
|
IoctlCmd::NonBuiltin(inner) => inner.arg_len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cmd_num(&self) -> u32 {
|
pub fn cmd_num(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
@ -142,6 +151,18 @@ macro_rules! get_arg_type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! get_arg_len {
|
||||||
|
(()) => {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
(mut $type: ty) => {
|
||||||
|
std::mem::size_of::<$type>()
|
||||||
|
};
|
||||||
|
($type: ty) => {
|
||||||
|
std::mem::size_of::<$type>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! get_arg {
|
macro_rules! get_arg {
|
||||||
((), $arg_ptr: ident) => {
|
((), $arg_ptr: ident) => {
|
||||||
()
|
()
|
||||||
|
@ -45,7 +45,7 @@ impl_ioctl_nums_and_cmds! {
|
|||||||
/// Sanity checks are mostly useful when the argument values are returned from
|
/// Sanity checks are mostly useful when the argument values are returned from
|
||||||
/// the untrusted host OS.
|
/// the untrusted host OS.
|
||||||
impl<'a> IoctlCmd<'a> {
|
impl<'a> IoctlCmd<'a> {
|
||||||
pub fn validate_arg_val(&self) -> Result<()> {
|
pub fn validate_arg_and_ret_vals(&self, ret: i32) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
IoctlCmd::TIOCGWINSZ(winsize_ref) => {
|
IoctlCmd::TIOCGWINSZ(winsize_ref) => {
|
||||||
// ws_row and ws_col are usually not zeros
|
// ws_row and ws_col are usually not zeros
|
||||||
@ -63,12 +63,27 @@ impl<'a> IoctlCmd<'a> {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Current ioctl commands all return zero
|
||||||
|
if ret != 0 {
|
||||||
|
return_errno!(EINVAL, "return value should be zero");
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_ioctl(fd: FileDesc, cmd: &mut IoctlCmd) -> Result<()> {
|
pub fn do_ioctl(fd: FileDesc, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
debug!("ioctl: fd: {}, cmd: {:?}", fd, cmd);
|
debug!("ioctl: fd: {}, cmd: {:?}", fd, cmd);
|
||||||
let file_ref = current!().file(fd)?;
|
let file_ref = current!().file(fd)?;
|
||||||
file_ref.ioctl(cmd)
|
file_ref.ioctl(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn occlum_ocall_ioctl(
|
||||||
|
ret: *mut i32,
|
||||||
|
fd: c_int,
|
||||||
|
request: c_int,
|
||||||
|
arg: *mut c_void,
|
||||||
|
len: size_t,
|
||||||
|
) -> sgx_status_t;
|
||||||
|
}
|
||||||
|
@ -65,6 +65,10 @@ impl<'a> NonBuiltinIoctlCmd<'a> {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(std::ptr::null(), |arg_slice| arg_slice.as_ptr())
|
.map_or(std::ptr::null(), |arg_slice| arg_slice.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn arg_len(&self) -> usize {
|
||||||
|
self.cmd_num.arg_size()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
@ -13,7 +13,9 @@ pub use self::fcntl::{do_fcntl, FcntlCmd};
|
|||||||
pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags};
|
pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags};
|
||||||
pub use self::flock::{Flock, FlockType};
|
pub use self::flock::{Flock, FlockType};
|
||||||
pub use self::fsync::{do_fdatasync, do_fsync};
|
pub use self::fsync::{do_fdatasync, do_fsync};
|
||||||
pub use self::ioctl::{do_ioctl, IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum};
|
pub use self::ioctl::{
|
||||||
|
do_ioctl, occlum_ocall_ioctl, IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum,
|
||||||
|
};
|
||||||
pub use self::link::do_link;
|
pub use self::link::do_link;
|
||||||
pub use self::lseek::do_lseek;
|
pub use self::lseek::do_lseek;
|
||||||
pub use self::mkdir::do_mkdir;
|
pub use self::mkdir::do_mkdir;
|
||||||
|
@ -13,7 +13,9 @@ use untrusted::{SliceAsMutPtrAndLen, SliceAsPtrAndLen};
|
|||||||
pub use self::dev_fs::AsDevRandom;
|
pub use self::dev_fs::AsDevRandom;
|
||||||
pub use self::event_file::{AsEvent, EventFile};
|
pub use self::event_file::{AsEvent, EventFile};
|
||||||
pub use self::file::{File, FileRef};
|
pub use self::file::{File, FileRef};
|
||||||
pub use self::file_ops::{AccessMode, CreationFlags, FileMode, Stat, StatusFlags};
|
pub use self::file_ops::{
|
||||||
|
occlum_ocall_ioctl, AccessMode, CreationFlags, FileMode, Stat, StatusFlags,
|
||||||
|
};
|
||||||
pub use self::file_ops::{Flock, FlockType};
|
pub use self::file_ops::{Flock, FlockType};
|
||||||
pub use self::file_ops::{IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum};
|
pub use self::file_ops::{IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum};
|
||||||
pub use self::file_table::{FileDesc, FileTable};
|
pub use self::file_table::{FileDesc, FileTable};
|
||||||
|
@ -169,7 +169,7 @@ impl File for StdoutFile {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
let can_delegate_to_host = match cmd {
|
let can_delegate_to_host = match cmd {
|
||||||
IoctlCmd::TIOCGWINSZ(_) => true,
|
IoctlCmd::TIOCGWINSZ(_) => true,
|
||||||
IoctlCmd::TIOCSWINSZ(_) => true,
|
IoctlCmd::TIOCSWINSZ(_) => true,
|
||||||
@ -180,16 +180,24 @@ impl File for StdoutFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cmd_bits = cmd.cmd_num() as c_int;
|
let cmd_bits = cmd.cmd_num() as c_int;
|
||||||
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_int;
|
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_void;
|
||||||
let host_stdout_fd = self.get_host_fd() as i32;
|
let host_stdout_fd = self.get_host_fd() as i32;
|
||||||
try_libc!(libc::ocall::ioctl_arg1(
|
let cmd_arg_len = cmd.arg_len();
|
||||||
host_stdout_fd,
|
let ret = try_libc!({
|
||||||
cmd_bits,
|
let mut retval: i32 = 0;
|
||||||
cmd_arg_ptr
|
let status = occlum_ocall_ioctl(
|
||||||
));
|
&mut retval as *mut i32,
|
||||||
cmd.validate_arg_val()?;
|
host_stdout_fd,
|
||||||
|
cmd_bits,
|
||||||
|
cmd_arg_ptr,
|
||||||
|
cmd_arg_len,
|
||||||
|
);
|
||||||
|
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||||
|
retval
|
||||||
|
});
|
||||||
|
cmd.validate_arg_and_ret_vals(ret)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
@ -310,7 +318,7 @@ impl File for StdinFile {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
let can_delegate_to_host = match cmd {
|
let can_delegate_to_host = match cmd {
|
||||||
IoctlCmd::TIOCGWINSZ(_) => true,
|
IoctlCmd::TIOCGWINSZ(_) => true,
|
||||||
IoctlCmd::TIOCSWINSZ(_) => true,
|
IoctlCmd::TIOCSWINSZ(_) => true,
|
||||||
@ -321,16 +329,24 @@ impl File for StdinFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cmd_bits = cmd.cmd_num() as c_int;
|
let cmd_bits = cmd.cmd_num() as c_int;
|
||||||
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_int;
|
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_void;
|
||||||
let host_stdin_fd = self.get_host_fd() as i32;
|
let host_stdin_fd = self.get_host_fd() as i32;
|
||||||
try_libc!(libc::ocall::ioctl_arg1(
|
let cmd_arg_len = cmd.arg_len();
|
||||||
host_stdin_fd,
|
let ret = try_libc!({
|
||||||
cmd_bits,
|
let mut retval: i32 = 0;
|
||||||
cmd_arg_ptr
|
let status = occlum_ocall_ioctl(
|
||||||
));
|
&mut retval as *mut i32,
|
||||||
cmd.validate_arg_val()?;
|
host_stdin_fd,
|
||||||
|
cmd_bits,
|
||||||
|
cmd_arg_ptr,
|
||||||
|
cmd_arg_len,
|
||||||
|
);
|
||||||
|
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||||
|
retval
|
||||||
|
});
|
||||||
|
cmd.validate_arg_and_ret_vals(ret)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -3,7 +3,7 @@ use super::*;
|
|||||||
mod recv;
|
mod recv;
|
||||||
mod send;
|
mod send;
|
||||||
|
|
||||||
use fs::{AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags};
|
use fs::{occlum_ocall_ioctl, AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
|
|
||||||
@ -106,13 +106,24 @@ impl File for SocketFile {
|
|||||||
return_errno!(ESPIPE, "Socket does not support seek")
|
return_errno!(ESPIPE, "Socket does not support seek")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
let cmd_num = cmd.cmd_num() as c_int;
|
let cmd_num = cmd.cmd_num() as c_int;
|
||||||
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_int;
|
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_void;
|
||||||
try_libc!(libc::ocall::ioctl_arg1(self.fd(), cmd_num, cmd_arg_ptr));
|
let ret = try_libc!({
|
||||||
|
let mut retval: i32 = 0;
|
||||||
|
let status = occlum_ocall_ioctl(
|
||||||
|
&mut retval as *mut i32,
|
||||||
|
self.fd(),
|
||||||
|
cmd_num,
|
||||||
|
cmd_arg_ptr,
|
||||||
|
cmd.arg_len(),
|
||||||
|
);
|
||||||
|
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||||
|
retval
|
||||||
|
});
|
||||||
// FIXME: add sanity checks for results returned for socket-related ioctls
|
// FIXME: add sanity checks for results returned for socket-related ioctls
|
||||||
cmd.validate_arg_val()?;
|
cmd.validate_arg_and_ret_vals(ret)?;
|
||||||
Ok(())
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_access_mode(&self) -> Result<AccessMode> {
|
fn get_access_mode(&self) -> Result<AccessMode> {
|
||||||
|
@ -80,7 +80,7 @@ impl File for UnixSocketFile {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
inner.ioctl(cmd)
|
inner.ioctl(cmd)
|
||||||
}
|
}
|
||||||
@ -260,7 +260,7 @@ impl UnixSocket {
|
|||||||
Ok((r, w, false))
|
Ok((r, w, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<()> {
|
pub fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||||
match cmd {
|
match cmd {
|
||||||
IoctlCmd::FIONREAD(arg) => {
|
IoctlCmd::FIONREAD(arg) => {
|
||||||
let bytes_to_read = self
|
let bytes_to_read = self
|
||||||
@ -272,7 +272,7 @@ impl UnixSocket {
|
|||||||
}
|
}
|
||||||
_ => return_errno!(EINVAL, "unknown ioctl cmd for unix socket"),
|
_ => return_errno!(EINVAL, "unknown ioctl cmd for unix socket"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn channel(&self) -> Result<&Channel> {
|
fn channel(&self) -> Result<&Channel> {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include "ocalls.h"
|
#include "ocalls.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
void occlum_ocall_sync(void) {
|
void occlum_ocall_sync(void) {
|
||||||
sync();
|
sync();
|
||||||
@ -9,3 +11,13 @@ void occlum_ocall_sync(void) {
|
|||||||
int occlum_ocall_eventfd(unsigned int initval, int flags) {
|
int occlum_ocall_eventfd(unsigned int initval, int flags) {
|
||||||
return eventfd(initval, flags);
|
return eventfd(initval, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int occlum_ocall_ioctl(int fd, int request, void *arg, size_t len) {
|
||||||
|
if (((arg == NULL) ^ (len == 0)) == 1) {
|
||||||
|
printf("invalid ioctl parameters\n");
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ioctl(fd, request, arg);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user