CVE-2020-15224 (C, published 2020-10-14T19:15Z)
Description: 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.
Severity: LOW (CVSS v3 base score: 6.8)
Weakness: NVD-CWE-Other \u2014 Other
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.
Repository: https://github.com/openenclave/openenclave
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 message: Merge pull request from GHSA-525h-wxcc-f66m

Signed-off-by: Ming-Wei Shih <mishih@microsoft.com>

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;