From 4750f361c88a8e7d2fc204d139684b5547ee0425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Su=C3=A1rez?= Date: Wed, 9 Sep 2020 15:49:37 +0200 Subject: Fix abstract unix socket name For the abstract unix socket address type, the string in the 'sun_path' field of the 'sockaddr_un' struct, is a not null-terminated string (see unix(7)). Fix the lentgh calculation of the 'sun_path' field to not add the termination null byte. --- lib/cpp/src/thrift/transport/SocketCommon.cpp | 85 ++++++++++++++++++++++ lib/cpp/src/thrift/transport/SocketCommon.h | 51 +++++++++++++ .../thrift/transport/TNonblockingServerSocket.cpp | 30 ++------ lib/cpp/src/thrift/transport/TServerSocket.cpp | 29 ++------ lib/cpp/src/thrift/transport/TSocket.cpp | 27 ++----- 5 files changed, 154 insertions(+), 68 deletions(-) create mode 100644 lib/cpp/src/thrift/transport/SocketCommon.cpp create mode 100644 lib/cpp/src/thrift/transport/SocketCommon.h (limited to 'lib/cpp/src/thrift/transport') diff --git a/lib/cpp/src/thrift/transport/SocketCommon.cpp b/lib/cpp/src/thrift/transport/SocketCommon.cpp new file mode 100644 index 000000000..570f39a93 --- /dev/null +++ b/lib/cpp/src/thrift/transport/SocketCommon.cpp @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * @author: David Suárez + */ + +#ifndef THRIFT_SOCKETCOMMON_H +#define THRIFT_SOCKETCOMMON_H + +#ifndef _WIN32 + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#include + +#include +#include +#include + +namespace apache { +namespace thrift { +namespace transport { + + +socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path) +{ + // abstract namespace socket ? + bool isAbstractNamespace = path[0] == 0; + +#ifndef __linux__ + if (isAbstractNamespace) { + GlobalOutput.perror("TSocket::open() Abstract Namespace Domain sockets only supported on linux: ", -99); + throw TTransportException(TTransportException::NOT_OPEN, + " Abstract Namespace Domain socket path not supported"); + } +#endif + + /* + * For abstract namespace sockets, the path string is not null-terminated (as opposite to path based), so we + * rely in pass the string size, to the bind() call. + */ + size_t addr_len = isAbstractNamespace ? path.size() : path.size() + 1; + + if (addr_len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { + int errno_copy = THRIFT_GET_SOCKET_ERROR; + GlobalOutput.perror("TSocket::open() Unix Domain socket path too long", errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long"); + } + + address.sun_family = AF_UNIX; + memcpy(address.sun_path, path.c_str(), addr_len); + + return static_cast(sizeof((sockaddr_un*)nullptr)->sun_family + addr_len); +} + +} +} +} // apache::thrift::transport + +#endif // _WIN32 + +#endif //THRIFT_SOCKETCOMMON_H diff --git a/lib/cpp/src/thrift/transport/SocketCommon.h b/lib/cpp/src/thrift/transport/SocketCommon.h new file mode 100644 index 000000000..78839c4e3 --- /dev/null +++ b/lib/cpp/src/thrift/transport/SocketCommon.h @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * @author: David Suárez + */ + +#ifndef THRIFT_SOCKETCOMMON_H +#define THRIFT_SOCKETCOMMON_H + +#ifndef _WIN32 + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#include + +namespace apache { +namespace thrift { +namespace transport { + +socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path); + +} +} +} // apache::thrift::transport + +#endif // _WIN32 + +#endif //THRIFT_SOCKETCOMMON_H diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp index 7bac37eb2..5ef083533 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX @@ -350,33 +351,14 @@ void TNonblockingServerSocket::listen() { _setup_sockopts(); //_setup_unixdomain_sockopts(); +/* + * TODO: seems that windows now support unix sockets, + * see: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ + */ #ifndef _WIN32 - size_t len = path_.size() + 1; - if (len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { - errno_copy = THRIFT_GET_SOCKET_ERROR; - GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy); - throw TTransportException(TTransportException::NOT_OPEN, - "Unix Domain socket path too long", - errno_copy); - } - struct sockaddr_un address; - address.sun_family = AF_UNIX; - memcpy(address.sun_path, path_.c_str(), len); - - auto structlen = static_cast(sizeof(address)); - - if (!address.sun_path[0]) { // abstract namespace socket -#ifdef __linux__ - // sun_path is not null-terminated in this case and structlen determines its length - structlen -= sizeof(address.sun_path) - len; -#else - GlobalOutput.perror("TSocket::open() Abstract Namespace Domain sockets only supported on linux: ", -99); - throw TTransportException(TTransportException::NOT_OPEN, - " Abstract Namespace Domain socket path not supported"); -#endif - } + socklen_t structlen = fillUnixSocketAddr(address, path_); do { if (0 == ::bind(serverSocket_, (struct sockaddr*)&address, structlen)) { diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index 6b7652560..5c58bda05 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX @@ -397,32 +398,14 @@ void TServerSocket::listen() { _setup_sockopts(); _setup_unixdomain_sockopts(); +/* + * TODO: seems that windows now support unix sockets, + * see: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ + */ #ifndef _WIN32 - size_t len = path_.size() + 1; - if (len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { - errno_copy = THRIFT_GET_SOCKET_ERROR; - GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy); - throw TTransportException(TTransportException::NOT_OPEN, - "Unix Domain socket path too long", - errno_copy); - } struct sockaddr_un address; - address.sun_family = AF_UNIX; - memcpy(address.sun_path, path_.c_str(), len); - - auto structlen = static_cast(sizeof(address)); - - if (!address.sun_path[0]) { // abstract namespace socket -#ifdef __linux__ - // sun_path is not null-terminated in this case and structlen determines its length - structlen -= sizeof(address.sun_path) - len; -#else - GlobalOutput.perror("TSocket::open() Abstract Namespace Domain sockets only supported on linux: ", -99); - throw TTransportException(TTransportException::NOT_OPEN, - " Abstract Namespace Domain socket path not supported"); -#endif - } + socklen_t structlen = fillUnixSocketAddr(address, path_); do { if (0 == ::bind(serverSocket_, (struct sockaddr*)&address, structlen)) { diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp index 81aaccf43..182977f45 100644 --- a/lib/cpp/src/thrift/transport/TSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSocket.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #ifndef SOCKOPT_CAST_T #ifndef _WIN32 @@ -328,30 +329,14 @@ void TSocket::openConnection(struct addrinfo* res) { int ret; if (!path_.empty()) { +/* + * TODO: seems that windows now support unix sockets, + * see: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ + */ #ifndef _WIN32 - size_t len = path_.size() + 1; - if (len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { - int errno_copy = THRIFT_GET_SOCKET_ERROR; - GlobalOutput.perror("TSocket::open() Unix Domain socket path too long", errno_copy); - throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long"); - } struct sockaddr_un address; - address.sun_family = AF_UNIX; - memcpy(address.sun_path, path_.c_str(), len); - - auto structlen = static_cast(sizeof(address)); - - if (!address.sun_path[0]) { // abstract namespace socket -#ifdef __linux__ - // sun_path is not null-terminated in this case and structlen determines its length - structlen -= sizeof(address.sun_path) - len; -#else - GlobalOutput.perror("TSocket::open() Abstract Namespace Domain sockets only supported on linux: ", -99); - throw TTransportException(TTransportException::NOT_OPEN, - " Abstract Namespace Domain socket path not supported"); -#endif - } + socklen_t structlen = fillUnixSocketAddr(address, path_); ret = connect(socket_, (struct sockaddr*)&address, structlen); #else -- cgit v1.2.1