CVE-2020-15224: Other (NVD-CWE-Other)
value: In Open Enclave before version 0.12.0, an information disclosure vulnerability exists when an enclave application using the syscalls provided by the sockets.edl is loaded by a malicious host application. An attacker who successfully exploited the vulnerability could read privileged data from the enclave heap across trust boundaries. To exploit this vulnerability, an attacker would have to log on to an affected system and run a specially crafted application. The vulnerability would not allow an attacker to elevate user rights directly, but it could be used to obtain information otherwise considered confidential in an enclave, which could be used in further compromises. The issue has been addressed in version 0.12.0 and the current master branch. Users will need to to recompile their applications against the patched libraries to be protected from this vulnerability.
CWE description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
CVSS v3 base score: 6.8
Published: 2020-10-14T19:15Z
Repository: https://github.com/openenclave/openenclave
Language: C
Files changed: include/openenclave/edl/socket.edl, include/openenclave/internal/syscall/fd.h, include/openenclave/internal/syscall/iov.h, include/openenclave/internal/syscall/sys/socket.h, syscall/consolefs.c, syscall/devices/hostepoll/hostepoll.c, syscall/devices/hostfs/hostfs.c, syscall/devices/hostresolver/hostresolver.c, syscall/devices/hostsock/hostsock.c, syscall/iov.c, syscall/socket.c, syscall/syscall.c
Commit date: 2020-10-12 13:40:03 -0700
Commit message: Merge pull request from GHSA-525h-wxcc-f66m

