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: Paul Burton <paul@archlinuxmips.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
parent
76b9424550
commit
8289d11281
@ -592,6 +592,37 @@ char *target_strerror(int err)
|
|||||||
return strerror(target_to_host_errno(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_brk;
|
||||||
static abi_ulong target_original_brk;
|
static abi_ulong target_original_brk;
|
||||||
static abi_ulong brk_page;
|
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));
|
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
if (optname == SO_TYPE) {
|
||||||
|
val = host_to_target_sock_type(val);
|
||||||
|
}
|
||||||
if (len > lv)
|
if (len > lv)
|
||||||
len = lv;
|
len = lv;
|
||||||
if (len == 4) {
|
if (len == 4) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user