[Pal] Fix IPv6-related failures by using sockaddr_storage

Fix IPv6 failures by increasing the sockaddr size by using
sockaddr_storage for all addresses that can be IPv6.

This now allows us to run this test here:

    ./pal_loader busybox telnet ::1 22

    SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

    Protocol mismatch.

    Connection closed by foreign host
    Connected to ::1
This commit is contained in:
Stefan Berger
2020-05-13 21:55:31 +02:00
committed by Michał Kowalczyk
parent 020e81a6bb
commit 14353a628f
2 changed files with 46 additions and 41 deletions
+26 -22
View File
@@ -78,7 +78,7 @@ static int inet_parse_uri(char** uri, struct sockaddr* addr, unsigned int* addrl
void* addr_buf;
int addr_len;
__be16* port_buf;
unsigned int slen;
size_t slen;
assert(addrlen);
@@ -323,8 +323,8 @@ static inline int sock_type(int type, int options) {
/* listen on a tcp socket */
static int tcp_listen(PAL_HANDLE* handle, char* uri, int create, int options) {
struct sockaddr buffer;
struct sockaddr* bind_addr = &buffer;
struct sockaddr_storage buffer;
struct sockaddr* bind_addr = (struct sockaddr*)&buffer;
unsigned int bind_addrlen = sizeof(buffer);
int ret;
@@ -368,8 +368,8 @@ static int tcp_accept(PAL_HANDLE handle, PAL_HANDLE* client) {
return -PAL_ERROR_BADHANDLE;
struct sockaddr* bind_addr = (struct sockaddr*)handle->sock.bind;
unsigned int bind_addrlen = addr_size(bind_addr);
struct sockaddr dest_addr;
size_t bind_addrlen = addr_size(bind_addr);
struct sockaddr_storage dest_addr;
unsigned int dest_addrlen = sizeof(dest_addr);
int ret = 0;
@@ -378,12 +378,13 @@ static int tcp_accept(PAL_HANDLE handle, PAL_HANDLE* client) {
memset(&sock_options, 0, sizeof(sock_options));
sock_options.reuseaddr = 1; /* sockets are always set as reusable in Graphene */
ret = ocall_accept(handle->sock.fd, &dest_addr, &dest_addrlen, &sock_options);
ret = ocall_accept(handle->sock.fd, (struct sockaddr*)&dest_addr, &dest_addrlen,
&sock_options);
if (IS_ERR(ret))
return unix_to_pal_error(ERRNO(ret));
*client = socket_create_handle(pal_type_tcp, ret, 0, bind_addr, bind_addrlen, &dest_addr,
dest_addrlen, &sock_options);
*client = socket_create_handle(pal_type_tcp, ret, 0, bind_addr, bind_addrlen,
(struct sockaddr*)&dest_addr, dest_addrlen, &sock_options);
if (!(*client)) {
ocall_close(ret);
@@ -395,10 +396,10 @@ static int tcp_accept(PAL_HANDLE handle, PAL_HANDLE* client) {
/* connect on a tcp socket */
static int tcp_connect(PAL_HANDLE* handle, char* uri, int options) {
struct sockaddr buffer[2];
struct sockaddr* bind_addr = &buffer[0];
struct sockaddr_storage buffer[2];
struct sockaddr* bind_addr = (struct sockaddr*)&buffer[0];
unsigned int bind_addrlen = sizeof(buffer[0]);
struct sockaddr* dest_addr = &buffer[1];
struct sockaddr* dest_addr = (struct sockaddr*)&buffer[1];
unsigned int dest_addrlen = sizeof(buffer[1]);
int ret;
@@ -517,8 +518,8 @@ static int64_t tcp_write(PAL_HANDLE handle, uint64_t offset, uint64_t len, const
/* used by 'open' operation of tcp stream for bound socket */
static int udp_bind(PAL_HANDLE* handle, char* uri, int create, int options) {
struct sockaddr buffer;
struct sockaddr* bind_addr = &buffer;
struct sockaddr_storage buffer;
struct sockaddr* bind_addr = (struct sockaddr*)&buffer;
unsigned int bind_addrlen = sizeof(buffer);
int ret = 0;
@@ -559,10 +560,10 @@ static int udp_bind(PAL_HANDLE* handle, char* uri, int create, int options) {
/* used by 'open' operation of tcp stream for connected socket */
static int udp_connect(PAL_HANDLE* handle, char* uri, int create, int options) {
struct sockaddr buffer[2];
struct sockaddr* bind_addr = &buffer[0];
struct sockaddr_storage buffer[2];
struct sockaddr* bind_addr = (struct sockaddr*)&buffer[0];
unsigned int bind_addrlen = sizeof(buffer[0]);
struct sockaddr* dest_addr = &buffer[1];
struct sockaddr* dest_addr = (struct sockaddr*)&buffer[1];
unsigned int dest_addrlen = sizeof(buffer[1]);
int ret;
@@ -658,10 +659,11 @@ static int64_t udp_receivebyaddr(PAL_HANDLE handle, uint64_t offset, uint64_t le
if (len != (uint32_t)len)
return -PAL_ERROR_INVAL;
struct sockaddr conn_addr;
struct sockaddr_storage conn_addr;
socklen_t conn_addrlen = sizeof(conn_addr);
ssize_t bytes = ocall_recv(handle->sock.fd, buf, len, &conn_addr, &conn_addrlen, NULL, NULL);
ssize_t bytes = ocall_recv(handle->sock.fd, buf, len,
(struct sockaddr*)&conn_addr, &conn_addrlen, NULL, NULL);
if (IS_ERR(bytes))
return unix_to_pal_error(ERRNO(bytes));
@@ -670,7 +672,8 @@ static int64_t udp_receivebyaddr(PAL_HANDLE handle, uint64_t offset, uint64_t le
if (!addr_uri)
return -PAL_ERROR_OVERFLOW;
int ret = inet_create_uri(addr_uri, addr + addrlen - addr_uri, &conn_addr, conn_addrlen);
int ret = inet_create_uri(addr_uri, addr + addrlen - addr_uri,
(struct sockaddr*)&conn_addr, conn_addrlen);
if (ret < 0)
return ret;
@@ -720,14 +723,15 @@ static int64_t udp_sendbyaddr(PAL_HANDLE handle, uint64_t offset, uint64_t len,
char* addrbuf = __alloca(addrlen);
memcpy(addrbuf, addr, addrlen);
struct sockaddr conn_addr;
struct sockaddr_storage conn_addr;
unsigned int conn_addrlen = sizeof(conn_addr);
int ret = inet_parse_uri(&addrbuf, &conn_addr, &conn_addrlen);
int ret = inet_parse_uri(&addrbuf, (struct sockaddr*)&conn_addr, &conn_addrlen);
if (ret < 0)
return ret;
ssize_t bytes = ocall_send(handle->sock.fd, buf, len, &conn_addr, conn_addrlen, NULL, 0);
ssize_t bytes = ocall_send(handle->sock.fd, buf, len,
(struct sockaddr*)&conn_addr, conn_addrlen, NULL, 0);
if (IS_ERR(bytes))
return unix_to_pal_error(ERRNO(bytes));
+20 -19
View File
@@ -328,8 +328,8 @@ static bool check_any_addr(struct sockaddr* addr) {
/* listen on a tcp socket */
static int tcp_listen(PAL_HANDLE* handle, char* uri, int create, int options) {
struct sockaddr buffer;
struct sockaddr* bind_addr = &buffer;
struct sockaddr_storage buffer;
struct sockaddr* bind_addr = (struct sockaddr*)&buffer;
size_t bind_addrlen = sizeof(buffer);
int ret, fd = -1;
@@ -418,8 +418,8 @@ static int tcp_accept(PAL_HANDLE handle, PAL_HANDLE* client) {
struct sockaddr* bind_addr = (struct sockaddr*)handle->sock.bind;
size_t bind_addrlen = addr_size(bind_addr);
struct sockaddr buffer;
socklen_t addrlen = sizeof(struct sockaddr);
struct sockaddr_storage buffer;
socklen_t addrlen = sizeof(buffer);
int ret = 0;
int newfd = INLINE_SYSCALL(accept4, 4, handle->sock.fd, &buffer, &addrlen, SOCK_CLOEXEC);
@@ -434,7 +434,7 @@ static int tcp_accept(PAL_HANDLE handle, PAL_HANDLE* client) {
return unix_to_pal_error(ERRNO(newfd));
}
struct sockaddr* dest_addr = &buffer;
struct sockaddr* dest_addr = (struct sockaddr*)&buffer;
size_t dest_addrlen = addrlen;
*client = socket_create_handle(pal_type_tcp, newfd, 0, bind_addr, bind_addrlen, dest_addr,
@@ -454,10 +454,10 @@ failed:
/* connect on a tcp socket */
static int tcp_connect(PAL_HANDLE* handle, char* uri, int options) {
struct sockaddr buffer[3];
struct sockaddr* bind_addr = &buffer[0];
struct sockaddr_storage buffer[3];
struct sockaddr* bind_addr = (struct sockaddr*)&buffer[0];
size_t bind_addrlen = sizeof(buffer[0]);
struct sockaddr* dest_addr = &buffer[1];
struct sockaddr* dest_addr = (struct sockaddr*)&buffer[1];
size_t dest_addrlen = sizeof(buffer[1]);
int ret, fd = -1;
@@ -509,7 +509,7 @@ static int tcp_connect(PAL_HANDLE* handle, char* uri, int options) {
if (!bind_addr) {
/* save some space to get socket address */
bind_addr = &buffer[2];
bind_addr = (struct sockaddr*)&buffer[2];
bind_addrlen = sizeof(buffer[2]);
/* call getsockname to get socket address */
@@ -626,8 +626,8 @@ static int64_t tcp_write(PAL_HANDLE handle, uint64_t offset, size_t len, const v
/* used by 'open' operation of tcp stream for bound socket */
static int udp_bind(PAL_HANDLE* handle, char* uri, int create, int options) {
struct sockaddr buffer;
struct sockaddr* bind_addr = &buffer;
struct sockaddr_storage buffer;
struct sockaddr* bind_addr = (struct sockaddr*)&buffer;
size_t bind_addrlen = sizeof(buffer);
int ret = 0, fd = -1;
@@ -693,10 +693,10 @@ failed:
/* used by 'open' operation of tcp stream for connected socket */
static int udp_connect(PAL_HANDLE* handle, char* uri, int create, int options) {
struct sockaddr buffer[2];
struct sockaddr* bind_addr = &buffer[0];
struct sockaddr_storage buffer[2];
struct sockaddr* bind_addr = (struct sockaddr*)&buffer[0];
size_t bind_addrlen = sizeof(buffer[0]);
struct sockaddr* dest_addr = &buffer[1];
struct sockaddr* dest_addr = (struct sockaddr*)&buffer[1];
size_t dest_addrlen = sizeof(buffer[1]);
int ret, fd = -1;
@@ -827,8 +827,8 @@ static int64_t udp_receivebyaddr(PAL_HANDLE handle, uint64_t offset, size_t len,
if (handle->sock.fd == PAL_IDX_POISON)
return -PAL_ERROR_BADHANDLE;
struct sockaddr conn_addr;
socklen_t conn_addrlen = sizeof(struct sockaddr);
struct sockaddr_storage conn_addr;
socklen_t conn_addrlen = sizeof(conn_addr);
struct msghdr hdr;
struct iovec iov;
@@ -851,7 +851,8 @@ static int64_t udp_receivebyaddr(PAL_HANDLE handle, uint64_t offset, size_t len,
if (!addr_uri)
return -PAL_ERROR_OVERFLOW;
int ret = inet_create_uri(addr_uri, addr + addrlen - addr_uri, &conn_addr, hdr.msg_namelen);
int ret = inet_create_uri(addr_uri, addr + addrlen - addr_uri,
(struct sockaddr*)&conn_addr, hdr.msg_namelen);
if (ret < 0)
return ret;
@@ -907,10 +908,10 @@ static int64_t udp_sendbyaddr(PAL_HANDLE handle, uint64_t offset, size_t len, co
char* addrbuf = __alloca(addrlen);
memcpy(addrbuf, addr, addrlen);
struct sockaddr conn_addr;
struct sockaddr_storage conn_addr;
size_t conn_addrlen = sizeof(conn_addr);
int ret = inet_parse_uri(&addrbuf, &conn_addr, &conn_addrlen);
int ret = inet_parse_uri(&addrbuf, (struct sockaddr*)&conn_addr, &conn_addrlen);
if (ret < 0)
return ret;