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