From 3e23de15237c81fe7af7c3ffa299a6ae5fec7d43 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 14 Aug 2018 19:12:17 +0200 Subject: linux-user: fix 32bit g2h()/h2g() sparc32plus has 64bit long type but only 32bit virtual address space. For instance, "apt-get upgrade" failed because of a mmap()/msync() sequence. mmap() returned 0xff252000 but msync() used g2h(0xffffffffff252000) to find the host address. The "(target_ulong)" in g2h() doesn't fix the address because it is 64bit long. This patch introduces an "abi_ptr" that is set to uint32_t if the virtual address space is addressed using 32bit in the linux-user case. It stays set to target_ulong with softmmu case. Signed-off-by: Laurent Vivier Message-Id: <20180814171217.14680-1-laurent@vivier.eu> Reviewed-by: Richard Henderson [lv: added "%" in TARGET_ABI_FMT_ptr "%"PRIx64] --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index bb42a22..1806b33 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7644,7 +7644,7 @@ static int open_self_maps(void *cpu_env, int fd) if (h2g(min) == ts->info->stack_limit) { pstrcpy(path, sizeof(path), " [stack]"); } - dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx + dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", h2g(min), h2g(max - 1) + 1, flag_r, flag_w, flag_x, flag_p, offset, dev_maj, dev_min, inode, -- cgit v1.1 From 2a03d3e6ae1b1ca86199a0c36a35e8ac847905f6 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 20 Aug 2018 19:15:54 +0200 Subject: linux-user: fix recvmsg()/recvfrom() with netlink and MSG_TRUNC If recvmsg()/recvfrom() are used with the MSG_TRUNC flag, they return the real length even if it was longer than the passed buffer. So when we translate the buffer we must check we don't go beyond the end of the buffer. Bug: https://github.com/vivier/qemu-m68k/issues/33 Reported-by: John Paul Adrian Glaubitz Signed-off-by: Laurent Vivier Reviewed-by: Peter Maydell Message-Id: <20180820171557.7734-2-laurent@vivier.eu> --- linux-user/syscall.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1806b33..e66faf1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3892,7 +3892,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, len = ret; if (fd_trans_host_to_target_data(fd)) { ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base, - len); + MIN(msg.msg_iov->iov_len, len)); } else { ret = host_to_target_cmsg(msgp, &msg); } @@ -4169,7 +4169,12 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, } if (!is_error(ret)) { if (fd_trans_host_to_target_data(fd)) { - ret = fd_trans_host_to_target_data(fd)(host_msg, ret); + abi_long trans; + trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len)); + if (is_error(trans)) { + ret = trans; + goto fail; + } } if (target_addr) { host_to_target_sockaddr(target_addr, addr, addrlen); -- cgit v1.1 From 3c3ab559c137af711e857e0ccfc2d44b5a13d993 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 20 Aug 2018 19:15:55 +0200 Subject: linux-user: introduce QEMU_RTA_* to use with rtattr_type_t Following commit will introduce RTA_PREF that appears only with kernel v4.1. To avoid to manage a specific case for it, this patch introduces the full list of rtattr_type_t prefixed with QEMU_ (as we did for IFLA values) Signed-off-by: Laurent Vivier Reviewed-by: Peter Maydell Message-Id: <20180820171557.7734-3-laurent@vivier.eu> [lv: added more RTA_* from linux v4.18] --- linux-user/syscall.c | 56 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 11 deletions(-) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e66faf1..9effbb3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -539,6 +539,40 @@ enum { QEMU___IFLA_XDP_MAX, }; +enum { + QEMU_RTA_UNSPEC, + QEMU_RTA_DST, + QEMU_RTA_SRC, + QEMU_RTA_IIF, + QEMU_RTA_OIF, + QEMU_RTA_GATEWAY, + QEMU_RTA_PRIORITY, + QEMU_RTA_PREFSRC, + QEMU_RTA_METRICS, + QEMU_RTA_MULTIPATH, + QEMU_RTA_PROTOINFO, /* no longer used */ + QEMU_RTA_FLOW, + QEMU_RTA_CACHEINFO, + QEMU_RTA_SESSION, /* no longer used */ + QEMU_RTA_MP_ALGO, /* no longer used */ + QEMU_RTA_TABLE, + QEMU_RTA_MARK, + QEMU_RTA_MFC_STATS, + QEMU_RTA_VIA, + QEMU_RTA_NEWDST, + QEMU_RTA_PREF, + QEMU_RTA_ENCAP_TYPE, + QEMU_RTA_ENCAP, + QEMU_RTA_EXPIRES, + QEMU_RTA_PAD, + QEMU_RTA_UID, + QEMU_RTA_TTL_PROPAGATE, + QEMU_RTA_IP_PROTO, + QEMU_RTA_SPORT, + QEMU_RTA_DPORT, + QEMU___RTA_MAX +}; + typedef abi_long (*TargetFdDataFunc)(void *, size_t); typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t); typedef struct TargetFdTrans { @@ -2661,14 +2695,14 @@ static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr) uint32_t *u32; switch (rtattr->rta_type) { /* binary: depends on family type */ - case RTA_GATEWAY: - case RTA_DST: - case RTA_PREFSRC: + case QEMU_RTA_GATEWAY: + case QEMU_RTA_DST: + case QEMU_RTA_PREFSRC: break; /* u32 */ - case RTA_PRIORITY: - case RTA_TABLE: - case RTA_OIF: + case QEMU_RTA_PRIORITY: + case QEMU_RTA_TABLE: + case QEMU_RTA_OIF: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; @@ -2808,13 +2842,13 @@ static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr) uint32_t *u32; switch (rtattr->rta_type) { /* binary: depends on family type */ - case RTA_DST: - case RTA_SRC: - case RTA_GATEWAY: + case QEMU_RTA_DST: + case QEMU_RTA_SRC: + case QEMU_RTA_GATEWAY: break; /* u32 */ - case RTA_PRIORITY: - case RTA_OIF: + case QEMU_RTA_PRIORITY: + case QEMU_RTA_OIF: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; -- cgit v1.1 From 90cce2a106e4f0f7b568f45ab1c1d175bb1ffa28 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 20 Aug 2018 19:15:56 +0200 Subject: linux-user: update netlink route types Add RTA_PREF and RTA_CACHEINFO. Fix following errors when we start gedit: Unknown host RTA type: 12 Unknown host RTA type: 20 Signed-off-by: Laurent Vivier Reviewed-by: Peter Maydell Message-Id: <20180820171557.7734-4-laurent@vivier.eu> --- linux-user/syscall.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9effbb3..c084010 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2693,12 +2693,17 @@ static abi_long host_to_target_data_addr_rtattr(struct rtattr *rtattr) static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr) { uint32_t *u32; + struct rta_cacheinfo *ci; + switch (rtattr->rta_type) { /* binary: depends on family type */ case QEMU_RTA_GATEWAY: case QEMU_RTA_DST: case QEMU_RTA_PREFSRC: break; + /* u8 */ + case QEMU_RTA_PREF: + break; /* u32 */ case QEMU_RTA_PRIORITY: case QEMU_RTA_TABLE: @@ -2706,6 +2711,20 @@ static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr) u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; + /* struct rta_cacheinfo */ + case QEMU_RTA_CACHEINFO: + ci = RTA_DATA(rtattr); + ci->rta_clntref = tswap32(ci->rta_clntref); + ci->rta_lastuse = tswap32(ci->rta_lastuse); + ci->rta_expires = tswap32(ci->rta_expires); + ci->rta_error = tswap32(ci->rta_error); + ci->rta_used = tswap32(ci->rta_used); +#if defined(RTNETLINK_HAVE_PEERINFO) + ci->rta_id = tswap32(ci->rta_id); + ci->rta_ts = tswap32(ci->rta_ts); + ci->rta_tsage = tswap32(ci->rta_tsage); +#endif + break; default: gemu_log("Unknown host RTA type: %d\n", rtattr->rta_type); break; -- cgit v1.1 From 70c61d4f78cc8475b597f1ef26faf232302b81d1 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 20 Aug 2018 19:15:57 +0200 Subject: linux-user: add QEMU_IFLA_INFO_KIND nested type for tun Signed-off-by: Laurent Vivier Reviewed-by: Peter Maydell Message-Id: <20180820171557.7734-5-laurent@vivier.eu> --- linux-user/syscall.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c084010..202aa77 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -502,6 +502,20 @@ enum { }; enum { + QEMU_IFLA_TUN_UNSPEC, + QEMU_IFLA_TUN_OWNER, + QEMU_IFLA_TUN_GROUP, + QEMU_IFLA_TUN_TYPE, + QEMU_IFLA_TUN_PI, + QEMU_IFLA_TUN_VNET_HDR, + QEMU_IFLA_TUN_PERSIST, + QEMU_IFLA_TUN_MULTI_QUEUE, + QEMU_IFLA_TUN_NUM_QUEUES, + QEMU_IFLA_TUN_NUM_DISABLED_QUEUES, + QEMU___IFLA_TUN_MAX, +}; + +enum { QEMU_IFLA_INFO_UNSPEC, QEMU_IFLA_INFO_KIND, QEMU_IFLA_INFO_DATA, @@ -2349,6 +2363,34 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr, return 0; } +static abi_long host_to_target_data_tun_nlattr(struct nlattr *nlattr, + void *context) +{ + uint32_t *u32; + + switch (nlattr->nla_type) { + /* uint8_t */ + case QEMU_IFLA_TUN_TYPE: + case QEMU_IFLA_TUN_PI: + case QEMU_IFLA_TUN_VNET_HDR: + case QEMU_IFLA_TUN_PERSIST: + case QEMU_IFLA_TUN_MULTI_QUEUE: + break; + /* uint32_t */ + case QEMU_IFLA_TUN_NUM_QUEUES: + case QEMU_IFLA_TUN_NUM_DISABLED_QUEUES: + case QEMU_IFLA_TUN_OWNER: + case QEMU_IFLA_TUN_GROUP: + u32 = NLA_DATA(nlattr); + *u32 = tswap32(*u32); + break; + default: + gemu_log("Unknown QEMU_IFLA_TUN type %d\n", nlattr->nla_type); + break; + } + return 0; +} + struct linkinfo_context { int len; char *name; @@ -2383,6 +2425,12 @@ static abi_long host_to_target_data_linkinfo_nlattr(struct nlattr *nlattr, nlattr->nla_len, NULL, host_to_target_data_bridge_nlattr); + } else if (strncmp(li_context->name, "tun", + li_context->len) == 0) { + return host_to_target_for_each_nlattr(NLA_DATA(nlattr), + nlattr->nla_len, + NULL, + host_to_target_data_tun_nlattr); } else { gemu_log("Unknown QEMU_IFLA_INFO_KIND %s\n", li_context->name); } -- cgit v1.1