From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43038) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VO51F-0005bM-FB for qemu-devel@nongnu.org; Mon, 23 Sep 2013 08:13:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VO517-00084K-0w for qemu-devel@nongnu.org; Mon, 23 Sep 2013 08:13:37 -0400 Received: from mail-lb0-x231.google.com ([2a00:1450:4010:c04::231]:49292) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VO516-000849-PA for qemu-devel@nongnu.org; Mon, 23 Sep 2013 08:13:28 -0400 Received: by mail-lb0-f177.google.com with SMTP id w7so2556303lbi.8 for ; Mon, 23 Sep 2013 05:13:26 -0700 (PDT) From: edgar.iglesias@gmail.com Date: Mon, 23 Sep 2013 14:11:53 +0200 Message-Id: <1379938313-24303-1-git-send-email-edgar.iglesias@gmail.com> Subject: [Qemu-devel] [PATCH v2] linux-user: Handle SOCK_CLOEXEC/NONBLOCK if unavailable on host List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Riku Voipio From: "Edgar E. Iglesias" If the host lacks SOCK_CLOEXEC, bail out with -EINVAL. If the host lacks SOCK_ONONBLOCK, try to emulate it with fcntl() and O_NONBLOCK. Signed-off-by: Edgar E. Iglesias --- v2: Dont emulate SOCK_CLOEXEC (Riku) linux-user/syscall.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c62d875..69badfa 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1701,7 +1701,7 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, free(vec); } -static inline void target_to_host_sock_type(int *type) +static inline int target_to_host_sock_type(int *type) { int host_type = 0; int target_type = *type; @@ -1718,22 +1718,56 @@ static inline void target_to_host_sock_type(int *type) break; } if (target_type & TARGET_SOCK_CLOEXEC) { +#if defined(SOCK_CLOEXEC) host_type |= SOCK_CLOEXEC; +#else + return -TARGET_EINVAL; +#endif } if (target_type & TARGET_SOCK_NONBLOCK) { +#if defined(SOCK_NONBLOCK) host_type |= SOCK_NONBLOCK; +#elif !defined(O_NONBLOCK) + return -TARGET_EINVAL; +#endif } *type = host_type; + return 0; +} + +/* Try to emulate socket type flags after socket creation. */ +static int sock_flags_fixup(int fd, int target_type) +{ +#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK) + if (target_type & TARGET_SOCK_NONBLOCK) { + int flags = fcntl(fd, F_GETFL); + if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) { + close(fd); + return -TARGET_EINVAL; + } + } +#endif + return fd; } /* do_socket() Must return target values and target errnos. */ static abi_long do_socket(int domain, int type, int protocol) { - target_to_host_sock_type(&type); + int target_type = type; + int ret; + + ret = target_to_host_sock_type(&type); + if (ret) { + return ret; + } if (domain == PF_NETLINK) return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */ - return get_errno(socket(domain, type, protocol)); + ret = get_errno(socket(domain, type, protocol)); + if (ret >= 0) { + ret = sock_flags_fixup(ret, target_type); + } + return ret; } /* do_bind() Must return target values and target errnos. */ -- 1.7.10.4