From 08396600b11323fadcc66b0bcd021bd249f3f624 Mon Sep 17 00:00:00 2001 From: MCApollo <34170230+MCApollo@users.noreply.github.com> Date: Thu, 6 Aug 2020 10:56:04 -0900 Subject: [PATCH 1/5] Added Linux support to tcp tunneling --- hw/arm/guest-socket.c | 108 ++++++++++++++++++++----- include/hw/arm/guest-services/socket.h | 53 +++++++++--- 2 files changed, 130 insertions(+), 31 deletions(-) diff --git a/hw/arm/guest-socket.c b/hw/arm/guest-socket.c index fdf9d1e2df0..47e243d1e9a 100644 --- a/hw/arm/guest-socket.c +++ b/hw/arm/guest-socket.c @@ -27,6 +27,16 @@ #include "sys/socket.h" #include "cpu.h" +#ifdef __APPLE__ // See guest-services/socket.h +# define GNU 0 +# define ADDR addr +# define ADDRLEN addrlen +#else /* linux */ +# define GNU 1 +# define ADDR darwin_addr +# define ADDRLEN darwin_addrlen +#endif + #define SOCKET_TIMEOUT_USECS (10) static int32_t find_free_socket(void) { @@ -55,9 +65,13 @@ int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, return retval; } -int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, - socklen_t *g_addrlen) +int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, + SOCKLEN_T *g_addrlen) { +#if GNU + S_SOCKADDR_IN darwin_addr; + SOCKLEN_T darwin_addrlen; +#endif struct sockaddr_in addr; socklen_t addrlen; @@ -68,24 +82,45 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, // TODO: timeout if (retval < 0) { guest_svcs_errno = ENOTSOCK; - } else if ((guest_svcs_fds[retval] = accept(guest_svcs_fds[sckt], + } else if ((guest_svcs_fds[retval] = +#if GNU + accept4(guest_svcs_fds[sckt], + (struct sockaddr *) &addr, + &addrlen, SOCK_NONBLOCK)) < 0) +#else + accept(guest_svcs_fds[sckt], (struct sockaddr *) &addr, - &addrlen)) < 0) { + &addrlen)) < 0) +#endif + { retval = -1; guest_svcs_errno = errno; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, - sizeof(addr), 1); + +#if GNU + darwin_addr.sin_family = addr.sin_family; + darwin_addr.sin_port = addr.sin_port; + darwin_addr.sin_addr = addr.sin_addr; + darwin_addr.sin_len = sizeof(darwin_addr); + memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); + + darwin_addrlen = sizeof(S_SOCKADDR); +#endif + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, + sizeof(ADDR), 1); cpu_memory_rw_debug(cpu, (target_ulong) g_addrlen, - (uint8_t*) &addrlen, sizeof(addrlen), 1); + (uint8_t*) &ADDRLEN, sizeof(ADDRLEN), 1); } return retval; } -int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, - socklen_t addrlen) +int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, + SOCKLEN_T addrlen) { +#if GNU + S_SOCKADDR_IN darwin_addr; +#endif struct sockaddr_in addr; VERIFY_FD(sckt); @@ -95,24 +130,41 @@ int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, if (addrlen > sizeof(addr)) { guest_svcs_errno = ENOMEM; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, - sizeof(addr), 0); - + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, + sizeof(ADDR), 0); +#if GNU + addr.sin_family = darwin_addr.sin_family; + addr.sin_port = darwin_addr.sin_port; + addr.sin_addr = darwin_addr.sin_addr; + memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); + + addrlen = sizeof(struct sockaddr_in); +#endif if ((retval = bind(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { guest_svcs_errno = errno; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, - sizeof(addr), 1); +#if GNU + darwin_addr.sin_family = addr.sin_family; + darwin_addr.sin_port = addr.sin_port; + darwin_addr.sin_addr = addr.sin_addr; + darwin_addr.sin_len = sizeof(darwin_addr); + memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); +#endif + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, + sizeof(ADDR), 1); } } return retval; } -int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, - socklen_t addrlen) +int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, + SOCKLEN_T addrlen) { +#if GNU + S_SOCKADDR_IN darwin_addr; +#endif struct sockaddr_in addr; VERIFY_FD(sckt); @@ -122,15 +174,29 @@ int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, if (addrlen > sizeof(addr)) { guest_svcs_errno = ENOMEM; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, - sizeof(addr), 0); - + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, + sizeof(ADDR), 0); +#if GNU + addr.sin_family = darwin_addr.sin_family; + addr.sin_port = darwin_addr.sin_port; + addr.sin_addr = darwin_addr.sin_addr; + memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); + + addrlen = sizeof(struct sockaddr_in); +#endif if ((retval = connect(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { guest_svcs_errno = errno; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, - sizeof(addr), 1); +#if GNU + darwin_addr.sin_family = addr.sin_family; + darwin_addr.sin_port = addr.sin_port; + darwin_addr.sin_addr = addr.sin_addr; + darwin_addr.sin_len = sizeof(S_SOCKADDR_IN); + memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); +#endif + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, + sizeof(ADDR), 1); } } diff --git a/include/hw/arm/guest-services/socket.h b/include/hw/arm/guest-services/socket.h index ff98bd8b668..6e727a6a4e1 100644 --- a/include/hw/arm/guest-services/socket.h +++ b/include/hw/arm/guest-services/socket.h @@ -32,6 +32,39 @@ #include "sys/socket.h" #endif +#ifdef __APPLE__ +#define S_SOCKADDR struct sockaddr +#define S_SOCKADDR_IN struct sockaddr_in +#define SOCKLEN_T socklen_t +#else /* __linux__ */ +/* XXX: A lot of this is defined by the standard. + But doesn't hurt to ensure Darwin/BSD lengths. + +- in_addr_t should be uint32 on all systems: +typedef unsigned int in_addr_t; +struct in_addr { + in_addr_t s_addr; +}; +*/ +struct darwin_sockaddr { + unsigned char sa_len; + unsigned char sa_family; + char sa_data[14]; +}; +struct darwin_sockaddr_in { + unsigned char sin_len; + unsigned char sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; +typedef unsigned int darwin_socklen_t; + +#define S_SOCKADDR struct darwin_sockaddr +#define S_SOCKADDR_IN struct darwin_sockaddr_in +#define SOCKLEN_T darwin_socklen_t +#endif + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" extern int32_t guest_svcs_errno; @@ -47,14 +80,14 @@ typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) { int32_t socket; - struct sockaddr *addr; - socklen_t *addrlen; + S_SOCKADDR *addr; + SOCKLEN_T *addrlen; } qc_accept_args_t; typedef struct __attribute__((packed)) { int32_t socket; - struct sockaddr *addr; - socklen_t addrlen; + S_SOCKADDR *addr; + SOCKLEN_T addrlen; } qc_bind_args_t, qc_connect_args_t; typedef struct __attribute__((packed)) { @@ -72,12 +105,12 @@ typedef struct __attribute__((packed)) { #ifndef OUT_OF_TREE_BUILD int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, int32_t protocol); -int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *addr, - socklen_t *addrlen); -int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *addr, - socklen_t addrlen); -int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *addr, - socklen_t addrlen); +int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *addr, + SOCKLEN_T *addrlen); +int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *addr, + SOCKLEN_T addrlen); +int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *addr, + SOCKLEN_T addrlen); int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog); int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *buffer, size_t length, int32_t flags); From 59a223a0b06890c17e483ff4675dee26581ec5fe Mon Sep 17 00:00:00 2001 From: MCApollo <34170230+MCApollo@users.noreply.github.com> Date: Thu, 6 Aug 2020 11:29:47 -0900 Subject: [PATCH 2/5] guest-socket: clean up addrlen's --- hw/arm/guest-socket.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/arm/guest-socket.c b/hw/arm/guest-socket.c index 47e243d1e9a..3711040645f 100644 --- a/hw/arm/guest-socket.c +++ b/hw/arm/guest-socket.c @@ -75,6 +75,7 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, struct sockaddr_in addr; socklen_t addrlen; + addrlen = sizeof(addr); VERIFY_FD(sckt); int retval = find_free_socket(); @@ -104,7 +105,7 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, darwin_addr.sin_len = sizeof(darwin_addr); memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); - darwin_addrlen = sizeof(S_SOCKADDR); + darwin_addrlen = sizeof(darwin_addr); #endif cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, sizeof(ADDR), 1); @@ -138,7 +139,7 @@ int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, addr.sin_addr = darwin_addr.sin_addr; memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); - addrlen = sizeof(struct sockaddr_in); + addrlen = sizeof(addr); #endif if ((retval = bind(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { @@ -182,7 +183,7 @@ int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, addr.sin_addr = darwin_addr.sin_addr; memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); - addrlen = sizeof(struct sockaddr_in); + addrlen = sizeof(addr); #endif if ((retval = connect(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { @@ -192,7 +193,7 @@ int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, darwin_addr.sin_family = addr.sin_family; darwin_addr.sin_port = addr.sin_port; darwin_addr.sin_addr = addr.sin_addr; - darwin_addr.sin_len = sizeof(S_SOCKADDR_IN); + darwin_addr.sin_len = sizeof(darwin_addr); memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); #endif cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, From 1377261e2b91d45f1c4897c8e8eb254eb89baa08 Mon Sep 17 00:00:00 2001 From: MCApollo <34170230+MCApollo@users.noreply.github.com> Date: Mon, 10 Aug 2020 20:40:08 -0900 Subject: [PATCH 3/5] guest-socket: reformat code; handle errno's on host side --- hw/arm/guest-socket.c | 162 +++++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 66 deletions(-) diff --git a/hw/arm/guest-socket.c b/hw/arm/guest-socket.c index 3711040645f..230be92c2db 100644 --- a/hw/arm/guest-socket.c +++ b/hw/arm/guest-socket.c @@ -27,16 +27,6 @@ #include "sys/socket.h" #include "cpu.h" -#ifdef __APPLE__ // See guest-services/socket.h -# define GNU 0 -# define ADDR addr -# define ADDRLEN addrlen -#else /* linux */ -# define GNU 1 -# define ADDR darwin_addr -# define ADDRLEN darwin_addrlen -#endif - #define SOCKET_TIMEOUT_USECS (10) static int32_t find_free_socket(void) { @@ -50,6 +40,74 @@ static int32_t find_free_socket(void) { return -1; } + +/* NETWORK_HACK: + See `guest-services/socket.h`: + Darwin still uses `sin_len` in sockaddr, + causing errors when copying memory from iOS. +*/ +#ifdef __APPLE__ +# define ADDR addr +# undef NETWORK_HACK +#else /* Linux, etc. */ +# define ADDR darwin_addr +# define NETWORK_HACK 1 +#endif + +static int convert_error(int err) { +#ifndef NETWORK_HACK + return err; +#else /* linux */ + int result; + + switch(err) { + case EAGAIN: +/* case EWOULDBLOCK: */ + result = 35; + break; + case EDEADLK: +/* case EDEADLOCK: */ + result = 11; + break; + /* case {...}: */ + default: + result = err; + break; + } + return result; +#endif +} + +static struct sockaddr_in convert_sockaddr_to(S_SOCKADDR_IN from) { +#ifndef NETWORK_HACK + return from; +#else + struct sockaddr_in to; + to.sin_family = from.sin_family; + to.sin_port = from.sin_port; + to.sin_addr = from.sin_addr; + memset(&to.sin_zero, 0, sizeof(to.sin_zero)); + + return to; +#endif +} + +static S_SOCKADDR_IN convert_sockaddr_from(struct sockaddr_in from) { +#ifndef NETWORK_HACK + return from; +#else + S_SOCKADDR_IN to; + to.sin_family = from.sin_family; + to.sin_port = from.sin_port; + to.sin_addr = from.sin_addr; + to.sin_len = sizeof(to); + memset(&to.sin_zero, 0, sizeof(to.sin_zero)); + + return to; +#endif +} + + int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, int32_t protocol) { @@ -59,7 +117,7 @@ int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, guest_svcs_errno = ENOTSOCK; } else if ((guest_svcs_fds[retval] = socket(domain, type, protocol)) < 0) { retval = -1; - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } return retval; @@ -68,12 +126,8 @@ int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, SOCKLEN_T *g_addrlen) { -#if GNU - S_SOCKADDR_IN darwin_addr; - SOCKLEN_T darwin_addrlen; -#endif struct sockaddr_in addr; - socklen_t addrlen; + SOCKLEN_T addrlen; addrlen = sizeof(addr); VERIFY_FD(sckt); @@ -84,7 +138,7 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, if (retval < 0) { guest_svcs_errno = ENOTSOCK; } else if ((guest_svcs_fds[retval] = -#if GNU +#ifdef NETWORK_HACK accept4(guest_svcs_fds[sckt], (struct sockaddr *) &addr, &addrlen, SOCK_NONBLOCK)) < 0) @@ -95,22 +149,15 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, #endif { retval = -1; - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } else { - -#if GNU - darwin_addr.sin_family = addr.sin_family; - darwin_addr.sin_port = addr.sin_port; - darwin_addr.sin_addr = addr.sin_addr; - darwin_addr.sin_len = sizeof(darwin_addr); - memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); - - darwin_addrlen = sizeof(darwin_addr); +#ifdef NETWORK_HACK + S_SOCKADDR_IN ADDR = convert_sockaddr_from(addr); #endif cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, sizeof(ADDR), 1); cpu_memory_rw_debug(cpu, (target_ulong) g_addrlen, - (uint8_t*) &ADDRLEN, sizeof(ADDRLEN), 1); + (uint8_t*) &addrlen, sizeof(addrlen), 1); } return retval; @@ -119,10 +166,10 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, SOCKLEN_T addrlen) { -#if GNU - S_SOCKADDR_IN darwin_addr; -#endif struct sockaddr_in addr; +#ifdef NETWORK_HACK + S_SOCKADDR_IN ADDR; +#endif VERIFY_FD(sckt); @@ -133,24 +180,16 @@ int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, } else { cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, sizeof(ADDR), 0); -#if GNU - addr.sin_family = darwin_addr.sin_family; - addr.sin_port = darwin_addr.sin_port; - addr.sin_addr = darwin_addr.sin_addr; - memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); - addrlen = sizeof(addr); +#ifdef NETWORK_HACK + addr = convert_sockaddr_to(ADDR); #endif if ((retval = bind(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } else { -#if GNU - darwin_addr.sin_family = addr.sin_family; - darwin_addr.sin_port = addr.sin_port; - darwin_addr.sin_addr = addr.sin_addr; - darwin_addr.sin_len = sizeof(darwin_addr); - memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); +#ifdef NETWORK_HACK + ADDR = convert_sockaddr_from(addr); #endif cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, sizeof(ADDR), 1); @@ -163,10 +202,10 @@ int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, SOCKLEN_T addrlen) { -#if GNU - S_SOCKADDR_IN darwin_addr; -#endif struct sockaddr_in addr; +#ifdef NETWORK_HACK + S_SOCKADDR_IN ADDR; +#endif VERIFY_FD(sckt); @@ -177,27 +216,18 @@ int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, } else { cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, sizeof(ADDR), 0); -#if GNU - addr.sin_family = darwin_addr.sin_family; - addr.sin_port = darwin_addr.sin_port; - addr.sin_addr = darwin_addr.sin_addr; - memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); - - addrlen = sizeof(addr); +#ifdef NETWORK_HACK + addr = convert_sockaddr_to(ADDR); #endif if ((retval = connect(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } else { -#if GNU - darwin_addr.sin_family = addr.sin_family; - darwin_addr.sin_port = addr.sin_port; - darwin_addr.sin_addr = addr.sin_addr; - darwin_addr.sin_len = sizeof(darwin_addr); - memset(&darwin_addr.sin_zero, 0, sizeof(darwin_addr.sin_zero)); +#ifdef NETWORK_HACK + ADDR = convert_sockaddr_from(addr); #endif - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, - sizeof(ADDR), 1); + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 1); } } @@ -211,7 +241,7 @@ int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog) int retval = 0; if ((retval = listen(guest_svcs_fds[sckt], backlog)) < 0) { - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } return retval; @@ -229,7 +259,7 @@ int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *g_buffer, if (length > MAX_BUF_SIZE) { guest_svcs_errno = ENOMEM; } else if ((retval = recv(guest_svcs_fds[sckt], buffer, length, flags)) <= 0) { - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } else { cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, retval, 1); } @@ -251,7 +281,7 @@ int32_t qc_handle_send(CPUState *cpu, int32_t sckt, void *g_buffer, cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, length, 0); if ((retval = send(guest_svcs_fds[sckt], buffer, length, flags)) < 0) { - guest_svcs_errno = errno; + guest_svcs_errno = convert_error(errno); } } From df08c4cd8558e07405966b073000895b24cc6def Mon Sep 17 00:00:00 2001 From: MCApollo <34170230+MCApollo@users.noreply.github.com> Date: Tue, 11 Aug 2020 21:39:39 -0900 Subject: [PATCH 4/5] guest-socket: Improved readability and flow --- hw/arm/guest-socket.c | 165 ++++++++++++------------- include/hw/arm/guest-services/socket.h | 36 +++--- 2 files changed, 98 insertions(+), 103 deletions(-) diff --git a/hw/arm/guest-socket.c b/hw/arm/guest-socket.c index 230be92c2db..a3fbc634830 100644 --- a/hw/arm/guest-socket.c +++ b/hw/arm/guest-socket.c @@ -41,23 +41,37 @@ static int32_t find_free_socket(void) { } -/* NETWORK_HACK: +#ifndef __APPLE__ +/* convert_sockaddr_from/to darwin: See `guest-services/socket.h`: - Darwin still uses `sin_len` in sockaddr, - causing errors when copying memory from iOS. + * Darwin still uses `sin_len` in sockaddr, + causing errors when copying memory from iOS. */ -#ifdef __APPLE__ -# define ADDR addr -# undef NETWORK_HACK -#else /* Linux, etc. */ -# define ADDR darwin_addr -# define NETWORK_HACK 1 +static struct sockaddr_in convert_sockaddr_from_darwin(struct darwin_sockaddr_in from) { + return (struct sockaddr_in) { + from.sin_family, + from.sin_port, + from.sin_addr, + { [0 ... sizeof(from.sin_zero) - 1] = 0 } }; +} + +static struct darwin_sockaddr_in convert_sockaddr_to_darwin(struct sockaddr_in from) { + return (struct darwin_sockaddr_in) { + sizeof(from), + from.sin_family, + from.sin_port, + from.sin_addr, + { [0 ... sizeof(from.sin_zero) - 1] = 0 } }; +} #endif -static int convert_error(int err) { -#ifndef NETWORK_HACK - return err; -#else /* linux */ +/* darwin_error: + At compile-time, redefine what errors mean to tcp-tunnel before sending them. +*/ +static int darwin_error(int err) { +#ifdef __APPLE__ + return err; +#else int result; switch(err) { @@ -69,41 +83,12 @@ static int convert_error(int err) { /* case EDEADLOCK: */ result = 11; break; - /* case {...}: */ default: result = err; break; - } - return result; -#endif -} - -static struct sockaddr_in convert_sockaddr_to(S_SOCKADDR_IN from) { -#ifndef NETWORK_HACK - return from; -#else - struct sockaddr_in to; - to.sin_family = from.sin_family; - to.sin_port = from.sin_port; - to.sin_addr = from.sin_addr; - memset(&to.sin_zero, 0, sizeof(to.sin_zero)); - - return to; -#endif -} + } -static S_SOCKADDR_IN convert_sockaddr_from(struct sockaddr_in from) { -#ifndef NETWORK_HACK - return from; -#else - S_SOCKADDR_IN to; - to.sin_family = from.sin_family; - to.sin_port = from.sin_port; - to.sin_addr = from.sin_addr; - to.sin_len = sizeof(to); - memset(&to.sin_zero, 0, sizeof(to.sin_zero)); - - return to; + return result; #endif } @@ -117,19 +102,18 @@ int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, guest_svcs_errno = ENOTSOCK; } else if ((guest_svcs_fds[retval] = socket(domain, type, protocol)) < 0) { retval = -1; - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } return retval; } -int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, - SOCKLEN_T *g_addrlen) +int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct SOCKADDR *g_addr, + socklen_t *g_addrlen) { struct sockaddr_in addr; - SOCKLEN_T addrlen; + socklen_t addrlen = sizeof(addr); - addrlen = sizeof(addr); VERIFY_FD(sckt); int retval = find_free_socket(); @@ -138,7 +122,7 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, if (retval < 0) { guest_svcs_errno = ENOTSOCK; } else if ((guest_svcs_fds[retval] = -#ifdef NETWORK_HACK +#ifndef __APPLE__ accept4(guest_svcs_fds[sckt], (struct sockaddr *) &addr, &addrlen, SOCK_NONBLOCK)) < 0) @@ -149,13 +133,15 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, #endif { retval = -1; - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } else { -#ifdef NETWORK_HACK - S_SOCKADDR_IN ADDR = convert_sockaddr_from(addr); +#ifndef __APPLE__ + struct darwin_sockaddr_in darwin_addr = convert_sockaddr_to_darwin(addr); + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &darwin_addr, + sizeof(darwin_addr), 1); #endif - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, - sizeof(ADDR), 1); + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 1); cpu_memory_rw_debug(cpu, (target_ulong) g_addrlen, (uint8_t*) &addrlen, sizeof(addrlen), 1); } @@ -163,12 +149,12 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, return retval; } -int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, - SOCKLEN_T addrlen) +int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct SOCKADDR *g_addr, + socklen_t addrlen) { struct sockaddr_in addr; -#ifdef NETWORK_HACK - S_SOCKADDR_IN ADDR; +#ifndef __APPLE__ + struct darwin_sockaddr_in darwin_addr; #endif VERIFY_FD(sckt); @@ -178,33 +164,38 @@ int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, if (addrlen > sizeof(addr)) { guest_svcs_errno = ENOMEM; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, - sizeof(ADDR), 0); - -#ifdef NETWORK_HACK - addr = convert_sockaddr_to(ADDR); +#ifndef __APPLE__ + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &darwin_addr, + sizeof(darwin_addr), 0); + addr = convert_sockaddr_from_darwin(darwin_addr); +#else + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 0); #endif if ((retval = bind(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } else { -#ifdef NETWORK_HACK - ADDR = convert_sockaddr_from(addr); +#ifndef __APPLE__ + darwin_addr = convert_sockaddr_to_darwin(addr); + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &darwin_addr, + sizeof(darwin_addr), 1); +#else + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 1); #endif - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, - sizeof(ADDR), 1); } } return retval; } -int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, - SOCKLEN_T addrlen) +int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct SOCKADDR *g_addr, + socklen_t addrlen) { struct sockaddr_in addr; -#ifdef NETWORK_HACK - S_SOCKADDR_IN ADDR; +#ifndef __APPLE__ + struct darwin_sockaddr_in darwin_addr; #endif VERIFY_FD(sckt); @@ -214,20 +205,26 @@ int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *g_addr, if (addrlen > sizeof(addr)) { guest_svcs_errno = ENOMEM; } else { - cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &ADDR, - sizeof(ADDR), 0); -#ifdef NETWORK_HACK - addr = convert_sockaddr_to(ADDR); +#ifndef __APPLE__ + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &darwin_addr, + sizeof(darwin_addr), 0); + addr = convert_sockaddr_from_darwin(darwin_addr); +#else + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 0); #endif if ((retval = connect(guest_svcs_fds[sckt], (struct sockaddr *) &addr, addrlen)) < 0) { - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } else { -#ifdef NETWORK_HACK - ADDR = convert_sockaddr_from(addr); -#endif +#ifndef __APPLE__ + darwin_addr = convert_sockaddr_to_darwin(addr); + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &darwin_addr, + sizeof(darwin_addr), 1); +#else cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, sizeof(addr), 1); +#endif } } @@ -241,7 +238,7 @@ int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog) int retval = 0; if ((retval = listen(guest_svcs_fds[sckt], backlog)) < 0) { - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } return retval; @@ -259,7 +256,7 @@ int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *g_buffer, if (length > MAX_BUF_SIZE) { guest_svcs_errno = ENOMEM; } else if ((retval = recv(guest_svcs_fds[sckt], buffer, length, flags)) <= 0) { - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } else { cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, retval, 1); } @@ -281,7 +278,7 @@ int32_t qc_handle_send(CPUState *cpu, int32_t sckt, void *g_buffer, cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, length, 0); if ((retval = send(guest_svcs_fds[sckt], buffer, length, flags)) < 0) { - guest_svcs_errno = convert_error(errno); + guest_svcs_errno = darwin_error(errno); } } diff --git a/include/hw/arm/guest-services/socket.h b/include/hw/arm/guest-services/socket.h index 6e727a6a4e1..b11a7c89500 100644 --- a/include/hw/arm/guest-services/socket.h +++ b/include/hw/arm/guest-services/socket.h @@ -33,9 +33,8 @@ #endif #ifdef __APPLE__ -#define S_SOCKADDR struct sockaddr -#define S_SOCKADDR_IN struct sockaddr_in -#define SOCKLEN_T socklen_t +#define SOCKADDR sockaddr +#define SOCKADDR_IN sockaddr_in #else /* __linux__ */ /* XXX: A lot of this is defined by the standard. But doesn't hurt to ensure Darwin/BSD lengths. @@ -46,23 +45,22 @@ struct in_addr { in_addr_t s_addr; }; */ + struct darwin_sockaddr { unsigned char sa_len; unsigned char sa_family; - char sa_data[14]; + char sa_data[14]; }; struct darwin_sockaddr_in { unsigned char sin_len; unsigned char sin_family; unsigned short sin_port; struct in_addr sin_addr; - char sin_zero[8]; + char sin_zero[8]; }; -typedef unsigned int darwin_socklen_t; -#define S_SOCKADDR struct darwin_sockaddr -#define S_SOCKADDR_IN struct darwin_sockaddr_in -#define SOCKLEN_T darwin_socklen_t +#define SOCKADDR darwin_sockaddr +#define SOCKADDR_IN darwin_sockaddr_in #endif #pragma GCC diagnostic push @@ -80,14 +78,14 @@ typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) { int32_t socket; - S_SOCKADDR *addr; - SOCKLEN_T *addrlen; + struct SOCKADDR *addr; + socklen_t *addrlen; } qc_accept_args_t; typedef struct __attribute__((packed)) { int32_t socket; - S_SOCKADDR *addr; - SOCKLEN_T addrlen; + struct SOCKADDR *addr; + socklen_t addrlen; } qc_bind_args_t, qc_connect_args_t; typedef struct __attribute__((packed)) { @@ -105,12 +103,12 @@ typedef struct __attribute__((packed)) { #ifndef OUT_OF_TREE_BUILD int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, int32_t protocol); -int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, S_SOCKADDR *addr, - SOCKLEN_T *addrlen); -int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, S_SOCKADDR *addr, - SOCKLEN_T addrlen); -int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, S_SOCKADDR *addr, - SOCKLEN_T addrlen); +int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct SOCKADDR *addr, + socklen_t *addrlen); +int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct SOCKADDR *addr, + socklen_t addrlen); +int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct SOCKADDR *addr, + socklen_t addrlen); int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog); int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *buffer, size_t length, int32_t flags); From 1f63f61f4ff8276845b6f3dfc9160808fc52fcdd Mon Sep 17 00:00:00 2001 From: MCApollo <34170230+MCApollo@users.noreply.github.com> Date: Wed, 26 Aug 2020 11:33:16 -0900 Subject: [PATCH 5/5] guest-socket: inherit flags from fd --- hw/arm/guest-socket.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/hw/arm/guest-socket.c b/hw/arm/guest-socket.c index a3fbc634830..56b7488f9fe 100644 --- a/hw/arm/guest-socket.c +++ b/hw/arm/guest-socket.c @@ -121,21 +121,25 @@ int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct SOCKADDR *g_addr, // TODO: timeout if (retval < 0) { guest_svcs_errno = ENOTSOCK; - } else if ((guest_svcs_fds[retval] = -#ifndef __APPLE__ - accept4(guest_svcs_fds[sckt], - (struct sockaddr *) &addr, - &addrlen, SOCK_NONBLOCK)) < 0) -#else - accept(guest_svcs_fds[sckt], + } else if ((guest_svcs_fds[retval] = accept(guest_svcs_fds[sckt], (struct sockaddr *) &addr, - &addrlen)) < 0) -#endif - { + &addrlen)) < 0) { retval = -1; guest_svcs_errno = darwin_error(errno); } else { #ifndef __APPLE__ + /* XXX: + On Linux, the new socket returned by accept() does not inherit file + status flags such as O_NONBLOCK and O_ASYNC from the listening socket. + */ + + if ((fcntl(guest_svcs_fds[retval], F_SETFL, fcntl(guest_svcs_fds[sckt], F_GETFL) | O_NONBLOCK)) < 0) { + retval = -1; + guest_svcs_errno = darwin_error(errno); + + return retval; + } + struct darwin_sockaddr_in darwin_addr = convert_sockaddr_to_darwin(addr); cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &darwin_addr, sizeof(darwin_addr), 1);