Fix grpc_sockaddr_to_uri to handle embedded nulls for unix_abstract resolved addresses (#29323)

Currently when an embedded null is present, it is left as is. This causes an issue when grpc_sockaddr_to_uri is followed by any c style operations like copy, as the string is truncated at the non-encoded null character. For example this is triggered when channel args containing a string channel arg is copied.

To prevent this properly encode the URI with %00.
reviewable/pr29111/r15
Anirudh Ramachandra 3 years ago committed by GitHub
parent ff28d4e6ae
commit 0922756050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      BUILD
  2. 22
      src/core/lib/address_utils/sockaddr_utils.cc
  3. 21
      test/core/address_utils/sockaddr_utils_test.cc

@ -1739,6 +1739,7 @@ grpc_cc_library(
"gpr_base",
"grpc_sockaddr",
"resolved_address",
"uri_parser",
],
)

@ -29,6 +29,7 @@
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_replace.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -37,6 +38,7 @@
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/uri/uri_parser.h"
#ifdef GRPC_HAVE_UNIX_SOCKET
#include <sys/un.h>
@ -52,14 +54,20 @@ static absl::StatusOr<std::string> grpc_sockaddr_to_uri_unix_if_possible(
absl::StrCat("Socket family is not AF_UNIX: ", addr->sa_family));
}
const auto* unix_addr = reinterpret_cast<const struct sockaddr_un*>(addr);
std::string scheme, path;
if (unix_addr->sun_path[0] == '\0' && unix_addr->sun_path[1] != '\0') {
return absl::StrCat(
"unix-abstract:",
absl::string_view(
unix_addr->sun_path + 1,
resolved_addr->len - sizeof(unix_addr->sun_family) - 1));
scheme = "unix-abstract";
path = std::string(unix_addr->sun_path + 1,
resolved_addr->len - sizeof(unix_addr->sun_family) - 1);
} else {
scheme = "unix";
path = unix_addr->sun_path;
}
return absl::StrCat("unix:", unix_addr->sun_path);
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Create(
std::move(scheme), /*authority=*/"", std::move(path),
/*query_parameter_pairs=*/{}, /*fragment=*/"");
if (!uri.ok()) return uri.status();
return uri->ToString();
}
#else
static absl::StatusOr<std::string> grpc_sockaddr_to_uri_unix_if_possible(
@ -263,6 +271,8 @@ absl::StatusOr<std::string> grpc_sockaddr_to_uri(
if (scheme == nullptr || strcmp("unix", scheme) == 0) {
return grpc_sockaddr_to_uri_unix_if_possible(resolved_addr);
}
// TODO(anramach): Encode the string using URI::Create() and URI::ToString()
// before returning.
auto path = grpc_sockaddr_to_string(resolved_addr, false /* normalize */);
if (!path.ok()) return path;
return absl::StrCat(scheme, ":", path.value());

@ -256,6 +256,27 @@ TEST(SockAddrUtilsTest, SockAddrToString) {
#endif
}
#ifdef GRPC_HAVE_UNIX_SOCKET
TEST(SockAddrUtilsTest, UnixSockAddrToUri) {
grpc_resolved_address addr;
ASSERT_TRUE(GRPC_ERROR_NONE ==
grpc_core::UnixSockaddrPopulate("sample-path", &addr));
EXPECT_EQ(grpc_sockaddr_to_uri(&addr).value(), "unix:sample-path");
ASSERT_TRUE(GRPC_ERROR_NONE ==
grpc_core::UnixAbstractSockaddrPopulate("no-nulls", &addr));
EXPECT_EQ(grpc_sockaddr_to_uri(&addr).value(), "unix-abstract:no-nulls");
ASSERT_TRUE(GRPC_ERROR_NONE ==
grpc_core::UnixAbstractSockaddrPopulate(
std::string("path_\0with_null", 15), &addr));
EXPECT_EQ(grpc_sockaddr_to_uri(&addr).value(),
"unix-abstract:path_%00with_null");
}
#endif /* GRPC_HAVE_UNIX_SOCKET */
TEST(SockAddrUtilsTest, SockAddrSetGetPort) {
grpc_resolved_address input4 = MakeAddr4(kIPv4, sizeof(kIPv4));
ASSERT_EQ(grpc_sockaddr_get_port(&input4), 12345);

Loading…
Cancel
Save