diff --git a/enclave-runner/src/usercalls/interface.rs b/enclave-runner/src/usercalls/interface.rs index f1b3711a6..63ac00d70 100644 --- a/enclave-runner/src/usercalls/interface.rs +++ b/enclave-runner/src/usercalls/interface.rs @@ -180,6 +180,8 @@ impl<'a> Drop for OutputBuffer<'a> { if let Some(buf) = self.data.take() { self.buf.len = buf.len(); self.buf.data = Box::into_raw(buf) as _; + } else { + self.buf.len = 0; } } } diff --git a/enclave-runner/src/usercalls/mod.rs b/enclave-runner/src/usercalls/mod.rs index 290ff739f..f00a74b5e 100644 --- a/enclave-runner/src/usercalls/mod.rs +++ b/enclave-runner/src/usercalls/mod.rs @@ -893,6 +893,9 @@ impl RunningTcs { unsafe { let layout = Layout::from_size_align(size, alignment).map_err(|_| IoErrorKind::InvalidInput)?; + if size == 0 { + return Ok(()) + } Ok(System.dealloc(ptr, layout)) } } diff --git a/fortanix-sgx-abi/src/lib.rs b/fortanix-sgx-abi/src/lib.rs index 4f82bcf66..07405df41 100644 --- a/fortanix-sgx-abi/src/lib.rs +++ b/fortanix-sgx-abi/src/lib.rs @@ -169,11 +169,14 @@ pub mod entry { /// An arbitrary-sized buffer of bytes in userspace, allocated by userspace. /// /// This type is used when userspace may return arbitrary-sized data from a -/// usercall. When reading from the buffer, the enclave must ensure the entire -/// buffer is in the user memory range. Once the enclave is done with the -/// buffer, it should deallocate the buffer buffer by calling +/// usercall. When reading from the buffer, if `len` is not `0`, the enclave +/// must ensure the entire buffer is in the user memory range. Once the enclave +/// is done with the buffer, it should deallocate the buffer buffer by calling /// [`free`]`(data, len, 1)`. /// +/// If `len` is `0`, the enclave should ignore `data`. It should not call +/// `free`. +/// /// [`free`]: ./struct.Usercalls.html#method.launch_thread #[repr(C)] #[derive(Copy, Clone)] @@ -565,6 +568,8 @@ impl Usercalls { /// `align`. If succesful, a pointer to this memory will be returned. The /// enclave must check the pointer is correctly aligned and that the entire /// range of memory pointed to is outside the enclave. + /// + /// It is an error to call this function with `size` equal to `0`. pub fn alloc(size: usize, alignment: usize) -> (Result, *mut u8) { unimplemented!() } /// Free user memory. @@ -573,6 +578,8 @@ impl Usercalls { /// `ptr` must have previously been returned by a usercall. The `size` and /// `alignment` specified must exactly match what was allocated. This /// function must be called exactly once for each user memory buffer. + /// + /// Calling this function with `size` equal to `0` is a no-op. pub fn free(ptr: *mut u8, size: usize, alignment: usize) { unimplemented!() } }