Signed-off-by: Ming-Wei Shih <mishih@microsoft.com>
Diff: diff --git a/include/openenclave/edl/socket.edl b/include/openenclave/edl/socket.edl
index 39b67bc56..824afeb7b 100644
--- a/include/openenclave/edl/socket.edl
+++ b/include/openenclave/edl/socket.edl
@@ -16,12 +16,10 @@
 **==============================================================================
 */
 
 enclave
 {
-
-
     // Headers needed for integral types
     include "openenclave/corelibc/bits/types.h"
     include "openenclave/bits/edl/syscall_types.h"
 
     struct oe_sockaddr
@@ -71,11 +69,11 @@ enclave
             oe_socklen_t addrlen)
             propagate_errno;
 
         oe_host_fd_t oe_syscall_accept_ocall(
             oe_host_fd_t sockfd,
-            [in, out, size=addrlen_in] struct oe_sockaddr* addr,
+            [out, size=addrlen_in] struct oe_sockaddr* addr,
             oe_socklen_t addrlen_in,
             [out, count=1] oe_socklen_t* addrlen_out)
             propagate_errno;
 
         int oe_syscall_bind_ocall(
@@ -115,21 +113,21 @@ enclave
             int flags)
             propagate_errno;
 
         ssize_t oe_syscall_recv_ocall(
             oe_host_fd_t sockfd,
-            [in, out, size=len] void* buf,
+            [out, size=len] void* buf,
             size_t len,
             int flags)
             propagate_errno;
 
         ssize_t oe_syscall_recvfrom_ocall(
             oe_host_fd_t sockfd,
             [out, size=len] void* buf,
             size_t len,
             int flags,
-            [in, out, size=addrlen_in] struct oe_sockaddr* src_addr,
+            [out, size=addrlen_in] struct oe_sockaddr* src_addr,
             oe_socklen_t addrlen_in,
             [out, count=1] oe_socklen_t* addrlen_out)
             propagate_errno;
 
         ssize_t oe_syscall_send_ocall(
@@ -184,18 +182,18 @@ enclave
             [out] oe_socklen_t* optlen_out)
             propagate_errno;
 
         int oe_syscall_getsockname_ocall(
             oe_host_fd_t sockfd,
-            [in, out, size=addrlen_in] struct oe_sockaddr* addr,
+            [out, size=addrlen_in] struct oe_sockaddr* addr,
             oe_socklen_t addrlen_in,
             [out, size=1] oe_socklen_t* addrlen_out)
             propagate_errno;
 
         int oe_syscall_getpeername_ocall(
             oe_host_fd_t sockfd,
-            [in, out, size=addrlen_in] struct oe_sockaddr* addr,
+            [out, size=addrlen_in] struct oe_sockaddr* addr,
             oe_socklen_t addrlen_in,
             [out, size=1] oe_socklen_t* addrlen_out)
             propagate_errno;
 
         int oe_syscall_getaddrinfo_open_ocall(
diff --git a/include/openenclave/internal/syscall/fd.h b/include/openenclave/internal/syscall/fd.h
index 84ce409b9..02be71b95 100644
--- a/include/openenclave/internal/syscall/fd.h
+++ b/include/openenclave/internal/syscall/fd.h
@@ -108,11 +108,11 @@ typedef struct _oe_socket_ops
     ssize_t (*recvfrom)(
         oe_fd_t* sock,
         void* buf,
         size_t len,
         int flags,
-        const struct oe_sockaddr* src_addr,
+        struct oe_sockaddr* src_addr,
         oe_socklen_t* addrlen);
 
     ssize_t (*sendmsg)(oe_fd_t* sock, const struct oe_msghdr* msg, int flags);
 
     ssize_t (*recvmsg)(oe_fd_t* sock, struct oe_msghdr* msg, int flags);
diff --git a/include/openenclave/internal/syscall/iov.h b/include/openenclave/internal/syscall/iov.h
index aed31cb80..670eede28 100644
--- a/include/openenclave/internal/syscall/iov.h
+++ b/include/openenclave/internal/syscall/iov.h
@@ -13,11 +13,12 @@ OE_EXTERNC_BEGIN
 
 int oe_iov_pack(
     const struct oe_iovec* iov,
     int iovcnt,
     void** buf_out,
-    size_t* buf_size_out);
+    size_t* buf_size_out,
+    size_t* data_size_out);
 
 int oe_iov_sync(
     const struct oe_iovec* iov,
     int iovcnt,
     const void* buf_,
diff --git a/include/openenclave/internal/syscall/sys/socket.h b/include/openenclave/internal/syscall/sys/socket.h
index be7078262..173c9b51d 100644
--- a/include/openenclave/internal/syscall/sys/socket.h
+++ b/include/openenclave/internal/syscall/sys/socket.h
@@ -131,10 +131,13 @@ OE_EXTERNC_BEGIN
 #define OE_SO_PRIORITY 12
 #define OE_SO_LINGER 13
 #define OE_SO_BSDCOMPAT 14
 #define OE_SO_REUSEPORT 15
 
+/* Socket message flags. */
+#define OE_MSG_CTRUNC 0x0008
+
 /* oe_shutdown() options. */
 #define OE_SHUT_RD 0
 #define OE_SHUT_WR 1
 #define OE_SHUT_RDWR 2
 
@@ -202,11 +205,11 @@ ssize_t oe_sendto(
 ssize_t oe_recvfrom(
     int sockfd,
     void* buf,
     size_t len,
     int flags,
-    const struct oe_sockaddr* src_addr,
+    struct oe_sockaddr* src_addr,
     oe_socklen_t* addrlen);
 
 ssize_t oe_sendmsg(int sockfd, const struct oe_msghdr* buf, int flags);
 
 ssize_t oe_recvmsg(int sockfd, struct oe_msghdr* buf, int flags);
diff --git a/syscall/consolefs.c b/syscall/consolefs.c
index caf9d0899..2da7c5245 100644
--- a/syscall/consolefs.c
+++ b/syscall/consolefs.c
@@ -203,31 +203,67 @@ done:
 static ssize_t _consolefs_read(oe_fd_t* file_, void* buf, size_t count)
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(file_);
 
-    if (!file)
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html for
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_read_ocall(&ret, file->host_fd, buf, count) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _consolefs_write(oe_fd_t* file_, const void* buf, size_t count)
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(file_);
 
-    if (!file)
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html for
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_write_ocall(&ret, file->host_fd, buf, count) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _consolefs_readv(
@@ -237,25 +273,47 @@ static ssize_t _consolefs_readv(
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!file || !iov || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html for
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_readv_ocall(&ret, file->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
     /* Synchronize data read with IO vector. */
     if (oe_iov_sync(iov, iovcnt, buf, buf_size) != 0)
         OE_RAISE_ERRNO(OE_EINVAL);
 
 done:
@@ -273,25 +331,47 @@ static ssize_t _consolefs_writev(
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!file || (!iov && iovcnt) || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_writev_ocall(&ret, file->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
 
     if (buf)
         oe_free(buf);
 
diff --git a/syscall/devices/hostepoll/hostepoll.c b/syscall/devices/hostepoll/hostepoll.c
index c15124632..546a49f1c 100644
--- a/syscall/devices/hostepoll/hostepoll.c
+++ b/syscall/devices/hostepoll/hostepoll.c
@@ -653,31 +653,70 @@ static ssize_t _epoll_read(oe_fd_t* epoll_, void* buf, size_t count)
     ssize_t ret = -1;
     epoll_t* file = _cast_epoll(epoll_);
 
     oe_errno = 0;
 
-    if (!file)
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html for
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Call the host. */
     if (oe_syscall_read_ocall(&ret, file->host_fd, buf, count) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _epoll_write(oe_fd_t* epoll_, const void* buf, size_t count)
 {
     ssize_t ret = -1;
-    epoll_t* epoll = _cast_epoll(epoll_);
+    epoll_t* file = _cast_epoll(epoll_);
 
     oe_errno = 0;
 
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html for
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
-    if (oe_syscall_write_ocall(&ret, epoll->host_fd, buf, count) != OE_OK)
+    if (oe_syscall_write_ocall(&ret, file->host_fd, buf, count) != OE_OK)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
         OE_RAISE_ERRNO(OE_EINVAL);
+    }
 
 done:
     return ret;
 }
 
@@ -688,25 +727,47 @@ static ssize_t _epoll_readv(
 {
     ssize_t ret = -1;
     epoll_t* file = _cast_epoll(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!file || (iovcnt && !iov) || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html for
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_readv_ocall(&ret, file->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
     /* Synchronize data read with IO vector. */
     if (oe_iov_sync(iov, iovcnt, buf, buf_size) != 0)
         OE_RAISE_ERRNO(OE_EINVAL);
 
 done:
@@ -724,25 +785,47 @@ static ssize_t _epoll_writev(
 {
     ssize_t ret = -1;
     epoll_t* file = _cast_epoll(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!file || (iovcnt && !iov) || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_writev_ocall(&ret, file->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
 
     if (buf)
         oe_free(buf);
 
diff --git a/syscall/devices/hostfs/hostfs.c b/syscall/devices/hostfs/hostfs.c
index 4aac62483..c03c55b5b 100644
--- a/syscall/devices/hostfs/hostfs.c
+++ b/syscall/devices/hostfs/hostfs.c
@@ -536,17 +536,35 @@ done:
 static ssize_t _hostfs_read(oe_fd_t* desc, void* buf, size_t count)
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
 
-    if (!file)
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html for
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Call the host to perform the read(). */
     if (oe_syscall_read_ocall(&ret, file->host_fd, buf, count) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 /* Called by oe_getdents64() to handle the getdents64 system call. */
@@ -596,18 +614,36 @@ done:
 static ssize_t _hostfs_write(oe_fd_t* desc, const void* buf, size_t count)
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
 
-    /* Check parameters. */
-    if (!file || (count && !buf))
+    /*
+     * Check parameters.
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html for
+     * for more detail.
+     */
+    if (!file || (count && !buf) || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Call the host. */
     if (oe_syscall_write_ocall(&ret, file->host_fd, buf, count) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _hostfs_readv(
@@ -617,25 +653,47 @@ static ssize_t _hostfs_readv(
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!file || (!iov && iovcnt) || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html for
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_readv_ocall(&ret, file->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
     /* Synchronize data read with IO vector. */
     if (ret > 0)
     {
         if (oe_iov_sync(iov, iovcnt, buf, buf_size) != 0)
             OE_RAISE_ERRNO(OE_EINVAL);
@@ -656,25 +714,47 @@ static ssize_t _hostfs_writev(
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!file || !iov || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_writev_ocall(&ret, file->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
 
     if (buf)
         oe_free(buf);
 
@@ -754,17 +834,35 @@ static ssize_t _hostfs_pread(
     oe_off_t offset)
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
 
-    if (!file)
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html for
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_pread_ocall(&ret, file->host_fd, buf, count, offset) !=
         OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _hostfs_pwrite(
@@ -774,17 +872,35 @@ static ssize_t _hostfs_pwrite(
     oe_off_t offset)
 {
     ssize_t ret = -1;
     file_t* file = _cast_file(desc);
 
-    if (!file)
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
+     * for more detail.
+     */
+    if (!file || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_pwrite_ocall(&ret, file->host_fd, buf, count, offset) !=
         OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static int _hostfs_close_file(oe_fd_t* desc)
diff --git a/syscall/devices/hostresolver/hostresolver.c b/syscall/devices/hostresolver/hostresolver.c
index 64aeab17a..50c5ff390 100644
--- a/syscall/devices/hostresolver/hostresolver.c
+++ b/syscall/devices/hostresolver/hostresolver.c
@@ -9,10 +9,11 @@
 
 #include <openenclave/internal/syscall/device.h>
 #include <openenclave/internal/syscall/raise.h>
 #include <openenclave/internal/syscall/sys/socket.h>
 #include <openenclave/internal/syscall/netdb.h>
+#include <openenclave/internal/syscall/netinet/in.h>
 #include <openenclave/internal/syscall/resolver.h>
 #include <openenclave/internal/safemath.h>
 #include <openenclave/internal/calls.h>
 #include <openenclave/internal/thread.h>
 #include <openenclave/internal/print.h>
@@ -22,10 +23,18 @@
 #include <openenclave/internal/trace.h>
 #include "syscall_t.h"
 
 #define RESOLV_MAGIC 0x536f636b
 
+/*
+ * The definition of AF_INET6 on Windows (i.e., 23) is different from that of on
+ * Linux (i.e., 10). Given that the internal socket.h conforms to the
+ * implementation of Linux, we explicitly define the Windows-specific value
+ * here for being compatible with a Windows host.
+ */
+#define OE_AF_INET6_WIN 23
+
 // The host resolver is not actually a device in the file descriptor sense.
 typedef struct _resolver
 {
     struct _oe_resolver base;
     uint32_t magic;
@@ -114,31 +123,29 @@ static int _hostresolver_getaddrinfo(
 
     /* Enumerate addrinfo structures. */
     for (;;)
     {
         int retval = 0;
-        size_t canonnamelen = 0;
+        size_t canonnamelen_in = 0;
+        size_t canonnamelen_out = 0;
+        struct oe_addrinfo p_out;
 
-        if (!(p = oe_calloc(1, sizeof(struct oe_addrinfo))))
-        {
-            ret = OE_EAI_MEMORY;
-            goto done;
-        }
+        memset(&p_out, 0, sizeof(struct oe_addrinfo));
 
         /* Determine required size ai_addr and ai_canonname buffers. */
         if (oe_syscall_getaddrinfo_read_ocall(
                 &retval,
                 handle,
-                &p->ai_flags,
-                &p->ai_family,
-                &p->ai_socktype,
-                &p->ai_protocol,
-                p->ai_addrlen,
-                &p->ai_addrlen,
+                &p_out.ai_flags,
+                &p_out.ai_family,
+                &p_out.ai_socktype,
+                &p_out.ai_protocol,
+                p_out.ai_addrlen,
+                &p_out.ai_addrlen,
                 NULL,
-                canonnamelen,
-                &canonnamelen,
+                canonnamelen_in,
+                &canonnamelen_out,
                 NULL) != OE_OK)
         {
             ret = OE_EAI_SYSTEM;
             OE_RAISE_ERRNO(OE_EINVAL);
         }
@@ -152,40 +159,100 @@ static int _hostresolver_getaddrinfo(
         {
             ret = OE_EAI_SYSTEM;
             OE_RAISE_ERRNO(oe_errno);
         }
 
-        if (p->ai_addrlen && !(p->ai_addr = oe_calloc(1, p->ai_addrlen)))
+        /*
+         * Guard the special case that a host sets an arbitrarily large value.
+         * Based on the implementation of MUSL, the ai_addrlen can only be
+         * sizeof(struct sockaddr_in) when the family is AF_INET or
+         * sizeof(struct sockaddr_in6) when the family is AF_INET6.
+         * When the family is AF_UNSPEC, OE checks the ai_addrlen against
+         * sizeof(struct sockaddr_in6) as it should cover AF_INET and
+         * AF_INET6 cases. Besides, OE errors out other family types.
+         */
+        switch (p_out.ai_family)
+        {
+            case OE_AF_INET:
+                if (p_out.ai_addrlen != sizeof(struct oe_sockaddr))
+                {
+                    ret = OE_EAI_FAIL;
+                    goto done;
+                }
+                break;
+            case OE_AF_INET6:
+            case OE_AF_INET6_WIN:
+            case OE_AF_UNSPEC:
+                if (p_out.ai_addrlen != sizeof(struct oe_sockaddr_in6))
+                {
+                    ret = OE_EAI_FAIL;
+                    goto done;
+                }
+                break;
+            default:
+                ret = OE_EAI_FAIL;
+                goto done;
+        }
+
+        if (!(p = oe_calloc(1, sizeof(struct oe_addrinfo))))
+        {
+            ret = OE_EAI_MEMORY;
+            goto done;
+        }
+
+        if (p_out.ai_addrlen && !(p->ai_addr = oe_calloc(1, p_out.ai_addrlen)))
         {
             ret = OE_EAI_MEMORY;
             goto done;
         }
 
-        if (canonnamelen && !(p->ai_canonname = oe_calloc(1, canonnamelen)))
+        if (canonnamelen_out &&
+            !(p->ai_canonname = oe_calloc(1, canonnamelen_out)))
         {
             ret = OE_EAI_MEMORY;
             goto done;
         }
 
+        /* Set canonnamelen_in to the expected length of p->ai_cannonname
+         * returned by the host. */
+        canonnamelen_in = canonnamelen_out;
+
         if (oe_syscall_getaddrinfo_read_ocall(
                 &retval,
                 handle,
                 &p->ai_flags,
                 &p->ai_family,
                 &p->ai_socktype,
                 &p->ai_protocol,
-                p->ai_addrlen,
+                p_out.ai_addrlen,
                 &p->ai_addrlen,
                 p->ai_addr,
-                canonnamelen,
-                &canonnamelen,
+                canonnamelen_in,
+                &canonnamelen_out,
                 p->ai_canonname) != OE_OK)
         {
             ret = OE_EAI_SYSTEM;
             OE_RAISE_ERRNO(OE_EINVAL);
         }
 
+        /*
+         * Lock down the out parameters, which are expected
+         * to be the same as the first invocation. Also,
+         * p->ai_cannonname is expected to be NULL-terminated.
+         */
+        if ((p->ai_flags != p_out.ai_flags) ||
+            (p->ai_family != p_out.ai_family) ||
+            (p->ai_socktype != p_out.ai_socktype) ||
+            (p->ai_protocol != p_out.ai_protocol) ||
+            (p->ai_addrlen != p_out.ai_addrlen) ||
+            (canonnamelen_out != canonnamelen_in) ||
+            (canonnamelen_out && p->ai_canonname[canonnamelen_out - 1] != '\0'))
+        {
+            ret = OE_EAI_FAIL;
+            goto done;
+        }
+
         /* Append to the list. */
         if (tail)
         {
             tail->ai_next = p;
             tail = p;
diff --git a/syscall/devices/hostsock/hostsock.c b/syscall/devices/hostsock/hostsock.c
index e790a59c7..9f2a6f51e 100644
--- a/syscall/devices/hostsock/hostsock.c
+++ b/syscall/devices/hostsock/hostsock.c
@@ -347,11 +347,19 @@ static ssize_t _hostsock_recv(
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(sock_);
 
     oe_errno = 0;
 
-    if (!sock || (count && !buf))
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
+     * for more detail.
+     */
+    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (buf)
     {
         if (oe_memset_s(buf, count, 0, count) != OE_OK)
@@ -359,44 +367,97 @@ static ssize_t _hostsock_recv(
     }
 
     if (oe_syscall_recv_ocall(&ret, sock->host_fd, buf, count, flags) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _hostsock_recvfrom(
     oe_fd_t* sock_,
     void* buf,
     size_t count,
     int flags,
-    const struct oe_sockaddr* src_addr,
+    struct oe_sockaddr* src_addr,
     oe_socklen_t* addrlen)
 {
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(sock_);
     oe_socklen_t addrlen_in = 0;
+    oe_socklen_t addrlen_out = 0;
 
     oe_errno = 0;
 
-    if (!sock || (count && !buf))
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html
+     * for more detail.
+     */
+    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
-    if (addrlen)
+    /*
+     * Update the addrlen_in to the value pointed by addrlen
+     * only if both src_addr and addrlen are not NULL.
+     */
+    if (src_addr && addrlen)
         addrlen_in = *addrlen;
 
     if (oe_syscall_recvfrom_ocall(
             &ret,
             sock->host_fd,
             buf,
             count,
             flags,
-            (struct oe_sockaddr*)src_addr,
+            src_addr,
             addrlen_in,
-            addrlen) != OE_OK)
+            &addrlen_out) != OE_OK)
+    {
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
+    /*
+     * Update the value pointed by addrlen based on the host-set
+     * addrlen_out only if both src_addr and addrlen are not NULL.
+     */
+    if (src_addr && addrlen)
+    {
+        /*
+         * Error out the case if the addrlen_out is greater than the size
+         * of sockaddr_storage.
+         */
+        if (addrlen_out > sizeof(struct oe_sockaddr_storage))
+            OE_RAISE_ERRNO(OE_EINVAL);
+
+        /*
+         * Note that the returned value can still exceed the supplied one,
+         * which indicates a truncation.
+         */
+        *addrlen = addrlen_out;
+    }
+
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
     {
+        ret = -1;
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
 done:
     return ret;
@@ -410,42 +471,103 @@ static ssize_t _hostsock_recvmsg(
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(sock_);
     oe_errno = 0;
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
+    oe_socklen_t namelen_out = 0;
+    size_t controllen_out = 0;
 
     /* Check the parameters. */
     if (!sock || !msg || (msg->msg_iovlen && !msg->msg_iov))
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size) != 0)
+    if (oe_iov_pack(
+            msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size, &data_size) !=
+        0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     {
         if (oe_syscall_recvmsg_ocall(
                 &ret,
                 sock->host_fd,
                 msg->msg_name,
                 msg->msg_namelen,
-                &msg->msg_namelen,
+                &namelen_out,
                 buf,
                 msg->msg_iovlen,
                 buf_size,
                 msg->msg_control,
                 msg->msg_controllen,
-                &msg->msg_controllen,
+                &controllen_out,
                 flags) != OE_OK)
         {
             OE_RAISE_ERRNO(OE_EINVAL);
         }
 
         if (ret == -1)
             OE_RAISE_ERRNO(oe_errno);
     }
 
+    if (!msg->msg_name)
+        msg->msg_namelen = 0;
+    else
+    {
+        /*
+         * Error out the case if the namelen_out is greater than the size
+         * of sockaddr_storage.
+         */
+        if (namelen_out > sizeof(struct oe_sockaddr_storage))
+            OE_RAISE_ERRNO(OE_EINVAL);
+
+        /*
+         * Note that the returned value can still exceed the supplied one,
+         * which indicates a truncation.
+         */
+        if (msg->msg_namelen >= namelen_out)
+            msg->msg_namelen = namelen_out;
+    }
+
+    if (!msg->msg_control)
+        msg->msg_controllen = 0;
+    else
+    {
+        /*
+         * Update the msg_controllen only if the supplied value is greater than
+         * or equal to the returned value. Otherwise, keep the msg_controllen
+         * unchanged, which indicates a truncation. In addition, explicitly
+         * setting the MSG_CTRUNC flag when the truncation occurs.
+         */
+        if (msg->msg_controllen >= controllen_out)
+            msg->msg_controllen = controllen_out;
+        else
+            msg->msg_flags |= OE_MSG_CTRUNC;
+    }
+
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
     /* Synchronize data read with IO vector. */
     if (oe_iov_sync(msg->msg_iov, (int)msg->msg_iovlen, buf, buf_size) != 0)
         OE_RAISE_ERRNO(OE_EINVAL);
 
 done:
@@ -465,16 +587,34 @@ static ssize_t _hostsock_send(
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(sock_);
 
     oe_errno = 0;
 
-    if (!sock || (count && !buf))
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html for
+     * for more detail.
+     */
+    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_send_ocall(&ret, sock->host_fd, buf, count, flags) != OE_OK)
         OE_RAISE_ERRNO(OE_EINVAL);
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _hostsock_sendto(
@@ -488,11 +628,19 @@ static ssize_t _hostsock_sendto(
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(sock_);
 
     oe_errno = 0;
 
-    if (!sock || (count && !buf))
+    /*
+     * According to the POSIX specification, when the count is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
+     * for more detail.
+     */
+    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_sendto_ocall(
             &ret,
             sock->host_fd,
@@ -503,10 +651,20 @@ static ssize_t _hostsock_sendto(
             addrlen) != OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed count.
+     */
+    if (ret > (ssize_t)count)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
     return ret;
 }
 
 static ssize_t _hostsock_sendmsg(
@@ -516,21 +674,35 @@ static ssize_t _hostsock_sendmsg(
 {
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(sock_);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     oe_errno = 0;
 
     /* Check the parameters. */
     if (!sock || !msg || (msg->msg_iovlen && !msg->msg_iov))
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size) != 0)
+    if (oe_iov_pack(
+            msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size, &data_size) !=
+        0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_sendmsg_ocall(
             &ret,
             sock->host_fd,
             msg->msg_name,
@@ -543,10 +715,20 @@ static ssize_t _hostsock_sendmsg(
             flags) != OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
 
     if (buf)
         oe_free(buf);
 
@@ -684,26 +866,46 @@ static int _hostsock_getsockopt(
     oe_socklen_t* optlen)
 {
     int ret = -1;
     sock_t* sock = _cast_sock(sock_);
     oe_socklen_t optlen_in = 0;
+    oe_socklen_t optlen_out = 0;
 
     oe_errno = 0;
 
-    if (!sock)
+    if (!sock || !optval || !optlen)
         OE_RAISE_ERRNO(OE_EINVAL);
 
-    if (optlen)
-        optlen_in = *optlen;
+    optlen_in = *optlen;
 
     if (oe_syscall_getsockopt_ocall(
-            &ret, sock->host_fd, level, optname, optval, optlen_in, optlen) !=
-        OE_OK)
+            &ret,
+            sock->host_fd,
+            level,
+            optname,
+            optval,
+            optlen_in,
+            &optlen_out) != OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * The POSIX specification for getsockopt states that if the size of optval
+     * is greater than the input optlen, then the value stored in the object
+     * pointed to by the optval argument shall be silently truncated. We do this
+     * in the enclave to ensure that the untrusted host has not returned an
+     * arbitrarily large optlen value.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
+     * for more detail.
+     */
+    if (optlen_out > optlen_in)
+        optlen_out = optlen_in;
+
+    *optlen = optlen_out;
+
 done:
 
     return ret;
 }
 
@@ -758,29 +960,46 @@ static int _hostsock_getpeername(
     oe_socklen_t* addrlen)
 {
     int ret = -1;
     sock_t* sock = _cast_sock(sock_);
     oe_socklen_t addrlen_in = 0;
+    oe_socklen_t addrlen_out = 0;
 
     oe_errno = 0;
 
-    if (!sock)
+    if (!sock || !addr || !addrlen)
         OE_RAISE_ERRNO(OE_EINVAL);
 
-    if (addrlen)
-        addrlen_in = *addrlen;
+    addrlen_in = *addrlen;
+    if (addrlen_in < 0)
+        OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_getpeername_ocall(
             &ret,
             sock->host_fd,
             (struct oe_sockaddr*)addr,
             addrlen_in,
-            addrlen) != OE_OK)
+            &addrlen_out) != OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Error out the case if the addrlen_out is greater than the size
+     * of sockaddr_storage.
+     */
+    if (addrlen_out > sizeof(struct oe_sockaddr_storage))
+        OE_RAISE_ERRNO(OE_EINVAL);
+
+    /*
+     * Note that the returned value can still exceed the supplied one,
+     * which indicates a truncation. Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html
+     * for more detail.
+     */
+    *addrlen = addrlen_out;
+
 done:
 
     return ret;
 }
 
@@ -790,29 +1009,43 @@ static int _hostsock_getsockname(
     oe_socklen_t* addrlen)
 {
     int ret = -1;
     sock_t* sock = _cast_sock(sock_);
     oe_socklen_t addrlen_in = 0;
+    oe_socklen_t addrlen_out = 0;
 
     oe_errno = 0;
 
-    if (!sock)
+    if (!sock || !addr || !addrlen)
         OE_RAISE_ERRNO(OE_EINVAL);
 
-    if (addrlen)
-        addrlen_in = *addrlen;
+    addrlen_in = *addrlen;
+    if (addrlen_in < 0)
+        OE_RAISE_ERRNO(OE_EINVAL);
 
     if (oe_syscall_getsockname_ocall(
-            &ret,
-            sock->host_fd,
-            (struct oe_sockaddr*)addr,
-            addrlen_in,
-            addrlen) != OE_OK)
+            &ret, sock->host_fd, addr, addrlen_in, &addrlen_out) != OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Error out the case if the addrlen_out is greater than the size
+     * of sockaddr_storage.
+     */
+    if (addrlen_out > sizeof(struct oe_sockaddr_storage))
+        OE_RAISE_ERRNO(OE_EINVAL);
+
+    /*
+     * Note that the returned value can still exceed the supplied one, which
+     * indicates a truncation. Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html
+     * for more detail.
+     */
+    if (addrlen_in >= addrlen_out)
+        *addrlen = addrlen_out;
+
 done:
 
     return ret;
 }
 
@@ -833,25 +1066,47 @@ static ssize_t _hostsock_readv(
 {
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!sock || (!iov && iovcnt) || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_recvv_ocall(&ret, sock->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The returned value should not exceed data_size.
+     */
+    if (ret > (ssize_t)(data_size))
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
     /* Synchronize data read with IO vector. */
     if (ret > 0)
     {
         if (oe_iov_sync(iov, iovcnt, buf, buf_size) != 0)
             OE_RAISE_ERRNO(OE_EINVAL);
@@ -872,25 +1127,47 @@ static ssize_t _hostsock_writev(
 {
     ssize_t ret = -1;
     sock_t* sock = _cast_sock(desc);
     void* buf = NULL;
     size_t buf_size = 0;
+    size_t data_size = 0;
 
     if (!sock || !iov || iovcnt < 0 || iovcnt > OE_IOV_MAX)
         OE_RAISE_ERRNO(OE_EINVAL);
 
     /* Flatten the IO vector into contiguous heap memory. */
-    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
+    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
         OE_RAISE_ERRNO(OE_ENOMEM);
 
+    /*
+     * According to the POSIX specification, when the data_size is greater
+     * than SSIZE_MAX, the result is implementation-defined. OE raises an
+     * error in this case.
+     * Refer to
+     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
+     * for more detail.
+     */
+    if (data_size > OE_SSIZE_MAX)
+        OE_RAISE_ERRNO(OE_EINVAL);
+
     /* Call the host. */
     if (oe_syscall_sendv_ocall(&ret, sock->host_fd, buf, iovcnt, buf_size) !=
         OE_OK)
     {
         OE_RAISE_ERRNO(OE_EINVAL);
     }
 
+    /*
+     * Guard the special case that a host sets an arbitrarily large value.
+     * The return value should not exceed data_size.
+     */
+    if (ret > (ssize_t)data_size)
+    {
+        ret = -1;
+        OE_RAISE_ERRNO(OE_EINVAL);
+    }
+
 done:
 
     if (buf)
         oe_free(buf);
 
diff --git a/syscall/iov.c b/syscall/iov.c
index 6aa1f51b9..c44ec9f83 100644
--- a/syscall/iov.c
+++ b/syscall/iov.c
@@ -15,11 +15,12 @@
 
 int oe_iov_pack(
     const struct oe_iovec* iov,
     int iovcnt,
     void** buf_out,
-    size_t* buf_size_out)
+    size_t* buf_size_out,
+    size_t* data_size_out)
 {
     int ret = -1;
     struct oe_iovec* buf = NULL;
     size_t buf_size = 0;
     size_t data_size = 0;
@@ -28,12 +29,16 @@ int oe_iov_pack(
         *buf_out = NULL;
 
     if (buf_size_out)
         *buf_size_out = 0;
 
+    if (data_size_out)
+        *data_size_out = 0;
+
     /* Reject invalid parameters. */
-    if (iovcnt < 0 || (iovcnt > 0 && !iov) || !buf_out || !buf_size_out)
+    if (iovcnt < 0 || (iovcnt > 0 && !iov) || !buf_out || !buf_size_out ||
+        !data_size_out)
         goto done;
 
     /* Handle zero-sized iovcnt up front. */
     if (iovcnt == 0)
     {
@@ -45,10 +50,11 @@ int oe_iov_pack(
             buf_size = sizeof(uint64_t);
         }
 
         *buf_out = buf;
         *buf_size_out = buf_size;
+        *data_size_out = data_size;
         buf = NULL;
         ret = 0;
         goto done;
     }
 
@@ -95,10 +101,11 @@ int oe_iov_pack(
             goto done;
     }
 
     *buf_out = buf;
     *buf_size_out = buf_size;
+    *data_size_out = data_size;
     buf = NULL;
     ret = 0;
 
 done:
 
@@ -153,11 +160,12 @@ int oe_iov_sync(
                 size_t dest_size = iov[i].iov_len;
 
                 if (src_size != dest_size)
                     goto done;
 
-                if (src < (uint8_t*)buf || src > (uint8_t*)buf + buf_size)
+                if (src < (uint8_t*)buf || src + src_size < src ||
+                    src + src_size > (uint8_t*)buf + buf_size)
                     goto done;
 
                 if (oe_memcpy_s(dest, dest_size, src, src_size) != OE_OK)
                     goto done;
             }
diff --git a/syscall/socket.c b/syscall/socket.c
index 33f0ff589..cfdb3ebec 100644
--- a/syscall/socket.c
+++ b/syscall/socket.c
@@ -195,11 +195,11 @@ done:
 ssize_t oe_recvfrom(
     int sockfd,
     void* buf,
     size_t len,
     int flags,
-    const struct oe_sockaddr* src_addr,
+    struct oe_sockaddr* src_addr,
     oe_socklen_t* addrlen)
 {
     ssize_t ret = -1;
     oe_fd_t* sock;
 
diff --git a/syscall/syscall.c b/syscall/syscall.c
index cc13334ca..f8707fc14 100644
--- a/syscall/syscall.c
+++ b/syscall/syscall.c
@@ -615,12 +615,11 @@ static long _syscall(
         {
             int sockfd = (int)arg1;
             void* buf = (void*)arg2;
             size_t len = (size_t)arg3;
             int flags = (int)arg4;
-            const struct oe_sockaddr* dest_add =
-                (const struct oe_sockaddr*)arg5;
+            struct oe_sockaddr* dest_add = (struct oe_sockaddr*)arg5;
             oe_socklen_t* addrlen = (oe_socklen_t*)arg6;
 
             ret = oe_recvfrom(sockfd, buf, len, flags, dest_add, addrlen);
             goto done;
         }

Vulnerable code: 

            [in, out, size=addrlen_in] struct oe_sockaddr* addr,
            [in, out, size=len] void* buf,
            [in, out, size=addrlen_in] struct oe_sockaddr* src_addr,
            [in, out, size=addrlen_in] struct oe_sockaddr* addr,
            [in, out, size=addrlen_in] struct oe_sockaddr* addr,
        const struct oe_sockaddr* src_addr,
    size_t* buf_size_out);
    const struct oe_sockaddr* src_addr,
    if (!file)
    if (!file)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (!file)
    epoll_t* epoll = _cast_epoll(epoll_);
    if (oe_syscall_write_ocall(&ret, epoll->host_fd, buf, count) != OE_OK)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (!file)
    /* Check parameters. */
    if (!file || (count && !buf))
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (!file)
    if (!file)
        size_t canonnamelen = 0;
        if (!(p = oe_calloc(1, sizeof(struct oe_addrinfo))))
        {
            ret = OE_EAI_MEMORY;
            goto done;
        }
                &p->ai_flags,
                &p->ai_family,
                &p->ai_socktype,
                &p->ai_protocol,
                p->ai_addrlen,
                &p->ai_addrlen,
                canonnamelen,
                &canonnamelen,
        if (p->ai_addrlen && !(p->ai_addr = oe_calloc(1, p->ai_addrlen)))
        if (canonnamelen && !(p->ai_canonname = oe_calloc(1, canonnamelen)))
                p->ai_addrlen,
                canonnamelen,
                &canonnamelen,
    if (!sock || (count && !buf))
    const struct oe_sockaddr* src_addr,
    if (!sock || (count && !buf))
    if (addrlen)
            (struct oe_sockaddr*)src_addr,
            addrlen) != OE_OK)
    if (oe_iov_pack(msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size) != 0)
                &msg->msg_namelen,
                &msg->msg_controllen,
    if (!sock || (count && !buf))
    if (!sock || (count && !buf))
    if (oe_iov_pack(msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size) != 0)
    if (!sock)
    if (optlen)
        optlen_in = *optlen;
            &ret, sock->host_fd, level, optname, optval, optlen_in, optlen) !=
        OE_OK)
    if (!sock)
    if (addrlen)
        addrlen_in = *addrlen;
            addrlen) != OE_OK)
    if (!sock)
    if (addrlen)
        addrlen_in = *addrlen;
            &ret,
            sock->host_fd,
            (struct oe_sockaddr*)addr,
            addrlen_in,
            addrlen) != OE_OK)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size) != 0)
    size_t* buf_size_out)
    if (iovcnt < 0 || (iovcnt > 0 && !iov) || !buf_out || !buf_size_out)
                if (src < (uint8_t*)buf || src > (uint8_t*)buf + buf_size)
    const struct oe_sockaddr* src_addr,
            const struct oe_sockaddr* dest_add =
                (const struct oe_sockaddr*)arg5;
Fixed code:             [out, size=addrlen_in] struct oe_sockaddr* addr,
            [out, size=len] void* buf,
            [out, size=addrlen_in] struct oe_sockaddr* src_addr,
            [out, size=addrlen_in] struct oe_sockaddr* addr,
            [out, size=addrlen_in] struct oe_sockaddr* addr,
        struct oe_sockaddr* src_addr,
    size_t* buf_size_out,
    size_t* data_size_out);
/* Socket message flags. */
#define OE_MSG_CTRUNC 0x0008

    struct oe_sockaddr* src_addr,
    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html for
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html for
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html for
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html for
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    epoll_t* file = _cast_epoll(epoll_);
    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html for
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    if (oe_syscall_write_ocall(&ret, file->host_fd, buf, count) != OE_OK)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
    }
    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html for
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html for
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * Check parameters.
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html for
     * for more detail.
     */
    if (!file || (count && !buf) || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html for
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html for
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
     * for more detail.
     */
    if (!file || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

#include <openenclave/internal/syscall/netinet/in.h>
/*
 * The definition of AF_INET6 on Windows (i.e., 23) is different from that of on
 * Linux (i.e., 10). Given that the internal socket.h conforms to the
 * implementation of Linux, we explicitly define the Windows-specific value
 * here for being compatible with a Windows host.
 */
#define OE_AF_INET6_WIN 23

        size_t canonnamelen_in = 0;
        size_t canonnamelen_out = 0;
        struct oe_addrinfo p_out;
        memset(&p_out, 0, sizeof(struct oe_addrinfo));
                &p_out.ai_flags,
                &p_out.ai_family,
                &p_out.ai_socktype,
                &p_out.ai_protocol,
                p_out.ai_addrlen,
                &p_out.ai_addrlen,
                canonnamelen_in,
                &canonnamelen_out,
        /*
         * Guard the special case that a host sets an arbitrarily large value.
         * Based on the implementation of MUSL, the ai_addrlen can only be
         * sizeof(struct sockaddr_in) when the family is AF_INET or
         * sizeof(struct sockaddr_in6) when the family is AF_INET6.
         * When the family is AF_UNSPEC, OE checks the ai_addrlen against
         * sizeof(struct sockaddr_in6) as it should cover AF_INET and
         * AF_INET6 cases. Besides, OE errors out other family types.
         */
        switch (p_out.ai_family)
        {
            case OE_AF_INET:
                if (p_out.ai_addrlen != sizeof(struct oe_sockaddr))
                {
                    ret = OE_EAI_FAIL;
                    goto done;
                }
                break;
            case OE_AF_INET6:
            case OE_AF_INET6_WIN:
            case OE_AF_UNSPEC:
                if (p_out.ai_addrlen != sizeof(struct oe_sockaddr_in6))
                {
                    ret = OE_EAI_FAIL;
                    goto done;
                }
                break;
            default:
                ret = OE_EAI_FAIL;
                goto done;
        }

        if (!(p = oe_calloc(1, sizeof(struct oe_addrinfo))))
        {
            ret = OE_EAI_MEMORY;
            goto done;
        }

        if (p_out.ai_addrlen && !(p->ai_addr = oe_calloc(1, p_out.ai_addrlen)))
        if (canonnamelen_out &&
            !(p->ai_canonname = oe_calloc(1, canonnamelen_out)))
        /* Set canonnamelen_in to the expected length of p->ai_cannonname
         * returned by the host. */
        canonnamelen_in = canonnamelen_out;

                p_out.ai_addrlen,
                canonnamelen_in,
                &canonnamelen_out,
        /*
         * Lock down the out parameters, which are expected
         * to be the same as the first invocation. Also,
         * p->ai_cannonname is expected to be NULL-terminated.
         */
        if ((p->ai_flags != p_out.ai_flags) ||
            (p->ai_family != p_out.ai_family) ||
            (p->ai_socktype != p_out.ai_socktype) ||
            (p->ai_protocol != p_out.ai_protocol) ||
            (p->ai_addrlen != p_out.ai_addrlen) ||
            (canonnamelen_out != canonnamelen_in) ||
            (canonnamelen_out && p->ai_canonname[canonnamelen_out - 1] != '\0'))
        {
            ret = OE_EAI_FAIL;
            goto done;
        }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
     * for more detail.
     */
    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    struct oe_sockaddr* src_addr,
    oe_socklen_t addrlen_out = 0;
    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html
     * for more detail.
     */
    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
    /*
     * Update the addrlen_in to the value pointed by addrlen
     * only if both src_addr and addrlen are not NULL.
     */
    if (src_addr && addrlen)
            src_addr,
            &addrlen_out) != OE_OK)
    {
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * Update the value pointed by addrlen based on the host-set
     * addrlen_out only if both src_addr and addrlen are not NULL.
     */
    if (src_addr && addrlen)
    {
        /*
         * Error out the case if the addrlen_out is greater than the size
         * of sockaddr_storage.
         */
        if (addrlen_out > sizeof(struct oe_sockaddr_storage))
            OE_RAISE_ERRNO(OE_EINVAL);

        /*
         * Note that the returned value can still exceed the supplied one,
         * which indicates a truncation.
         */
        *addrlen = addrlen_out;
    }

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed count.
     */
    if (ret > (ssize_t)count)
        ret = -1;
    size_t data_size = 0;
    oe_socklen_t namelen_out = 0;
    size_t controllen_out = 0;
    if (oe_iov_pack(
            msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size, &data_size) !=
        0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

                &namelen_out,
                &controllen_out,
    if (!msg->msg_name)
        msg->msg_namelen = 0;
    else
    {
        /*
         * Error out the case if the namelen_out is greater than the size
         * of sockaddr_storage.
         */
        if (namelen_out > sizeof(struct oe_sockaddr_storage))
            OE_RAISE_ERRNO(OE_EINVAL);

        /*
         * Note that the returned value can still exceed the supplied one,
         * which indicates a truncation.
         */
        if (msg->msg_namelen >= namelen_out)
            msg->msg_namelen = namelen_out;
    }

    if (!msg->msg_control)
        msg->msg_controllen = 0;
    else
    {
        /*
         * Update the msg_controllen only if the supplied value is greater than
         * or equal to the returned value. Otherwise, keep the msg_controllen
         * unchanged, which indicates a truncation. In addition, explicitly
         * setting the MSG_CTRUNC flag when the truncation occurs.
         */
        if (msg->msg_controllen >= controllen_out)
            msg->msg_controllen = controllen_out;
        else
            msg->msg_flags |= OE_MSG_CTRUNC;
    }

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html for
     * for more detail.
     */
    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    /*
     * According to the POSIX specification, when the count is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html
     * for more detail.
     */
    if (!sock || (count && !buf) || count > OE_SSIZE_MAX)
    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed count.
     */
    if (ret > (ssize_t)count)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(
            msg->msg_iov, (int)msg->msg_iovlen, &buf, &buf_size, &data_size) !=
        0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    oe_socklen_t optlen_out = 0;
    if (!sock || !optval || !optlen)
    optlen_in = *optlen;
            &ret,
            sock->host_fd,
            level,
            optname,
            optval,
            optlen_in,
            &optlen_out) != OE_OK)
    /*
     * The POSIX specification for getsockopt states that if the size of optval
     * is greater than the input optlen, then the value stored in the object
     * pointed to by the optval argument shall be silently truncated. We do this
     * in the enclave to ensure that the untrusted host has not returned an
     * arbitrarily large optlen value.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html
     * for more detail.
     */
    if (optlen_out > optlen_in)
        optlen_out = optlen_in;

    *optlen = optlen_out;

    oe_socklen_t addrlen_out = 0;
    if (!sock || !addr || !addrlen)
    addrlen_in = *addrlen;
    if (addrlen_in < 0)
        OE_RAISE_ERRNO(OE_EINVAL);
            &addrlen_out) != OE_OK)
    /*
     * Error out the case if the addrlen_out is greater than the size
     * of sockaddr_storage.
     */
    if (addrlen_out > sizeof(struct oe_sockaddr_storage))
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Note that the returned value can still exceed the supplied one,
     * which indicates a truncation. Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html
     * for more detail.
     */
    *addrlen = addrlen_out;

    oe_socklen_t addrlen_out = 0;
    if (!sock || !addr || !addrlen)
    addrlen_in = *addrlen;
    if (addrlen_in < 0)
        OE_RAISE_ERRNO(OE_EINVAL);
            &ret, sock->host_fd, addr, addrlen_in, &addrlen_out) != OE_OK)
    /*
     * Error out the case if the addrlen_out is greater than the size
     * of sockaddr_storage.
     */
    if (addrlen_out > sizeof(struct oe_sockaddr_storage))
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Note that the returned value can still exceed the supplied one, which
     * indicates a truncation. Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html
     * for more detail.
     */
    if (addrlen_in >= addrlen_out)
        *addrlen = addrlen_out;

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The returned value should not exceed data_size.
     */
    if (ret > (ssize_t)(data_size))
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t data_size = 0;
    if (oe_iov_pack(iov, iovcnt, &buf, &buf_size, &data_size) != 0)
    /*
     * According to the POSIX specification, when the data_size is greater
     * than SSIZE_MAX, the result is implementation-defined. OE raises an
     * error in this case.
     * Refer to
     * https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html
     * for more detail.
     */
    if (data_size > OE_SSIZE_MAX)
        OE_RAISE_ERRNO(OE_EINVAL);

    /*
     * Guard the special case that a host sets an arbitrarily large value.
     * The return value should not exceed data_size.
     */
    if (ret > (ssize_t)data_size)
    {
        ret = -1;
        OE_RAISE_ERRNO(OE_EINVAL);
    }

    size_t* buf_size_out,
    size_t* data_size_out)
    if (data_size_out)
        *data_size_out = 0;

    if (iovcnt < 0 || (iovcnt > 0 && !iov) || !buf_out || !buf_size_out ||
        !data_size_out)
        *data_size_out = data_size;
    *data_size_out = data_size;
                if (src < (uint8_t*)buf || src + src_size < src ||
                    src + src_size > (uint8_t*)buf + buf_size)
    struct oe_sockaddr* src_addr,
            struct oe_sockaddr* dest_add = (struct oe_sockaddr*)arg5;