Commit 8289d112 authored by Paul Burton's avatar Paul Burton Committed by Riku Voipio
Browse files

linux-user: translate the result of getsockopt SO_TYPE



QEMU previously passed the result of the host syscall directly to the
target program. This is a problem if the host & target have different
representations of socket types, as is the case when running a MIPS
target program on an x86 host. Introduce a host_to_target_sock_type
helper function mirroring the existing target_to_host_sock_type, and
call it to translate the value provided by getsockopt when called for
the SO_TYPE option.

Signed-off-by: default avatarPaul Burton <paul@archlinuxmips.org>
Signed-off-by: default avatarRiku Voipio <riku.voipio@linaro.org>
parent 76b94245
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -592,6 +592,37 @@ char *target_strerror(int err)
    return strerror(target_to_host_errno(err));
}

static inline int host_to_target_sock_type(int host_type)
{
    int target_type;

    switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
    case SOCK_DGRAM:
        target_type = TARGET_SOCK_DGRAM;
        break;
    case SOCK_STREAM:
        target_type = TARGET_SOCK_STREAM;
        break;
    default:
        target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
        break;
    }

#if defined(SOCK_CLOEXEC)
    if (host_type & SOCK_CLOEXEC) {
        target_type |= TARGET_SOCK_CLOEXEC;
    }
#endif

#if defined(SOCK_NONBLOCK)
    if (host_type & SOCK_NONBLOCK) {
        target_type |= TARGET_SOCK_NONBLOCK;
    }
#endif

    return target_type;
}

static abi_ulong target_brk;
static abi_ulong target_original_brk;
static abi_ulong brk_page;
@@ -1636,6 +1667,9 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
        ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
        if (ret < 0)
            return ret;
        if (optname == SO_TYPE) {
            val = host_to_target_sock_type(val);
        }
        if (len > lv)
            len = lv;
        if (len == 4) {